===== include/linux/netfilter_ipv4/ip_tables.h 1.12 vs edited ===== --- 1.12/include/linux/netfilter_ipv4/ip_tables.h 2004-11-02 01:39:53 +01:00 +++ edited/include/linux/netfilter_ipv4/ip_tables.h 2004-12-07 20:16:50 +01:00 @@ -53,7 +53,9 @@ u_int16_t match_size; /* Used by userspace */ - char name[IPT_FUNCTION_MAXNAMELEN]; + char name[IPT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t version; } user; struct { u_int16_t match_size; @@ -76,7 +78,9 @@ u_int16_t target_size; /* Used by userspace */ - char name[IPT_FUNCTION_MAXNAMELEN]; + char name[IPT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t version; } user; struct { u_int16_t target_size; @@ -344,7 +348,9 @@ { struct list_head list; - const char name[IPT_FUNCTION_MAXNAMELEN]; + const char name[IPT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t version; /* Return true or false: return FALSE and set *hotdrop = 1 to force immediate packet drop. */ @@ -378,7 +384,9 @@ { struct list_head list; - const char name[IPT_FUNCTION_MAXNAMELEN]; + const char name[IPT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t version; /* Called when user tries to insert an entry of this type: hook_mask is a bitmask of hooks from which it can be @@ -414,7 +422,7 @@ extern void ipt_unregister_match(struct ipt_match *match); extern struct ipt_target * -__ipt_find_target_lock(const char *name, int *error); +__ipt_find_target_lock(const char *name, const u_int8_t ver, int *error); extern void __ipt_mutex_up(void); /* Furniture shopping... */ ===== net/ipv4/netfilter/ip_tables.c 1.34 vs edited ===== --- 1.34/net/ipv4/netfilter/ip_tables.c 2004-11-16 00:00:45 +01:00 +++ edited/net/ipv4/netfilter/ip_tables.c 2004-12-07 20:07:45 +01:00 @@ -465,22 +465,133 @@ return find_inlist_lock(&ipt_tables, name, "iptable_", error, mutex); } +static struct ipt_target * +find_target(const char *name, u_int8_t version) +{ + struct list_head *i; + struct ipt_target *t; + + list_for_each(i, &ipt_target) { + t = (struct ipt_target *) i; + if (!strcmp(name, t->name) + && version == t->version) + return t; + } + return NULL; +} + +static struct ipt_match * +find_match(const char *name, u_int8_t version) +{ + struct list_head *i; + struct ipt_match *m; + + list_for_each(i, &ipt_match) { + m = (struct ipt_match *) i; + if (!strcmp(name, m->name) + && version == m->version) + return m; + } + return NULL; +} + +static int +target_insert(struct ipt_target *target) +{ + if (find_target(target->name, target->version) == NULL) { + list_prepend(&ipt_target, target); + return 1; + } + return 0; +} + +static int +match_insert(struct ipt_match *match) +{ + if (find_match(match->name, match->version) == NULL) { + list_prepend(&ipt_match, match); + return 1; + } + return 0; +} + +#define IPT_MATCH 0 +#define IPT_TARGET 1 + +static inline void * +find_inlist_tm_lock_noload(const char *name, + const u_int8_t ver, + int *error, + struct semaphore *mutex, + int type) +{ + void *ret = NULL; + + *error = down_interruptible(mutex); + if (*error != 0) + return NULL; + + switch(type) { + case IPT_MATCH: + ret = (void *) find_match(name, ver); + break; + case IPT_TARGET: + ret = (void *) find_target(name, ver); + break; + default: + /* shouldn't happen */ + break; + } + if (!ret) { + printk("find_tm_lock_noload: `%s' version=(%1x) not found!\n", name, ver); + *error = -ENOENT; + up(mutex); + } + return ret; +} + +#ifndef CONFIG_KMOD +#define find_inlist_tm_lock(n,v,p,e,m,t) find_inlist_tm_lock_noload((n),(v),(e),(m),(t)) +#else +static void * +find_inlist_tm_lock(const char *name, + const u_int8_t ver, + const char *prefix, + int *error, + struct semaphore *mutex, + int type) +{ + void *ret; + + ret = find_inlist_tm_lock_noload(name, ver, error, mutex, type); + if (!ret) { + duprintf("find_inlist: loading `%s%s'.\n", prefix, name); + request_module("%s%s", prefix, name); + ret = find_inlist_tm_lock_noload(name, ver, error, mutex,type); + } + + return ret; +} +#endif + static inline struct ipt_match * -find_match_lock(const char *name, int *error, struct semaphore *mutex) +find_match_lock(const char *name, u_int8_t ver, int *error, + struct semaphore *mutex) { - return find_inlist_lock(&ipt_match, name, "ipt_", error, mutex); + return find_inlist_tm_lock(name, ver, "ipt_", error, mutex, IPT_MATCH); } static struct ipt_target * -ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex) +ipt_find_target_lock(const char *name, const u_int8_t ver, int *error, + struct semaphore *mutex) { - return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex); + return find_inlist_tm_lock(name, ver, "ipt_", error, mutex,IPT_TARGET); } struct ipt_target * -__ipt_find_target_lock(const char *name, int *error) +__ipt_find_target_lock(const char *name, const u_int8_t ver, int *error) { - return ipt_find_target_lock(name,error,&ipt_mutex); + return ipt_find_target_lock(name,ver,error,&ipt_mutex); } void @@ -651,7 +762,8 @@ int ret; struct ipt_match *match; - match = find_match_lock(m->u.user.name, &ret, &ipt_mutex); + match = find_match_lock(m->u.user.name, m->u.user.version, &ret, + &ipt_mutex); if (!match) { duprintf("check_match: `%s' not found\n", m->u.user.name); return ret; @@ -699,7 +811,8 @@ goto cleanup_matches; t = ipt_get_target(e); - target = ipt_find_target_lock(t->u.user.name, &ret, &ipt_mutex); + target = ipt_find_target_lock(t->u.user.name, t->u.user.version, &ret, + &ipt_mutex); if (!target) { duprintf("check_entry: `%s' not found\n", t->u.user.name); goto cleanup_matches; @@ -1339,12 +1452,13 @@ if (ret != 0) return ret; - if (!list_named_insert(&ipt_target, target)) { - duprintf("ipt_register_target: `%s' already in list!\n", - target->name); - ret = -EINVAL; + if (!target_insert(target)) { + printk("ipt_register_target: `%s' already in list!\n", + target->name); + return -EINVAL; } up(&ipt_mutex); + printk("register_target: `%s' registered\n", target->name); return ret; } @@ -1365,12 +1479,13 @@ if (ret != 0) return ret; - if (!list_named_insert(&ipt_match, match)) { - duprintf("ipt_register_match: `%s' already in list!\n", - match->name); - ret = -EINVAL; + if (!match_insert(match)) { + printk("ipt_register_match: `%s' already in list!\n", + match->name); + return -EINVAL; } up(&ipt_mutex); + printk("register_match: `%s' registered\n", match->name); return ret; }