From: Pablo Neira <pablo@eurodev.net>
To: Netfilter Development Mailinglist <netfilter-devel@lists.netfilter.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Subject: [PATCH 1/2] Versioning (aka release) stuff for iptables
Date: Sat, 25 Dec 2004 22:31:43 +0100 [thread overview]
Message-ID: <41CDDC3F.2060708@eurodev.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 949 bytes --]
Hi Rusty,
I've been working on the versioning stuff last days. I've tested with
the mark target.
As I told you, I propose to add an option called --release to the
current syntax of iptables which works as follows:
a) New version of matches/targets: iptables -I INPUT -t mangle -j MARK
--release 1 --and-mark 0x1
b) Primitive version. To keep backward compatibility, the syntax is the
same, no modification: iptables -I INPUT -t mangle -j MARK --set-mark 0x1
Optionally, someone could apply this: iptables -I INPUT -t mangle -j
MARK --release 0 --set-mark 0x1
To finish, some comments about what I have in mind for next days:
1) Test this stuff in nfsim with a test case based on yours.
2) Clean up the kernel patch that I sent you some weeks ago and rename
field `version' to `release'
3) port mport match to multiport to test that versioning stuff is
working fine with matches.
4) More testing...
Please, comments welcome.
--
Pablo
[-- Attachment #2: xmas-version.patch --]
[-- Type: text/x-patch, Size: 12751 bytes --]
Index: iptables.c
===================================================================
--- iptables.c (revision 3357)
+++ iptables.c (working copy)
@@ -138,6 +138,7 @@
{ "line-numbers", 0, 0, '0' },
{ "modprobe", 1, 0, 'M' },
{ "set-counters", 1, 0, 'c' },
+ { "release", 1, 0, 'r' },
{ 0 }
};
@@ -664,12 +665,12 @@
}
struct iptables_match *
-find_match(const char *name, enum ipt_tryload tryload, struct iptables_rule_match **matches)
+find_match(const char *name, u_int8_t rel, enum ipt_tryload tryload, struct iptables_rule_match **matches)
{
struct iptables_match *ptr;
for (ptr = iptables_matches; ptr; ptr = ptr->next) {
- if (strcmp(name, ptr->name) == 0)
+ if (strcmp(name, ptr->name) == 0 && ptr->release == rel)
break;
}
@@ -681,16 +682,16 @@
if (dlopen(path, RTLD_NOW)) {
/* Found library. If it didn't register itself,
maybe they specified target as match. */
- ptr = find_match(name, DONT_LOAD, NULL);
+ ptr = find_match(name, rel, DONT_LOAD, NULL);
if (!ptr)
exit_error(PARAMETER_PROBLEM,
- "Couldn't load match `%s'\n",
- name);
+ "Couldn't load match `%s' (r.%d)\n",
+ name, rel);
} else if (tryload == LOAD_MUST_SUCCEED)
exit_error(PARAMETER_PROBLEM,
- "Couldn't load match `%s':%s\n",
- name, dlerror());
+ "Couldn't load match `%s' (r.%d):%s\n",
+ name, rel, dlerror());
}
#else
if (ptr && !ptr->loaded) {
@@ -701,7 +702,7 @@
}
if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
exit_error(PARAMETER_PROBLEM,
- "Couldn't find match `%s'\n", name);
+ "Couldn't find match `%s' (r.%d)\n", name, rel);
}
#endif
@@ -730,9 +731,10 @@
char *protoname = proto_to_name(proto, nolookup);
if (protoname)
- return find_match(protoname, tryload, matches);
+ /* standalone matches doesn't support versioning */
+ return find_match(protoname, 0, tryload, matches);
} else
- return find_match(pname, tryload, matches);
+ return find_match(pname, 0, tryload, matches);
return NULL;
}
@@ -966,7 +968,7 @@
}
struct iptables_target *
-find_target(const char *name, enum ipt_tryload tryload)
+find_target(const char *name, u_int8_t rel, enum ipt_tryload tryload)
{
struct iptables_target *ptr;
@@ -979,7 +981,7 @@
name = "standard";
for (ptr = iptables_targets; ptr; ptr = ptr->next) {
- if (strcmp(name, ptr->name) == 0)
+ if (strcmp(name, ptr->name) == 0 && ptr->release == rel)
break;
}
@@ -991,15 +993,15 @@
if (dlopen(path, RTLD_NOW)) {
/* Found library. If it didn't register itself,
maybe they specified match as a target. */
- ptr = find_target(name, DONT_LOAD);
+ ptr = find_target(name, rel, DONT_LOAD);
if (!ptr)
exit_error(PARAMETER_PROBLEM,
- "Couldn't load target `%s'\n",
- name);
+ "Couldn't load target `%s' (r.%d)\n",
+ name, rel);
} else if (tryload == LOAD_MUST_SUCCEED)
exit_error(PARAMETER_PROBLEM,
- "Couldn't load target `%s':%s\n",
- name, dlerror());
+ "Couldn't load target `%s' (r.%d):%s\n",
+ name, rel, dlerror());
}
#else
if (ptr && !ptr->loaded) {
@@ -1010,7 +1012,7 @@
}
if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
exit_error(PARAMETER_PROBLEM,
- "Couldn't find target `%s'\n", name);
+ "Couldn't find target `%s' (r.%d)\n", name, rel);
}
#endif
@@ -1055,7 +1057,7 @@
exit(1);
}
- if (find_match(me->name, DONT_LOAD, NULL)) {
+ if (find_match(me->name, me->release, DONT_LOAD, NULL)) {
fprintf(stderr, "%s: match `%s' already registered.\n",
program_name, me->name);
exit(1);
@@ -1085,7 +1087,7 @@
exit(1);
}
- if (find_target(me->name, DONT_LOAD)) {
+ if (find_target(me->name, me->release, DONT_LOAD)) {
fprintf(stderr, "%s: target `%s' already registered.\n",
program_name, me->name);
exit(1);
@@ -1185,7 +1187,7 @@
const struct ipt_ip *ip,
int numeric)
{
- struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD, NULL);
+ struct iptables_match *match = find_match(m->u.user.name, m->u.user.version, TRY_LOAD, NULL);
if (match) {
if (match->print)
@@ -1213,12 +1215,12 @@
u_int8_t flags;
char buf[BUFSIZ];
+ t = ipt_get_target((struct ipt_entry *)fw);
if (!iptc_is_chain(targname, handle))
- target = find_target(targname, TRY_LOAD);
+ target = find_target(targname, t->u.user.version, TRY_LOAD);
else
- target = find_target(IPT_STANDARD_TARGET, LOAD_MUST_SUCCEED);
+ target = find_target(IPT_STANDARD_TARGET, t->u.user.version, LOAD_MUST_SUCCEED);
- t = ipt_get_target((struct ipt_entry *)fw);
flags = fw->ip.flags;
if (format & FMT_LINENUMBERS)
@@ -1715,6 +1717,9 @@
char *protocol = NULL;
const char *modprobe = NULL;
int proto_used = 0;
+ int release = 0, match_option = 0, target_option = 0;
+ char *match_name = NULL, *target_name = NULL;
+ static struct option *old_opts;
memset(&fw, 0, sizeof(fw));
@@ -1737,7 +1742,7 @@
opterr = 0;
while ((c = getopt_long(argc, argv,
- "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
+ "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:r:xc:",
opts, NULL)) != -1) {
switch (c) {
/*
@@ -1815,7 +1820,7 @@
exit_error(PARAMETER_PROBLEM,
"chain name not allowed to start "
"with `-'\n");
- if (find_target(optarg, TRY_LOAD))
+ if (find_target(optarg, 0, TRY_LOAD))
exit_error(PARAMETER_PROBLEM,
"chain name may not clash "
"with target name\n");
@@ -1866,7 +1871,7 @@
/* iptables -p icmp -h */
if (!matches && protocol)
- find_match(protocol, TRY_LOAD, &matches);
+ find_match(protocol, 0, TRY_LOAD, &matches);
exit_printhelp(matches);
@@ -1913,19 +1918,14 @@
invert);
jumpto = parse_target(optarg);
/* TRY_LOAD (may be chain name) */
- target = find_target(jumpto, TRY_LOAD);
+ target = find_target(jumpto, 0, TRY_LOAD);
if (target) {
- size_t size;
-
- size = IPT_ALIGN(sizeof(struct ipt_entry_target))
- + target->size;
-
- target->t = fw_calloc(1, size);
- target->t->u.target_size = size;
- strcpy(target->t->u.user.name, jumpto);
- target->init(target->t, &fw.nfcache);
+ old_opts = opts;
opts = merge_options(opts, target->extra_opts, &target->option_offset);
+ target_name = jumpto;
+ target_option = 1;
+ release = 0;
}
break;
@@ -1964,24 +1964,76 @@
verbose++;
break;
- case 'm': {
- size_t size;
-
+ case 'm':
if (invert)
exit_error(PARAMETER_PROBLEM,
"unexpected ! flag before --match");
- m = find_match(optarg, LOAD_MUST_SUCCEED, &matches);
- size = IPT_ALIGN(sizeof(struct ipt_entry_match))
- + m->size;
- m->m = fw_calloc(1, size);
- m->m->u.match_size = size;
- strcpy(m->m->u.user.name, m->name);
- m->init(m->m, &fw.nfcache);
- opts = merge_options(opts, m->extra_opts, &m->option_offset);
- }
+ /* Backward compatibility: load release 0 */
+ m = find_match(optarg, release, LOAD_MUST_SUCCEED, NULL);
+
+ /* Merge option of release 0, but keep a
+ * pointer to the old structure */
+ old_opts = opts;
+ opts = merge_options(opts, m->extra_opts,
+ &m->option_offset);
+ match_name = optarg;
+ match_option = 1;
+ release = 0;
break;
+ case 'r':
+ release = atoi(optarg);
+
+ if (release < 0 || release > 256)
+ exit_error(PARAMETER_PROBLEM,
+ "release must be >= 0 and =< 255");
+
+ if (match_option) {
+ size_t s;
+
+ /* restore old options */
+ free(opts);
+ opts = old_opts;
+
+ /* load a specific release of a match */
+ m = find_match(match_name, release,
+ LOAD_MUST_SUCCEED, &matches);
+ s = IPT_ALIGN(sizeof(struct ipt_entry_match))
+ + m->size;
+ m->m = fw_calloc(1, s);
+ m->m->u.match_size = s;
+ strcpy(m->m->u.user.name, m->name);
+ m->m->u.user.version = m->release;
+ m->init(m->m, &fw.nfcache);
+ opts = merge_options(opts, m->extra_opts,
+ &m->option_offset);
+ /* reset flag */
+ match_option = 0;
+ } else if (target_option) {
+ size_t s;
+
+ /* restore old options */
+ free(opts);
+ opts = old_opts;
+
+ /* load a specific release of a target */
+ target = find_target(target_name, release, TRY_LOAD);
+
+ s = IPT_ALIGN(sizeof(struct ipt_entry_target))
+ + target->size;
+
+ target->t = fw_calloc(1, s);
+ target->t->u.target_size = s;
+ strcpy(target->t->u.user.name, target_name);
+ target->t->u.user.version = target->release;
+ target->init(target->t, &fw.nfcache);
+ opts = merge_options(opts, target->extra_opts, &target->option_offset);
+ /* reset flag */
+ target_option = 0;
+ }
+ break;
+
case 'n':
set_option(&options, OPT_NUMERIC, &fw.ip.invflags,
invert);
@@ -2056,6 +2108,41 @@
exit_tryhelp(2);
default:
+ if (match_option) {
+ /* No release specified, so use release 0 */
+ size_t s;
+
+ m = find_match(match_name, release,
+ LOAD_MUST_SUCCEED, &matches);
+ s = IPT_ALIGN(sizeof(struct ipt_entry_match))
+ + m->size;
+ m->m = fw_calloc(1, s);
+ m->m->u.match_size = s;
+ strcpy(m->m->u.user.name, m->name);
+ m->m->u.user.version = 0;
+ m->init(m->m, &fw.nfcache);
+
+ /* reset flag */
+ match_option = 0;
+ } else if (target_option) {
+ /* targets with parameters like SNAT need
+ * this stuff */
+ size_t s;
+
+ s = IPT_ALIGN(sizeof(struct ipt_entry_target))
+ + target->size;
+
+ target->t = fw_calloc(1, s);
+ target->t->u.target_size = s;
+ strcpy(target->t->u.user.name, target_name);
+ target->t->u.user.version = 0;
+ target->init(target->t, &fw.nfcache);
+
+ /* reset flag */
+ target_option = 0;
+ }
+
+
/* FIXME: This scheme doesn't allow two of the same
matches --RR */
if (!target
@@ -2135,6 +2222,23 @@
invert = FALSE;
}
+ if (target_option) {
+ /* This target has no parameters */
+ size_t s;
+
+ s = IPT_ALIGN(sizeof(struct ipt_entry_target))
+ + target->size;
+
+ target->t = fw_calloc(1, s);
+ target->t->u.target_size = s;
+ strcpy(target->t->u.user.name, target_name);
+ target->t->u.user.version = 0;
+ target->init(target->t, &fw.nfcache);
+
+ /* reset flag */
+ target_option = 0;
+ }
+
for (matchp = matches; matchp; matchp = matchp->next)
matchp->match->final_check(matchp->match->mflags);
@@ -2239,7 +2343,9 @@
|| iptc_is_chain(jumpto, *handle))) {
size_t size;
+ /* standard doesn't support versioning */
target = find_target(IPT_STANDARD_TARGET,
+ 0,
LOAD_MUST_SUCCEED);
size = sizeof(struct ipt_entry_target)
@@ -2255,7 +2361,7 @@
* We cannot know if the plugin is corrupt, non
* existant OR if the user just misspelled a
* chain. */
- find_target(jumpto, LOAD_MUST_SUCCEED);
+ find_target(jumpto, 0, LOAD_MUST_SUCCEED);
} else {
e = generate_entry(&fw, matches, target->t);
free(target->t);
Index: include/iptables.h
===================================================================
--- include/iptables.h (revision 3309)
+++ include/iptables.h (working copy)
@@ -22,8 +22,12 @@
ipt_chainlabel name;
+ /* compatible with a certain iptables version */
const char *version;
+ /* release number of this match */
+ u_int8_t release;
+
/* Size of match data. */
size_t size;
@@ -74,6 +78,8 @@
const char *version;
+ u_int8_t release;
+
/* Size of target data. */
size_t size;
@@ -143,8 +149,8 @@
LOAD_MUST_SUCCEED
};
-extern struct iptables_target *find_target(const char *name, enum ipt_tryload);
-extern struct iptables_match *find_match(const char *name, enum ipt_tryload, struct iptables_rule_match **match);
+extern struct iptables_target *find_target(const char *name, const u_int8_t version, enum ipt_tryload);
+extern struct iptables_match *find_match(const char *name, const u_int8_t version, enum ipt_tryload, struct iptables_rule_match **match);
extern int delete_chain(const ipt_chainlabel chain, int verbose,
iptc_handle_t *handle);
Index: libiptc/libiptc.c
===================================================================
--- libiptc/libiptc.c (revision 3309)
+++ libiptc/libiptc.c (working copy)
@@ -1246,7 +1246,11 @@
/* memset to all 0 for your memcmp convenience. */
memset(t->u.user.name + strlen(t->u.user.name),
0,
- FUNCTION_MAXNAMELEN - strlen(t->u.user.name));
+ FUNCTION_MAXNAMELEN - strlen(t->u.user.name) - 1);
+ /* fcuk (tm), this is what happens when you apply
+ * dirty hacks... that memset has been knocking me for
+ * hours... arrrg! --pablo
+ */
set_changed(handle);
return 1;
next reply other threads:[~2004-12-25 21:31 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-12-25 21:31 Pablo Neira [this message]
2004-12-29 6:30 ` [PATCH 1/2] Versioning (aka release) stuff for iptables Rusty Russell
2005-01-01 21:56 ` Pablo Neira
2005-01-03 9:47 ` Rusty Russell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=41CDDC3F.2060708@eurodev.net \
--to=pablo@eurodev.net \
--cc=netfilter-devel@lists.netfilter.org \
--cc=rusty@rustcorp.com.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.