Commit 5d9ed066 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Steal a Character To Create a Revision Number

Pablo Neira <pablo@eurodev.net> came up with the idea of stealing the
last byte in the (already nul-terminated) name of a target/match to
create a version.

That patch motivated me to clean up the match and target searching in
ip_tables, which makes this patch more trivial.  I also renamed
"version" to "revision" since the word "version" was used for iptables
itself.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a22405d4
...@@ -53,7 +53,9 @@ struct ipt_entry_match ...@@ -53,7 +53,9 @@ struct ipt_entry_match
u_int16_t match_size; u_int16_t match_size;
/* Used by userspace */ /* Used by userspace */
char name[IPT_FUNCTION_MAXNAMELEN]; char name[IPT_FUNCTION_MAXNAMELEN-1];
u_int8_t revision;
} user; } user;
struct { struct {
u_int16_t match_size; u_int16_t match_size;
...@@ -76,7 +78,9 @@ struct ipt_entry_target ...@@ -76,7 +78,9 @@ struct ipt_entry_target
u_int16_t target_size; u_int16_t target_size;
/* Used by userspace */ /* Used by userspace */
char name[IPT_FUNCTION_MAXNAMELEN]; char name[IPT_FUNCTION_MAXNAMELEN-1];
u_int8_t revision;
} user; } user;
struct { struct {
u_int16_t target_size; u_int16_t target_size;
...@@ -344,7 +348,9 @@ struct ipt_match ...@@ -344,7 +348,9 @@ struct ipt_match
{ {
struct list_head list; struct list_head list;
const char name[IPT_FUNCTION_MAXNAMELEN]; const char name[IPT_FUNCTION_MAXNAMELEN-1];
u_int8_t revision;
/* Return true or false: return FALSE and set *hotdrop = 1 to /* Return true or false: return FALSE and set *hotdrop = 1 to
force immediate packet drop. */ force immediate packet drop. */
...@@ -378,7 +384,9 @@ struct ipt_target ...@@ -378,7 +384,9 @@ struct ipt_target
{ {
struct list_head list; struct list_head list;
const char name[IPT_FUNCTION_MAXNAMELEN]; const char name[IPT_FUNCTION_MAXNAMELEN-1];
u_int8_t revision;
/* Called when user tries to insert an entry of this type: /* Called when user tries to insert an entry of this type:
hook_mask is a bitmask of hooks from which it can be hook_mask is a bitmask of hooks from which it can be
......
...@@ -430,34 +430,62 @@ static inline struct ipt_table *find_table_lock(const char *name) ...@@ -430,34 +430,62 @@ static inline struct ipt_table *find_table_lock(const char *name)
return NULL; return NULL;
} }
/* Find match by name, grabs mutex & ref. Returns ERR_PTR() on error. */ /* Find match, grabs mutex & ref. Returns ERR_PTR() on error. */
static inline struct ipt_match *find_match_lock(const char *name) static inline struct ipt_match *find_match_lock(const char *name, u8 revision)
{ {
struct ipt_match *m; struct ipt_match *m;
int found = 0;
if (down_interruptible(&ipt_mutex) != 0) if (down_interruptible(&ipt_mutex) != 0)
return ERR_PTR(-EINTR); return ERR_PTR(-EINTR);
list_for_each_entry(m, &ipt_match, list) list_for_each_entry(m, &ipt_match, list) {
if (strcmp(m->name, name) == 0 && try_module_get(m->me)) if (strcmp(m->name, name) == 0) {
return m; found = 1;
if (m->revision == revision) {
if (!try_module_get(m->me))
found = 0;
else
return m;
}
}
}
up(&ipt_mutex); up(&ipt_mutex);
return NULL;
/* Not found at all? NULL so try_then_request_module loads module. */
if (!found)
return NULL;
return ERR_PTR(-EPROTOTYPE);
} }
/* Find target by name, grabs mutex & ref. Returns ERR_PTR() on error. */ /* Find target, grabs mutex & ref. Returns ERR_PTR() on error. */
static inline struct ipt_target *find_target_lock(const char *name) static inline struct ipt_target *find_target_lock(const char *name, u8 revision)
{ {
struct ipt_target *t; struct ipt_target *t;
int found = 0;
if (down_interruptible(&ipt_mutex) != 0) if (down_interruptible(&ipt_mutex) != 0)
return ERR_PTR(-EINTR); return ERR_PTR(-EINTR);
list_for_each_entry(t, &ipt_target, list) list_for_each_entry(t, &ipt_target, list) {
if (strcmp(t->name, name) == 0 && try_module_get(t->me)) if (strcmp(t->name, name) == 0) {
return t; found = 1;
if (t->revision == revision) {
if (!try_module_get(t->me))
found = 0;
else
return t;
}
}
}
up(&ipt_mutex); up(&ipt_mutex);
return NULL;
/* Not found at all? NULL so try_then_request_module loads module. */
if (!found)
return NULL;
return ERR_PTR(-EPROTOTYPE);
} }
/* All zeroes == unconditional rule. */ /* All zeroes == unconditional rule. */
...@@ -621,7 +649,8 @@ check_match(struct ipt_entry_match *m, ...@@ -621,7 +649,8 @@ check_match(struct ipt_entry_match *m,
{ {
struct ipt_match *match; struct ipt_match *match;
match = try_then_request_module(find_match_lock(m->u.user.name), match = try_then_request_module(find_match_lock(m->u.user.name,
m->u.user.revision),
"ipt_%s", m->u.user.name); "ipt_%s", m->u.user.name);
if (IS_ERR(match) || !match) { if (IS_ERR(match) || !match) {
duprintf("check_match: `%s' not found\n", m->u.user.name); duprintf("check_match: `%s' not found\n", m->u.user.name);
...@@ -666,7 +695,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, ...@@ -666,7 +695,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
goto cleanup_matches; goto cleanup_matches;
t = ipt_get_target(e); t = ipt_get_target(e);
target = try_then_request_module(find_target_lock(t->u.user.name), target = try_then_request_module(find_target_lock(t->u.user.name,
t->u.user.revision),
"ipt_%s", t->u.user.name); "ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) { if (IS_ERR(target) || !target) {
duprintf("check_entry: `%s' not found\n", t->u.user.name); duprintf("check_entry: `%s' not found\n", t->u.user.name);
...@@ -1303,12 +1333,7 @@ ipt_register_target(struct ipt_target *target) ...@@ -1303,12 +1333,7 @@ ipt_register_target(struct ipt_target *target)
ret = down_interruptible(&ipt_mutex); ret = down_interruptible(&ipt_mutex);
if (ret != 0) if (ret != 0)
return ret; return ret;
list_add(&target->list, &ipt_target);
if (!list_named_insert(&ipt_target, target)) {
duprintf("ipt_register_target: `%s' already in list!\n",
target->name);
ret = -EINVAL;
}
up(&ipt_mutex); up(&ipt_mutex);
return ret; return ret;
} }
...@@ -1330,11 +1355,7 @@ ipt_register_match(struct ipt_match *match) ...@@ -1330,11 +1355,7 @@ ipt_register_match(struct ipt_match *match)
if (ret != 0) if (ret != 0)
return ret; return ret;
if (!list_named_insert(&ipt_match, match)) { list_add(&match->list, &ipt_match);
duprintf("ipt_register_match: `%s' already in list!\n",
match->name);
ret = -EINVAL;
}
up(&ipt_mutex); up(&ipt_mutex);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment