linux-old/net/ipv4/ip_masq_mod.c
<<
>>
Prefs
   1/*
   2 *              IP_MASQ_MOD masq modules support
   3 *
   4 *
   5 * Author:      Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
   6 *
   7 *      $Id: ip_masq_mod.c,v 1.5 1998/08/29 23:51:09 davem Exp $
   8 *
   9 *      This program is free software; you can redistribute it and/or
  10 *      modify it under the terms of the GNU General Public License
  11 *      as published by the Free Software Foundation; either version
  12 *      2 of the License, or (at your option) any later version.
  13 *
  14 * Changes:
  15 *              Cyrus Durgin:           fixed kerneld stuff for kmod.
  16 */
  17
  18#include <linux/config.h>
  19#include <linux/module.h>
  20#include <linux/types.h>
  21#include <linux/kernel.h>
  22#include <linux/errno.h>
  23#include <net/ip_masq.h>
  24#include <net/ip_masq_mod.h>
  25
  26#include <linux/ip_masq.h>
  27#ifdef CONFIG_KMOD
  28#include <linux/kmod.h>
  29#endif
  30
  31EXPORT_SYMBOL(register_ip_masq_mod);
  32EXPORT_SYMBOL(unregister_ip_masq_mod);
  33EXPORT_SYMBOL(ip_masq_mod_lkp_link);
  34EXPORT_SYMBOL(ip_masq_mod_lkp_unlink);
  35
  36#ifdef __SMP__
  37static spinlock_t masq_mod_lock = SPIN_LOCK_UNLOCKED;
  38#endif
  39
  40/*
  41 *      Base pointer for registered modules
  42 */
  43struct ip_masq_mod * ip_masq_mod_reg_base = NULL;
  44
  45/*
  46 *      Base pointer for lookup (subset of above, a module could be
  47 *      registered, but it could have no active rule); will avoid
  48 *      unnecessary lookups.
  49 */
  50struct ip_masq_mod * ip_masq_mod_lkp_base = NULL;
  51
  52int ip_masq_mod_register_proc(struct ip_masq_mod *mmod)
  53{
  54#ifdef CONFIG_PROC_FS        
  55        int ret;
  56
  57        struct proc_dir_entry *ent = mmod->mmod_proc_ent;
  58
  59        if (!ent) 
  60                return 0;
  61        if (!ent->name) {
  62                ent->name = mmod->mmod_name;
  63                ent->namelen = strlen (mmod->mmod_name);
  64        }
  65        ret = ip_masq_proc_register(ent);
  66        if (ret) mmod->mmod_proc_ent = NULL;
  67
  68        return ret;
  69#else
  70        return 0;
  71#endif
  72}
  73
  74void ip_masq_mod_unregister_proc(struct ip_masq_mod *mmod)
  75{
  76#ifdef CONFIG_PROC_FS        
  77        struct proc_dir_entry *ent = mmod->mmod_proc_ent;
  78        if (!ent)
  79                return;
  80        ip_masq_proc_unregister(ent);
  81#endif
  82}
  83
  84/*
  85 *      Link/unlink object for lookups
  86 */
  87
  88int ip_masq_mod_lkp_unlink(struct ip_masq_mod *mmod)
  89{
  90        struct ip_masq_mod **mmod_p;
  91
  92        write_lock_bh(&masq_mod_lock);
  93
  94        for (mmod_p = &ip_masq_mod_lkp_base; *mmod_p ; mmod_p = &(*mmod_p)->next)
  95                if (mmod == (*mmod_p))  {
  96                        *mmod_p = mmod->next;
  97                        mmod->next = NULL;
  98                        write_unlock_bh(&masq_mod_lock);
  99                        return 0;
 100                }
 101
 102        write_unlock_bh(&masq_mod_lock);
 103        return -EINVAL;
 104}
 105
 106int ip_masq_mod_lkp_link(struct ip_masq_mod *mmod)
 107{
 108        write_lock_bh(&masq_mod_lock);
 109
 110        mmod->next = ip_masq_mod_lkp_base;
 111        ip_masq_mod_lkp_base=mmod;
 112
 113        write_unlock_bh(&masq_mod_lock);
 114        return 0;
 115}
 116
 117int register_ip_masq_mod(struct ip_masq_mod *mmod)
 118{
 119        if (!mmod) {
 120                IP_MASQ_ERR("register_ip_masq_mod(): NULL arg\n");
 121                return -EINVAL;
 122        }
 123        if (!mmod->mmod_name) {
 124                IP_MASQ_ERR("register_ip_masq_mod(): NULL mmod_name\n");
 125                return -EINVAL;
 126        }
 127        ip_masq_mod_register_proc(mmod);
 128
 129        mmod->next_reg = ip_masq_mod_reg_base;
 130        ip_masq_mod_reg_base=mmod;
 131
 132        return 0;
 133}
 134
 135int unregister_ip_masq_mod(struct ip_masq_mod *mmod)
 136{
 137        struct ip_masq_mod **mmod_p;
 138
 139        if (!mmod) {
 140                IP_MASQ_ERR( "unregister_ip_masq_mod(): NULL arg\n");
 141                return -EINVAL;
 142        }
 143
 144        /*
 145         *      Only allow unregistration if it is not referenced
 146         */
 147        if (atomic_read(&mmod->refcnt))  {
 148                IP_MASQ_ERR( "unregister_ip_masq_mod(): is in use by %d guys. failed\n",
 149                                atomic_read(&mmod->refcnt));
 150                return -EINVAL;
 151        }
 152
 153        /*      
 154         *      Must be already unlinked from lookup list
 155         */
 156        if (mmod->next) {
 157                IP_MASQ_WARNING("MASQ: unregistering \"%s\" while in lookup list.fixed.",
 158                        mmod->mmod_name);
 159                ip_masq_mod_lkp_unlink(mmod);
 160        }
 161
 162        for (mmod_p = &ip_masq_mod_reg_base; *mmod_p ; mmod_p = &(*mmod_p)->next_reg)
 163                if (mmod == (*mmod_p))  {
 164                        ip_masq_mod_unregister_proc(mmod);
 165                        *mmod_p = mmod->next_reg;
 166                        return 0;
 167                }
 168
 169        IP_MASQ_ERR("unregister_ip_masq_mod(%s): not linked \n", mmod->mmod_name);
 170        return -EINVAL;
 171}
 172
 173int ip_masq_mod_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
 174{
 175        struct ip_masq_mod *mmod;
 176        int ret = IP_MASQ_MOD_NOP;
 177
 178        for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 179                if (!mmod->mmod_in_rule) continue;
 180                switch (ret=mmod->mmod_in_rule(skb, iph)) {
 181                        case IP_MASQ_MOD_NOP:
 182                                continue;
 183                        case IP_MASQ_MOD_ACCEPT:
 184                        case IP_MASQ_MOD_REJECT:
 185                                goto out;
 186                }
 187        }
 188out:
 189        return ret;
 190}
 191
 192int ip_masq_mod_out_rule(const struct sk_buff *skb, const struct iphdr *iph)
 193{
 194        struct ip_masq_mod *mmod;
 195        int ret = IP_MASQ_MOD_NOP;
 196
 197        for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 198                if (!mmod->mmod_out_rule) continue;
 199                switch (ret=mmod->mmod_out_rule(skb, iph)) {
 200                        case IP_MASQ_MOD_NOP:
 201                                continue;
 202                        case IP_MASQ_MOD_ACCEPT:
 203                        case IP_MASQ_MOD_REJECT:
 204                                goto out;
 205                }
 206        }
 207out:
 208        return ret;
 209}
 210
 211struct ip_masq * ip_masq_mod_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
 212{
 213        struct ip_masq_mod *mmod;
 214        struct ip_masq *ms = NULL;
 215
 216        for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 217                if (!mmod->mmod_in_create) continue;
 218                if ((ms=mmod->mmod_in_create(skb, iph, maddr))) {
 219                        goto out;
 220                }
 221        }
 222out:
 223        return ms;
 224}
 225
 226struct ip_masq * ip_masq_mod_out_create(const struct sk_buff *skb, const struct iphdr *iph,  __u32 maddr)
 227{
 228        struct ip_masq_mod *mmod;
 229        struct ip_masq *ms = NULL;
 230
 231        for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 232                if (!mmod->mmod_out_create) continue;
 233                if ((ms=mmod->mmod_out_create(skb, iph, maddr))) {
 234                        goto out;
 235                }
 236        }
 237out:
 238        return ms;
 239}
 240
 241int ip_masq_mod_in_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
 242{
 243        struct ip_masq_mod *mmod;
 244        int ret = IP_MASQ_MOD_NOP;
 245
 246        for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 247                if (!mmod->mmod_in_update) continue;
 248                switch (ret=mmod->mmod_in_update(skb, iph, ms)) {
 249                        case IP_MASQ_MOD_NOP:
 250                                continue;
 251                        case IP_MASQ_MOD_ACCEPT:
 252                        case IP_MASQ_MOD_REJECT:
 253                                goto out;
 254                }
 255        }
 256out:
 257        return ret;
 258}
 259
 260int ip_masq_mod_out_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
 261{
 262        struct ip_masq_mod *mmod;
 263        int ret = IP_MASQ_MOD_NOP;
 264
 265        for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 266                if (!mmod->mmod_out_update) continue;
 267                switch (ret=mmod->mmod_out_update(skb, iph, ms)) {
 268                        case IP_MASQ_MOD_NOP:
 269                                continue;
 270                        case IP_MASQ_MOD_ACCEPT:
 271                        case IP_MASQ_MOD_REJECT:
 272                                goto out;
 273                }
 274        }
 275out:
 276        return ret;
 277}
 278
 279struct ip_masq_mod * ip_masq_mod_getbyname(const char *mmod_name)
 280{
 281        struct ip_masq_mod * mmod;
 282
 283        IP_MASQ_DEBUG(1, "searching mmod_name \"%s\"\n", mmod_name);
 284        
 285        for (mmod=ip_masq_mod_reg_base; mmod ; mmod=mmod->next_reg) {
 286                if (mmod->mmod_ctl && *(mmod_name)
 287                                && (strcmp(mmod_name, mmod->mmod_name)==0)) {
 288                        /* HIT */
 289                        return mmod;
 290                }
 291        }
 292        return NULL;
 293}
 294
 295/*
 296 *      Module control entry
 297 */
 298int ip_masq_mod_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
 299{
 300        struct ip_masq_mod * mmod;
 301#ifdef CONFIG_KMOD
 302        char kmod_name[IP_MASQ_TNAME_MAX+8];
 303#endif
 304        /* tappo */
 305        mctl->m_tname[IP_MASQ_TNAME_MAX-1] = 0;
 306
 307        mmod = ip_masq_mod_getbyname(mctl->m_tname);
 308        if (mmod)
 309                return mmod->mmod_ctl(optname, mctl, optlen);
 310#ifdef CONFIG_KMOD
 311        sprintf(kmod_name,"ip_masq_%s", mctl->m_tname);
 312
 313        IP_MASQ_DEBUG(1, "About to request \"%s\" module\n", kmod_name);
 314
 315        /* 
 316         *      Let sleep for a while ...
 317         */
 318        request_module(kmod_name);
 319        mmod = ip_masq_mod_getbyname(mctl->m_tname);
 320        if (mmod)
 321                return mmod->mmod_ctl(optname, mctl, optlen);
 322#endif
 323        return ESRCH;
 324}
 325
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.