From 931d388ff33dee589bc00e4f9033be5ca7c43786 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 9 Jun 2011 15:24:49 +0200 Subject: doc: include matches/targets in manpage again Evil sed did not throw any warning whatsoever when it cannot find the file. Signed-off-by: Jan Engelhardt --- iptables/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iptables/Makefile.am b/iptables/Makefile.am index 13cca9c6..a0682788 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -51,10 +51,10 @@ v6_sbin_links = ip6tables ip6tables-restore ip6tables-save endif iptables.8: ${srcdir}/iptables.8.in ../extensions/matches4.man ../extensions/targets4.man - ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r extensions/matches4.man' -e '/@TARGET@/ r extensions/targets4.man' $< >$@; + ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches4.man' -e '/@TARGET@/ r ../extensions/targets4.man' $< >$@; ip6tables.8: ${srcdir}/ip6tables.8.in ../extensions/matches6.man ../extensions/targets6.man - ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r extensions/matches6.man' -e '/@TARGET@/ r extensions/targets6.man' $< >$@; + ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches6.man' -e '/@TARGET@/ r ../extensions/targets6.man' $< >$@; pkgconfig_DATA = xtables.pc -- cgit v1.2.3 From 3b7a22b44d74b9b05d5e4b0529ebf72c49dcbff5 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Fri, 17 Jun 2011 05:46:22 +0200 Subject: doc: document IPv6 TOS mangling bug in old Linux kernels In Linux kernels up to and including 2.6.38, with the exception of longterm releases 2.6.32.42 (or later) and 2.6.33.15 (or later), there is a bug (*) whereby IPv6 TOS mangling does not behave as documented and differs from the IPv4 version. The TOS mask indicates the bits one wants to zero out, so it needs to be inverted before applying it to the original TOS field. However, the aformentioned kernels forgo the inversion which breaks --set-tos and its mnemonics. (*) Fixed by upstream commit: 1ed2f73d90fb49bcf5704aee7e9084adb882bfc5 (netfilter: IPv6: fix DSCP mangle code) Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: Patrick McHardy --- extensions/libxt_TOS.man | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/extensions/libxt_TOS.man b/extensions/libxt_TOS.man index 46f67379..f9896740 100644 --- a/extensions/libxt_TOS.man +++ b/extensions/libxt_TOS.man @@ -4,24 +4,33 @@ shares the same bits as DSCP and ECN. The TOS target is only valid in the \fBmangle\fP table. .TP \fB\-\-set\-tos\fP \fIvalue\fP[\fB/\fP\fImask\fP] -Zeroes out the bits given by \fImask\fP and XORs \fIvalue\fP into the -TOS/Priority field. If \fImask\fP is omitted, 0xFF is assumed. +Zeroes out the bits given by \fImask\fP (see NOTE below) and XORs \fIvalue\fP +into the TOS/Priority field. If \fImask\fP is omitted, 0xFF is assumed. .TP \fB\-\-set\-tos\fP \fIsymbol\fP You can specify a symbolic name when using the TOS target for IPv4. It implies -a mask of 0xFF. The list of recognized TOS names can be obtained by calling -iptables with \fB\-j TOS \-h\fP. +a mask of 0xFF (see NOTE below). The list of recognized TOS names can be +obtained by calling iptables with \fB\-j TOS \-h\fP. .PP The following mnemonics are available: .TP \fB\-\-and\-tos\fP \fIbits\fP Binary AND the TOS value with \fIbits\fP. (Mnemonic for \fB\-\-set\-tos -0/\fP\fIinvbits\fP, where \fIinvbits\fP is the binary negation of \fIbits\fP.) +0/\fP\fIinvbits\fP, where \fIinvbits\fP is the binary negation of \fIbits\fP. +See NOTE below.) .TP \fB\-\-or\-tos\fP \fIbits\fP Binary OR the TOS value with \fIbits\fP. (Mnemonic for \fB\-\-set\-tos\fP -\fIbits\fP\fB/\fP\fIbits\fP.) +\fIbits\fP\fB/\fP\fIbits\fP. See NOTE below.) .TP \fB\-\-xor\-tos\fP \fIbits\fP Binary XOR the TOS value with \fIbits\fP. (Mnemonic for \fB\-\-set\-tos\fP -\fIbits\fP\fB/0\fP.) +\fIbits\fP\fB/0\fP. See NOTE below.) +.PP +NOTE: In Linux kernels up to and including 2.6.38, with the exception of +longterm releases 2.6.32.42 (or later) and 2.6.33.15 (or later), there is a bug +whereby IPv6 TOS mangling does not behave as documented and differs from the +IPv4 version. The TOS mask indicates the bits one wants to zero out, so it needs +to be inverted before applying it to the original TOS field. However, the +aformentioned kernels forgo the inversion which breaks --set-tos and its +mnemonics. -- cgit v1.2.3 From 4e98e81ecdcc321d232edc42fac168d257e712ff Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 21 Jun 2011 17:00:45 +0200 Subject: libipt_LOG: fix ignoring all but last flags Signed-off-by: Jan Engelhardt --- extensions/libip6t_LOG.c | 10 +++++----- extensions/libipt_LOG.c | 10 +++++----- tests/options-most.rules | 2 ++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/extensions/libip6t_LOG.c b/extensions/libip6t_LOG.c index a419ec91..2b1ae289 100644 --- a/extensions/libip6t_LOG.c +++ b/extensions/libip6t_LOG.c @@ -87,19 +87,19 @@ static void LOG_parse(struct xt_option_call *cb) "Newlines not allowed in --log-prefix"); break; case O_LOG_TCPSEQ: - info->logflags = IP6T_LOG_TCPSEQ; + info->logflags |= IP6T_LOG_TCPSEQ; break; case O_LOG_TCPOPTS: - info->logflags = IP6T_LOG_TCPOPT; + info->logflags |= IP6T_LOG_TCPOPT; break; case O_LOG_IPOPTS: - info->logflags = IP6T_LOG_IPOPT; + info->logflags |= IP6T_LOG_IPOPT; break; case O_LOG_UID: - info->logflags = IP6T_LOG_UID; + info->logflags |= IP6T_LOG_UID; break; case O_LOG_MAC: - info->logflags = IP6T_LOG_MACDECODE; + info->logflags |= IP6T_LOG_MACDECODE; break; } } diff --git a/extensions/libipt_LOG.c b/extensions/libipt_LOG.c index b270bcf6..77f16d19 100644 --- a/extensions/libipt_LOG.c +++ b/extensions/libipt_LOG.c @@ -87,19 +87,19 @@ static void LOG_parse(struct xt_option_call *cb) "Newlines not allowed in --log-prefix"); break; case O_LOG_TCPSEQ: - info->logflags = IPT_LOG_TCPSEQ; + info->logflags |= IPT_LOG_TCPSEQ; break; case O_LOG_TCPOPTS: - info->logflags = IPT_LOG_TCPOPT; + info->logflags |= IPT_LOG_TCPOPT; break; case O_LOG_IPOPTS: - info->logflags = IPT_LOG_IPOPT; + info->logflags |= IPT_LOG_IPOPT; break; case O_LOG_UID: - info->logflags = IPT_LOG_UID; + info->logflags |= IPT_LOG_UID; break; case O_LOG_MAC: - info->logflags = IPT_LOG_MACDECODE; + info->logflags |= IPT_LOG_MACDECODE; break; } } diff --git a/tests/options-most.rules b/tests/options-most.rules index 6c4a8313..13ee9873 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -146,6 +146,8 @@ -A matches -A matches -m rt --rt-segsleft 5:4294967295 -A matches +-A ntarg -j LOG --log-tcp-sequence --log-tcp-options --log-ip-options +-A ntarg -A ntarg -j NFQUEUE --queue-num 1 -A ntarg -A ntarg -j NFQUEUE --queue-balance 8:99 -- cgit v1.2.3 From 68818f746bf9c68de04a75fbe756bf2c73e0fb32 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 21 Jun 2011 14:20:15 +0200 Subject: libxt_RATEEST: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_RATEEST.c | 94 +++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 64 deletions(-) diff --git a/extensions/libxt_RATEEST.c b/extensions/libxt_RATEEST.c index 6369e9e4..b928b339 100644 --- a/extensions/libxt_RATEEST.c +++ b/extensions/libxt_RATEEST.c @@ -1,9 +1,6 @@ -#include #include #include #include -#include -#include #include #include @@ -11,7 +8,6 @@ #include /* hack to pass raw values to final_check */ -static struct xt_rateest_target_info *RATEEST_info; static unsigned int interval; static unsigned int ewma_log; @@ -25,18 +21,23 @@ RATEEST_help(void) " --rateest-ewmalog value Rate measurement averaging time constant\n"); } -enum RATEEST_options { - RATEEST_OPT_NAME, - RATEEST_OPT_INTERVAL, - RATEEST_OPT_EWMALOG, +enum { + O_NAME = 0, + O_INTERVAL, + O_EWMALOG, }; -static const struct option RATEEST_opts[] = { - {.name = "rateest-name", .has_arg = true, .val = RATEEST_OPT_NAME}, - {.name = "rateest-interval", .has_arg = true, .val = RATEEST_OPT_INTERVAL}, - {.name = "rateest-ewmalog", .has_arg = true, .val = RATEEST_OPT_EWMALOG}, - XT_GETOPT_TABLEEND, +#define s struct xt_rateest_target_info +static const struct xt_option_entry RATEEST_opts[] = { + {.name = "rateest-name", .id = O_NAME, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name)}, + {.name = "rateest-interval", .id = O_INTERVAL, .type = XTTYPE_STRING, + .flags = XTOPT_MAND}, + {.name = "rateest-ewmalog", .id = O_EWMALOG, .type = XTTYPE_STRING, + .flags = XTOPT_MAND}, + XTOPT_TABLEEND, }; +#undef s /* Copied from iproute */ #define TIME_UNITS_PER_SEC 1000000 @@ -82,63 +83,28 @@ RATEEST_print_time(unsigned int time) printf(" %uus", time); } -static int -RATEEST_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void RATEEST_parse(struct xt_option_call *cb) { - struct xt_rateest_target_info *info = (void *)(*target)->data; - - RATEEST_info = info; - - switch (c) { - case RATEEST_OPT_NAME: - if (*flags & (1 << c)) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_INTERVAL: + if (RATEEST_get_time(&interval, cb->arg) < 0) xtables_error(PARAMETER_PROBLEM, - "RATEEST: can't specify --rateest-name twice"); - *flags |= 1 << c; - - strncpy(info->name, optarg, sizeof(info->name) - 1); + "RATEEST: bad interval value \"%s\"", + cb->arg); break; - - case RATEEST_OPT_INTERVAL: - if (*flags & (1 << c)) + case O_EWMALOG: + if (RATEEST_get_time(&ewma_log, cb->arg) < 0) xtables_error(PARAMETER_PROBLEM, - "RATEEST: can't specify --rateest-interval twice"); - *flags |= 1 << c; - - if (RATEEST_get_time(&interval, optarg) < 0) - xtables_error(PARAMETER_PROBLEM, - "RATEEST: bad interval value `%s'", optarg); - - break; - - case RATEEST_OPT_EWMALOG: - if (*flags & (1 << c)) - xtables_error(PARAMETER_PROBLEM, - "RATEEST: can't specify --rateest-ewmalog twice"); - *flags |= 1 << c; - - if (RATEEST_get_time(&ewma_log, optarg) < 0) - xtables_error(PARAMETER_PROBLEM, - "RATEEST: bad ewmalog value `%s'", optarg); - + "RATEEST: bad ewmalog value \"%s\"", + cb->arg); break; } - - return 1; } -static void -RATEEST_final_check(unsigned int flags) +static void RATEEST_final_check(struct xt_fcheck_call *cb) { - struct xt_rateest_target_info *info = RATEEST_info; - - if (!(flags & (1 << RATEEST_OPT_NAME))) - xtables_error(PARAMETER_PROBLEM, "RATEEST: no name specified"); - if (!(flags & (1 << RATEEST_OPT_INTERVAL))) - xtables_error(PARAMETER_PROBLEM, "RATEEST: no interval specified"); - if (!(flags & (1 << RATEEST_OPT_EWMALOG))) - xtables_error(PARAMETER_PROBLEM, "RATEEST: no ewmalog specified"); + struct xt_rateest_target_info *info = cb->data; for (info->interval = 0; info->interval <= 5; info->interval++) { if (interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4)) @@ -199,11 +165,11 @@ static struct xtables_target rateest_tg_reg = { .size = XT_ALIGN(sizeof(struct xt_rateest_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_rateest_target_info)), .help = RATEEST_help, - .parse = RATEEST_parse, - .final_check = RATEEST_final_check, + .x6_parse = RATEEST_parse, + .x6_fcheck = RATEEST_final_check, .print = RATEEST_print, .save = RATEEST_save, - .extra_opts = RATEEST_opts, + .x6_options = RATEEST_opts, }; void _init(void) -- cgit v1.2.3 From 14190986f87301b18bcc473c842bd82d778d87a2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 18 Jun 2011 21:18:29 +0200 Subject: iptables: consolidate target/match init call This is useful for the upcoming patch about per-instance auxiliary data. Signed-off-by: Jan Engelhardt --- iptables/ip6tables.c | 9 +++------ iptables/iptables.c | 10 ++++------ iptables/xshared.c | 15 +++++++++++++-- iptables/xshared.h | 2 ++ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 4037acfb..d13744ca 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1288,8 +1288,7 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t->u.target_size = size; strcpy(cs->target->t->u.user.name, cs->jumpto); cs->target->t->u.user.revision = cs->target->revision; - if (cs->target->init != NULL) - cs->target->init(cs->target->t); + xs_init_target(cs->target); if (cs->target->x6_options != NULL) opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts, cs->target->x6_options, @@ -1317,8 +1316,7 @@ static void command_match(struct iptables_command_state *cs) m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); + xs_init_match(m); if (m == m->next) return; /* Merge options for non-cloned matches */ @@ -1839,8 +1837,7 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand cs.target->t = xtables_calloc(1, size); cs.target->t->u.target_size = size; strcpy(cs.target->t->u.user.name, cs.jumpto); - if (cs.target->init != NULL) - cs.target->init(cs.target->t); + xs_init_target(cs.target); } if (!cs.target) { diff --git a/iptables/iptables.c b/iptables/iptables.c index 4ae75419..477e8f1d 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1315,8 +1315,8 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t->u.target_size = size; strcpy(cs->target->t->u.user.name, cs->jumpto); cs->target->t->u.user.revision = cs->target->revision; - if (cs->target->init != NULL) - cs->target->init(cs->target->t); + xs_init_target(cs->target); + if (cs->target->x6_options != NULL) opts = xtables_options_xfrm(iptables_globals.orig_opts, opts, cs->target->x6_options, @@ -1344,8 +1344,7 @@ static void command_match(struct iptables_command_state *cs) m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); + xs_init_match(m); if (m == m->next) return; /* Merge options for non-cloned matches */ @@ -1871,8 +1870,7 @@ int do_command4(int argc, char *argv[], char **table, struct iptc_handle **handl strcpy(cs.target->t->u.user.name, cs.jumpto); if (!iptc_is_chain(cs.jumpto, *handle)) cs.target->t->u.user.revision = cs.target->revision; - if (cs.target->init != NULL) - cs.target->init(cs.target->t); + xs_init_target(cs.target); } if (!cs.target) { diff --git a/iptables/xshared.c b/iptables/xshared.c index 0e3857bb..55ce5504 100644 --- a/iptables/xshared.c +++ b/iptables/xshared.c @@ -145,8 +145,7 @@ int command_default(struct iptables_command_state *cs, m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); m->m->u.user.revision = m->revision; - if (m->init != NULL) - m->init(m->m); + xs_init_match(m); if (m->x6_options != NULL) gl->opts = xtables_options_xfrm(gl->orig_opts, @@ -207,3 +206,15 @@ int subcmd_main(int argc, char **argv, const struct subcommand *cb) fprintf(stderr, " * %s\n", cb->name); exit(EXIT_FAILURE); } + +void xs_init_target(struct xtables_target *target) +{ + if (target->init != NULL) + target->init(target->t); +} + +void xs_init_match(struct xtables_match *match) +{ + if (match->init != NULL) + match->init(match->m); +} diff --git a/iptables/xshared.h b/iptables/xshared.h index b44a3a35..b804aafe 100644 --- a/iptables/xshared.h +++ b/iptables/xshared.h @@ -81,6 +81,8 @@ extern int command_default(struct iptables_command_state *, struct xtables_globals *); extern struct xtables_match *load_proto(struct iptables_command_state *); extern int subcmd_main(int, char **, const struct subcommand *); +extern void xs_init_target(struct xtables_target *); +extern void xs_init_match(struct xtables_match *); extern const struct xtables_afinfo *afinfo; -- cgit v1.2.3 From 2dba676b68ef842025f3afecba26cb0b2ae4c09b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 18 Jun 2011 21:34:25 +0200 Subject: extensions: support for per-extension instance "global" variable space Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 18 +++++++++++++++--- iptables/xshared.c | 18 ++++++++++++++++++ iptables/xtoptions.c | 4 ++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index 2565dd23..0dead268 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -137,11 +137,13 @@ struct xt_option_entry { * @arg: input from command line * @ext_name: name of extension currently being processed * @entry: current option being processed - * @data: per-extension data block + * @data: per-extension kernel data block * @xflags: options of the extension that have been used * @invert: whether option was used with ! * @nvals: number of results in uXX_multi * @val: parsed result + * @udata: per-extension private scratch area + * (cf. xtables_{match,target}->udata_size) */ struct xt_option_call { const char *arg, *ext_name; @@ -174,16 +176,19 @@ struct xt_option_call { struct xt_entry_target **target; }; void *xt_entry; + void *udata; }; /** * @ext_name: name of extension currently being processed - * @data: per-extension data block + * @data: per-extension (kernel) data block + * @udata: per-extension private scratch area + * (cf. xtables_{match,target}->udata_size) * @xflags: options of the extension that have been used */ struct xt_fcheck_call { const char *ext_name; - void *data; + void *data, *udata; unsigned int xflags; }; @@ -254,7 +259,11 @@ struct xtables_match void (*x6_fcheck)(struct xt_fcheck_call *); const struct xt_option_entry *x6_options; + /* Size of per-extension instance extra "global" scratch space */ + size_t udata_size; + /* Ignore these men behind the curtain: */ + void *udata; unsigned int option_offset; struct xt_entry_match *m; unsigned int mflags; @@ -318,7 +327,10 @@ struct xtables_target void (*x6_fcheck)(struct xt_fcheck_call *); const struct xt_option_entry *x6_options; + size_t udata_size; + /* Ignore these men behind the curtain: */ + void *udata; unsigned int option_offset; struct xt_entry_target *t; unsigned int tflags; diff --git a/iptables/xshared.c b/iptables/xshared.c index 55ce5504..79da507d 100644 --- a/iptables/xshared.c +++ b/iptables/xshared.c @@ -209,12 +209,30 @@ int subcmd_main(int argc, char **argv, const struct subcommand *cb) void xs_init_target(struct xtables_target *target) { + if (target->udata_size != 0) { + free(target->udata); + target->udata = calloc(1, target->udata_size); + if (target->udata == NULL) + xtables_error(RESOURCE_PROBLEM, "malloc"); + } if (target->init != NULL) target->init(target->t); } void xs_init_match(struct xtables_match *match) { + if (match->udata_size != 0) { + /* + * As soon as a subsequent instance of the same match + * is used, e.g. "-m time -m time", the first instance + * is no longer reachable anyway, so we can free udata. + * Same goes for target. + */ + free(match->udata); + match->udata = calloc(1, match->udata_size); + if (match->udata == NULL) + xtables_error(RESOURCE_PROBLEM, "malloc"); + } if (match->init != NULL) match->init(match->m); } diff --git a/iptables/xtoptions.c b/iptables/xtoptions.c index ac0601f2..1423724b 100644 --- a/iptables/xtoptions.c +++ b/iptables/xtoptions.c @@ -908,6 +908,7 @@ void xtables_option_tpcall(unsigned int c, char **argv, bool invert, cb.xflags = t->tflags; cb.target = &t->t; cb.xt_entry = fw; + cb.udata = t->udata; t->x6_parse(&cb); t->tflags = cb.xflags; } @@ -943,6 +944,7 @@ void xtables_option_mpcall(unsigned int c, char **argv, bool invert, cb.xflags = m->mflags; cb.match = &m->m; cb.xt_entry = fw; + cb.udata = m->udata; m->x6_parse(&cb); m->mflags = cb.xflags; } @@ -1028,6 +1030,7 @@ void xtables_option_tfcall(struct xtables_target *t) cb.ext_name = t->name; cb.data = t->t->data; cb.xflags = t->tflags; + cb.udata = t->udata; t->x6_fcheck(&cb); } else if (t->final_check != NULL) { t->final_check(t->tflags); @@ -1048,6 +1051,7 @@ void xtables_option_mfcall(struct xtables_match *m) cb.ext_name = m->name; cb.data = m->m->data; cb.xflags = m->mflags; + cb.udata = m->udata; m->x6_fcheck(&cb); } else if (m->final_check != NULL) { m->final_check(m->mflags); -- cgit v1.2.3 From 4a96d2e2c9d8c43b58d9490cd1d2ae2d1b3e0bef Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 21 Jun 2011 09:54:31 +0200 Subject: libxt_rateest: abolish global variables Signed-off-by: Jan Engelhardt --- extensions/libxt_rateest.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c index 509b3e31..5f42a137 100644 --- a/extensions/libxt_rateest.c +++ b/extensions/libxt_rateest.c @@ -8,9 +8,6 @@ #include #include -/* Ugly hack to pass info to final_check function. We should fix the API */ -static struct xt_rateest_match_info *rateest_info; - static void rateest_help(void) { printf( @@ -115,8 +112,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, struct xt_rateest_match_info *info = (void *)(*match)->data; unsigned int val; - rateest_info = info; - switch (c) { case OPT_RATEEST1: xtables_check_inverse(optarg, &invert, &optind, 0, argv); @@ -302,10 +297,9 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, return 1; } -static void -rateest_final_check(unsigned int flags) +static void rateest_final_check(struct xt_fcheck_call *cb) { - struct xt_rateest_match_info *info = rateest_info; + struct xt_rateest_match_info *info = cb->data; if (info == NULL) xtables_error(PARAMETER_PROBLEM, "rateest match: " @@ -439,7 +433,7 @@ static struct xtables_match rateest_mt_reg = { .userspacesize = XT_ALIGN(offsetof(struct xt_rateest_match_info, est1)), .help = rateest_help, .parse = rateest_parse, - .final_check = rateest_final_check, + .x6_fcheck = rateest_final_check, .print = rateest_print, .save = rateest_save, .extra_opts = rateest_opts, -- cgit v1.2.3 From 12bc22a9d3e4ae4a3276dbae1cf3bd50ef5dbe9d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 21 Jun 2011 14:22:20 +0200 Subject: libxt_RATEEST: abolish global variables Signed-off-by: Jan Engelhardt --- extensions/libxt_RATEEST.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/extensions/libxt_RATEEST.c b/extensions/libxt_RATEEST.c index b928b339..62bcb5e8 100644 --- a/extensions/libxt_RATEEST.c +++ b/extensions/libxt_RATEEST.c @@ -7,9 +7,10 @@ #include #include -/* hack to pass raw values to final_check */ -static unsigned int interval; -static unsigned int ewma_log; +struct rateest_tg_udata { + unsigned int interval; + unsigned int ewma_log; +}; static void RATEEST_help(void) @@ -85,16 +86,18 @@ RATEEST_print_time(unsigned int time) static void RATEEST_parse(struct xt_option_call *cb) { + struct rateest_tg_udata *udata = cb->udata; + xtables_option_parse(cb); switch (cb->entry->id) { case O_INTERVAL: - if (RATEEST_get_time(&interval, cb->arg) < 0) + if (RATEEST_get_time(&udata->interval, cb->arg) < 0) xtables_error(PARAMETER_PROBLEM, "RATEEST: bad interval value \"%s\"", cb->arg); break; case O_EWMALOG: - if (RATEEST_get_time(&ewma_log, cb->arg) < 0) + if (RATEEST_get_time(&udata->ewma_log, cb->arg) < 0) xtables_error(PARAMETER_PROBLEM, "RATEEST: bad ewmalog value \"%s\"", cb->arg); @@ -105,9 +108,10 @@ static void RATEEST_parse(struct xt_option_call *cb) static void RATEEST_final_check(struct xt_fcheck_call *cb) { struct xt_rateest_target_info *info = cb->data; + struct rateest_tg_udata *udata = cb->udata; for (info->interval = 0; info->interval <= 5; info->interval++) { - if (interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4)) + if (udata->interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4)) break; } @@ -118,7 +122,7 @@ static void RATEEST_final_check(struct xt_fcheck_call *cb) for (info->ewma_log = 1; info->ewma_log < 32; info->ewma_log++) { double w = 1.0 - 1.0 / (1 << info->ewma_log); - if (interval / (-log(w)) > ewma_log) + if (udata->interval / (-log(w)) > udata->ewma_log) break; } info->ewma_log--; @@ -170,6 +174,7 @@ static struct xtables_target rateest_tg_reg = { .print = RATEEST_print, .save = RATEEST_save, .x6_options = RATEEST_opts, + .udata_size = sizeof(struct rateest_tg_udata), }; void _init(void) -- cgit v1.2.3 From 017e7b7e1cf4fb63208e46592d06cc030f6d552d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 22 Jun 2011 10:15:07 +0200 Subject: libip6t_HL: fix option names from ttl -> hl Signed-off-by: Jan Engelhardt --- extensions/libip6t_HL.c | 6 +++--- tests/options-most.rules | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/extensions/libip6t_HL.c b/extensions/libip6t_HL.c index 254b1914..52ca5d3e 100644 --- a/extensions/libip6t_HL.c +++ b/extensions/libip6t_HL.c @@ -20,12 +20,12 @@ enum { #define s struct ip6t_HL_info static const struct xt_option_entry HL_opts[] = { - {.name = "ttl-set", .type = XTTYPE_UINT8, .id = O_HL_SET, + {.name = "hl-set", .type = XTTYPE_UINT8, .id = O_HL_SET, .excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit)}, - {.name = "ttl-dec", .type = XTTYPE_UINT8, .id = O_HL_DEC, + {.name = "hl-dec", .type = XTTYPE_UINT8, .id = O_HL_DEC, .excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit), .min = 1}, - {.name = "ttl-inc", .type = XTTYPE_UINT8, .id = O_HL_INC, + {.name = "hl-inc", .type = XTTYPE_UINT8, .id = O_HL_INC, .excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit), .min = 1}, XTOPT_TABLEEND, diff --git a/tests/options-most.rules b/tests/options-most.rules index 13ee9873..125b5bf3 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -1,4 +1,3 @@ -# Generated by ip6tables-save v1.4.10 on Mon Jan 31 02:19:53 2011 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] @@ -171,4 +170,17 @@ #-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-eq --rateest-pps2 9 #-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-gt --rateest-pps2 9 COMMIT -# Completed on Mon Jan 31 02:19:54 2011 +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:matches - - +:ntarg - - +:zmatches - - +-A INPUT -m u32 --u32 "0x0=0x0&&0x0=0x1" -j ntarg +-A ntarg -j HL --hl-inc 1 +-A ntarg -j HL --hl-dec 1 +-A ntarg +COMMIT -- cgit v1.2.3 From 70cb0a6d3e09f64f9a05870d694ac0160319de9a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 22 Jun 2011 11:15:34 +0200 Subject: libxt_state: fix regression about inversion of main option Signed-off-by: Jan Engelhardt --- extensions/libxt_state.c | 2 +- tests/options-most.rules | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_state.c b/extensions/libxt_state.c index 3fc747d8..eff444c8 100644 --- a/extensions/libxt_state.c +++ b/extensions/libxt_state.c @@ -23,7 +23,7 @@ state_help(void) static const struct xt_option_entry state_opts[] = { {.name = "state", .id = O_STATE, .type = XTTYPE_STRING, - .flags = XTOPT_MAND}, + .flags = XTOPT_MAND | XTOPT_INVERT}, XTOPT_TABLEEND, }; diff --git a/tests/options-most.rules b/tests/options-most.rules index 125b5bf3..2b419e57 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -75,6 +75,8 @@ -A matches -A matches -m conntrack --ctexpire 5:4294967295 -A matches +-A matches -m conntrack ! --ctstate NEW ! --ctproto tcp ! --ctorigsrc ::1/127 ! --ctorigdst ::2/127 ! --ctreplsrc ::2/127 ! --ctrepldst ::2/127 ! --ctorigsrcport 3 ! --ctorigdstport 4 ! --ctreplsrcport 5 ! --ctrepldstport 6 ! --ctstatus ASSURED ! --ctexpire 8:9 +-A matches -A matches -p esp -m esp --espspi 1 -A matches -A matches -p esp -m esp --espspi :2 -- cgit v1.2.3 From 68146dad91611bd8d6d12c8ba27219130d99607b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 22 Jun 2011 11:18:19 +0200 Subject: libxt_hashlimit: use a more obvious expiry value by default Due to the previous default expiry of 10 sec, "--hashlimit 1/min" would allow matching up to 6/min if a properly timed. To do what the user expects, the minimum expiry must equal the selected time quantum however. Cc: Jan Rovner Signed-off-by: Jan Engelhardt --- extensions/libxt_hashlimit.c | 57 +++++++++++++++++++++++++++++++------------- tests/options-most.rules | 5 ++++ 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index e683f9ad..a838680c 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -25,6 +25,10 @@ #define XT_HASHLIMIT_GCINTERVAL 1000 #define XT_HASHLIMIT_EXPIRE 10000 +struct hashlimit_mt_udata { + uint32_t mult; +}; + static void hashlimit_help(void) { printf( @@ -56,8 +60,9 @@ enum { O_HTABLE_MAX, O_HTABLE_GCINT, O_HTABLE_EXPIRE, - F_UPTO = 1 << O_UPTO, - F_ABOVE = 1 << O_ABOVE, + F_UPTO = 1 << O_UPTO, + F_ABOVE = 1 << O_ABOVE, + F_HTABLE_EXPIRE = 1 << O_HTABLE_EXPIRE, }; static void hashlimit_mt_help(void) @@ -141,25 +146,25 @@ static const struct xt_option_entry hashlimit_mt_opts[] = { #undef s static -int parse_rate(const char *rate, uint32_t *val) +int parse_rate(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud) { const char *delim; uint32_t r; - uint32_t mult = 1; /* Seconds by default. */ + ud->mult = 1; /* Seconds by default. */ delim = strchr(rate, '/'); if (delim) { if (strlen(delim+1) == 0) return 0; if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0) - mult = 1; + ud->mult = 1; else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0) - mult = 60; + ud->mult = 60; else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0) - mult = 60*60; + ud->mult = 60*60; else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0) - mult = 24*60*60; + ud->mult = 24*60*60; else return 0; } @@ -169,10 +174,10 @@ int parse_rate(const char *rate, uint32_t *val) /* This would get mapped to infinite (1/day is minimum they can specify, so we're ok at that end). */ - if (r / mult > XT_HASHLIMIT_SCALE) + if (r / ud->mult > XT_HASHLIMIT_SCALE) xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate); - *val = XT_HASHLIMIT_SCALE * mult / r; + *val = XT_HASHLIMIT_SCALE * ud->mult / r; return 1; } @@ -248,14 +253,14 @@ static void hashlimit_parse(struct xt_option_call *cb) case O_UPTO: if (cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(cb->arg, &info->cfg.avg)) + if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", "--hashlimit-upto", cb->arg); break; case O_ABOVE: if (!cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(cb->arg, &info->cfg.avg)) + if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", "--hashlimit-above", cb->arg); break; @@ -276,14 +281,14 @@ static void hashlimit_mt_parse(struct xt_option_call *cb) case O_UPTO: if (cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(cb->arg, &info->cfg.avg)) + if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", "--hashlimit-upto", cb->arg); break; case O_ABOVE: if (!cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(cb->arg, &info->cfg.avg)) + if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", "--hashlimit-above", cb->arg); break; @@ -303,9 +308,26 @@ static void hashlimit_mt_parse(struct xt_option_call *cb) static void hashlimit_check(struct xt_fcheck_call *cb) { + const struct hashlimit_mt_udata *udata = cb->udata; + struct xt_hashlimit_info *info = cb->data; + if (!(cb->xflags & (F_UPTO | F_ABOVE))) xtables_error(PARAMETER_PROBLEM, "You have to specify --hashlimit"); + if (!(cb->xflags & F_HTABLE_EXPIRE)) + info->cfg.expire = udata->mult; +} + +static void hashlimit_mt_check(struct xt_fcheck_call *cb) +{ + const struct hashlimit_mt_udata *udata = cb->udata; + struct xt_hashlimit_mtinfo1 *info = cb->data; + + if (!(cb->xflags & (F_UPTO | F_ABOVE))) + xtables_error(PARAMETER_PROBLEM, + "You have to specify --hashlimit"); + if (!(cb->xflags & F_HTABLE_EXPIRE)) + info->cfg.expire = udata->mult; } static const struct rates @@ -508,6 +530,7 @@ static struct xtables_match hashlimit_mt_reg[] = { .print = hashlimit_print, .save = hashlimit_save, .x6_options = hashlimit_mt_opts, + .udata_size = sizeof(struct hashlimit_mt_udata), }, { .version = XTABLES_VERSION, @@ -519,10 +542,11 @@ static struct xtables_match hashlimit_mt_reg[] = { .help = hashlimit_mt_help, .init = hashlimit_mt4_init, .x6_parse = hashlimit_mt_parse, - .x6_fcheck = hashlimit_check, + .x6_fcheck = hashlimit_mt_check, .print = hashlimit_mt4_print, .save = hashlimit_mt4_save, .x6_options = hashlimit_mt_opts, + .udata_size = sizeof(struct hashlimit_mt_udata), }, { .version = XTABLES_VERSION, @@ -534,10 +558,11 @@ static struct xtables_match hashlimit_mt_reg[] = { .help = hashlimit_mt_help, .init = hashlimit_mt6_init, .x6_parse = hashlimit_mt_parse, - .x6_fcheck = hashlimit_check, + .x6_fcheck = hashlimit_mt_check, .print = hashlimit_mt6_print, .save = hashlimit_mt6_save, .x6_options = hashlimit_mt_opts, + .udata_size = sizeof(struct hashlimit_mt_udata), }, }; diff --git a/tests/options-most.rules b/tests/options-most.rules index 2b419e57..7298a1f9 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -87,6 +87,11 @@ -A matches -A matches -p esp -m esp --espspi 5:4294967295 -A matches +-A matches -m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-name mini1 +-A matches -m hashlimit --hashlimit-upto 1/min --hashlimit-burst 1 --hashlimit-name mini2 +-A matches -m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 1 --hashlimit-name mini3 +-A matches -m hashlimit --hashlimit-upto 1/day --hashlimit-burst 1 --hashlimit-name mini4 +-A matches -A matches -m ipvs --vaddr fe80::/64 --vport 1 --vdir REPLY --vmethod GATE --vportctl 21 -A matches -A matches -m length --length 1 -- cgit v1.2.3 From f6677b5bcae125af28d227b9073426bddbd9190e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 22 Jun 2011 15:42:48 +0200 Subject: build: bump soversion for recent data structure change Cf. commit v1.4.11.1-5-g2dba676. Signed-off-by: Jan Engelhardt --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e902ab92..b57f542d 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_INIT([iptables], [1.4.11.1]) # See libtool.info "Libtool's versioning system" -libxtables_vcurrent=6 +libxtables_vcurrent=7 libxtables_vage=0 AC_CONFIG_HEADERS([config.h]) -- cgit v1.2.3 From 96d0d0130a9a08803406c5c18681903446088ebf Mon Sep 17 00:00:00 2001 From: Jiri Popelka Date: Fri, 10 Jun 2011 15:25:55 +0200 Subject: iptables: Coverity: DEADCODE libiptc.c:407: dead_error_condition: On this path, the condition "res > 0" cannot be false. libiptc.c:396: at_least: After this line, the value of "res" is at least 1. libiptc.c:393: equality_cond: Condition "res == 0" is evaluated as false. libiptc.c:396: new_values: Noticing condition "res < 0". libiptc.c:425: new_values: Noticing condition "res < 0". libiptc.c:407: new_values: Noticing condition "res > 0". libiptc.c:435: dead_error_line: Execution cannot reach this statement "return list_pos;". Signed-off-by: Jan Engelhardt --- libiptc/libiptc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 0b6d5e3a..42d9784a 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -403,7 +403,7 @@ __iptcc_bsearch_chain_index(const char *name, unsigned int offset, } debug("jump back to pos:%d (end:%d)\n", pos, end); goto loop; - } else if (res > 0 ){ /* Not far enough, jump forward */ + } else { /* res > 0; Not far enough, jump forward */ /* Exit case: Last element of array */ if (pos == handle->chain_index_sz-1) { @@ -430,8 +430,6 @@ __iptcc_bsearch_chain_index(const char *name, unsigned int offset, debug("jump forward to pos:%d (end:%d)\n", pos, end); goto loop; } - - return list_pos; } /* Wrapper for string chain name based bsearch */ -- cgit v1.2.3 From 474c18d7982407246dd724c6fa3939f78466620a Mon Sep 17 00:00:00 2001 From: Jiri Popelka Date: Fri, 10 Jun 2011 15:25:57 +0200 Subject: iptables: Coverity: NEGATIVE_RETURNS libipq.c:232: var_tested_neg: Variable "h->fd" tests negative. libipq.c:234: negative_returns: "h->fd" is passed to a parameter that cannot be negative. Signed-off-by: Jan Engelhardt --- libipq/libipq.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libipq/libipq.c b/libipq/libipq.c index e3304875..fb65971a 100644 --- a/libipq/libipq.c +++ b/libipq/libipq.c @@ -231,7 +231,6 @@ struct ipq_handle *ipq_create_handle(uint32_t flags, uint32_t protocol) if (h->fd == -1) { ipq_errno = IPQ_ERR_SOCKET; - close(h->fd); free(h); return NULL; } -- cgit v1.2.3 From ee80faf4438102395bc4034894b6468453181be9 Mon Sep 17 00:00:00 2001 From: Jiri Popelka Date: Fri, 10 Jun 2011 15:25:58 +0200 Subject: iptables: Coverity: REVERSE_INULL ip6tables-restore.c:186: deref_ptr_in_call: Dereferencing pointer "in". ip6tables-restore.c:463: check_after_deref: Dereferencing "in" before a null check. iptables-restore.c:192: deref_ptr_in_call: Dereferencing pointer "in". iptables-restore.c:468: check_after_deref: Dereferencing "in" before a null check. iptables-xml.c:671: deref_ptr_in_call: Dereferencing pointer "in". iptables-xml.c:873: check_after_deref: Dereferencing "in" before a null check. Signed-off-by: Jan Engelhardt --- iptables/ip6tables-restore.c | 3 +-- iptables/iptables-restore.c | 3 +-- iptables/iptables-xml.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 420bc523..ae147d55 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -460,7 +460,6 @@ int main(int argc, char *argv[]) exit(1); } - if (in != NULL) - fclose(in); + fclose(in); return 0; } diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 26245997..1cb833c0 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -465,7 +465,6 @@ main(int argc, char *argv[]) exit(1); } - if (in != NULL) - fclose(in); + fclose(in); return 0; } diff --git a/iptables/iptables-xml.c b/iptables/iptables-xml.c index 5aa638c0..502b2d96 100644 --- a/iptables/iptables-xml.c +++ b/iptables/iptables-xml.c @@ -865,8 +865,7 @@ main(int argc, char *argv[]) exit(1); } - if (in != NULL) - fclose(in); + fclose(in); printf("\n"); free_argv(); -- cgit v1.2.3 From d0101690d9ae347d8a8ee9e340c5db72480046a3 Mon Sep 17 00:00:00 2001 From: Jiri Popelka Date: Fri, 10 Jun 2011 15:26:00 +0200 Subject: iptables: Coverity: VARARGS xtables.c:931: va_init: Initializing va_list "args". xtables.c:938: missing_va_end: va_end was not called for "args". xtables.c:947: missing_va_end: va_end was not called for "args". xtables.c:961: missing_va_end: va_end was not called for "args". Signed-off-by: Jan Engelhardt --- iptables/xtables.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/iptables/xtables.c b/iptables/xtables.c index acfcf8bd..db6d079f 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -1042,8 +1042,10 @@ void xtables_param_act(unsigned int status, const char *p1, ...) case XTF_ONLY_ONCE: p2 = va_arg(args, const char *); b = va_arg(args, unsigned int); - if (!b) + if (!b) { + va_end(args); return; + } xt_params->exit_err(PARAMETER_PROBLEM, "%s: \"%s\" option may only be specified once", p1, p2); @@ -1051,8 +1053,10 @@ void xtables_param_act(unsigned int status, const char *p1, ...) case XTF_NO_INVERT: p2 = va_arg(args, const char *); b = va_arg(args, unsigned int); - if (!b) + if (!b) { + va_end(args); return; + } xt_params->exit_err(PARAMETER_PROBLEM, "%s: \"%s\" option cannot be inverted", p1, p2); break; @@ -1065,8 +1069,10 @@ void xtables_param_act(unsigned int status, const char *p1, ...) break; case XTF_ONE_ACTION: b = va_arg(args, unsigned int); - if (!b) + if (!b) { + va_end(args); return; + } xt_params->exit_err(PARAMETER_PROBLEM, "%s: At most one action is possible", p1); break; -- cgit v1.2.3 From f53710b16c2bae1843c3f5fee390f496dfa82526 Mon Sep 17 00:00:00 2001 From: Jiri Popelka Date: Fri, 10 Jun 2011 15:26:02 +0200 Subject: iptables: Coverity: RESOURCE_LEAK xtables.c:320: alloc_fn: Calling allocation function "get_modprobe". xtables.c:294: alloc_fn: Storage is returned from allocation function "malloc". xtables.c:294: var_assign: Assigning: "ret" = "malloc(1024UL)". xtables.c:304: return_alloc: Returning allocated memory "ret". xtables.c:320: var_assign: Assigning: "buf" = storage returned from "get_modprobe()". xtables.c:323: var_assign: Assigning: "modprobe" = "buf". xtables.c:348: leaked_storage: Variable "buf" going out of scope leaks the storage it points to. xtables.c:348: leaked_storage: Returning without freeing "modprobe" leaks the storage that it points to. Signed-off-by: Jan Engelhardt --- iptables/xtables.c | 1 + 1 file changed, 1 insertion(+) diff --git a/iptables/xtables.c b/iptables/xtables.c index db6d079f..00c7c066 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -362,6 +362,7 @@ int xtables_insmod(const char *modname, const char *modprobe, bool quiet) /* not usually reached */ exit(1); case -1: + free(buf); return -1; default: /* parent */ -- cgit v1.2.3 From 622abc73b097e7e778b432e422fd3c1f035bcfd3 Mon Sep 17 00:00:00 2001 From: Massimo Maggi Date: Wed, 15 Jun 2011 02:52:00 +0200 Subject: libxt_RATEEST: fix userspacesize field I cannot delete a rule by matching it if the target of the rule is RATEEST. Copy-paste from terminal: # iptables -t mangle -A PREROUTING -j RATEEST --rateest-name somename --rateest-interval 250ms --rateest-ewmalog 4s # iptables -t mangle -D PREROUTING -j RATEEST --rateest-name somename --rateest-interval 250ms --rateest-ewmalog 4s iptables: No chain/target/match by that name. I saw in comments of the kernel code that the last part of the struct xt_rateest_target_info is used only by kernel: struct xt_rateest_target_info { char name[IFNAMSIZ]; __s8 interval; __u8 ewma_log; /* Used internally by the kernel */ struct xt_rateest *est __attribute__((aligned(8))); }; but in struct xtables_target, .size and .userspacesize are equal. Simply correcting this solved the problem. References: http://bugzilla.netfilter.org/show_bug.cgi?id=724 Signed-off-by: Jan Engelhardt --- extensions/libxt_RATEEST.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_RATEEST.c b/extensions/libxt_RATEEST.c index 62bcb5e8..acdefb90 100644 --- a/extensions/libxt_RATEEST.c +++ b/extensions/libxt_RATEEST.c @@ -167,7 +167,7 @@ static struct xtables_target rateest_tg_reg = { .name = "RATEEST", .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct xt_rateest_target_info)), - .userspacesize = XT_ALIGN(sizeof(struct xt_rateest_target_info)), + .userspacesize = offsetof(struct xt_rateest_target_info, est), .help = RATEEST_help, .x6_parse = RATEEST_parse, .x6_fcheck = RATEEST_final_check, -- cgit v1.2.3 From 447ddfbfb3ed16ad0059f4559334670e9b9806ec Mon Sep 17 00:00:00 2001 From: Jakub Zawadzki Date: Mon, 13 Jun 2011 13:54:33 +0200 Subject: doc: fix group range in libxt_NFLOG's man References: http://bugzilla.netfilter.org/show_bug.cgi?id=723 Signed-off-by: Jan Engelhardt --- extensions/libxt_NFLOG.man | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_NFLOG.man b/extensions/libxt_NFLOG.man index 66f0b973..1b6dbf16 100644 --- a/extensions/libxt_NFLOG.man +++ b/extensions/libxt_NFLOG.man @@ -9,7 +9,7 @@ may subscribe to the group to receive the packets. Like LOG, this is a non-terminating target, i.e. rule traversal continues at the next rule. .TP \fB\-\-nflog\-group\fP \fInlgroup\fP -The netlink group (1 \- 2^32\-1) to which packets are (only applicable for +The netlink group (0 - 2^16\-1) to which packets are (only applicable for nfnetlink_log). The default value is 0. .TP \fB\-\-nflog\-prefix\fP \fIprefix\fP -- cgit v1.2.3 From 3c871010888e1479ef8fca2048485b979ec2661a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 24 Jun 2011 20:16:48 +0200 Subject: build: attempt to fix building under Linux 2.4 iptables no longer compiles for Linux 2.4 because it uses linux/magic.h. This header and the PROC_SUPER_MAGIC macro are only for Linux 2.6. xtables.c:35:52: error: linux/magic.h: No such file or directory xtables.c: In function 'proc_file_exists': xtables.c:389: error: 'PROC_SUPER_MAGIC' undeclared (first use in this function) xtables.c:389: error: (Each undeclared identifier is reported only once for each function it appears in.) References: http://bugzilla.netfilter.org/show_bug.cgi?id=720 Signed-off-by: Jan Engelhardt --- configure.ac | 4 +--- iptables/xtables.c | 7 ++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index b57f542d..6c90caaf 100644 --- a/configure.ac +++ b/configure.ac @@ -59,12 +59,10 @@ AC_SUBST([libiptc_LDFLAGS2]) blacklist_modules=""; -AC_CHECK_HEADER([linux/dccp.h]) +AC_CHECK_HEADERS([linux/dccp.h linux/ip_vs.h linux/magic.h linux/proc_fs.h]) if test "$ac_cv_header_linux_dccp_h" != "yes"; then blacklist_modules="$blacklist_modules dccp"; fi; - -AC_CHECK_HEADER([linux/ip_vs.h]) if test "$ac_cv_header_linux_ip_vs_h" != "yes"; then blacklist_modules="$blacklist_modules ipvs"; fi; diff --git a/iptables/xtables.c b/iptables/xtables.c index 00c7c066..c4b1c2a8 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -15,6 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "config.h" #include #include #include @@ -32,7 +33,11 @@ #include #include #include -#include /* for PROC_SUPER_MAGIC */ +#if defined(HAVE_LINUX_MAGIC_H) +# include /* for PROC_SUPER_MAGIC */ +#elif defined(HAVE_LINUX_PROC_FS_H) +# include /* Linux 2.4 */ +#endif #include #include /* INT_MAX in ip_tables.h/ip6_tables.h */ -- cgit v1.2.3 From 358650c0e280dad8c1292efbf856ac310004a52b Mon Sep 17 00:00:00 2001 From: "Martin F. Krafft" Date: Tue, 22 Sep 2009 21:07:13 +0200 Subject: iptables-apply: select default rule file depending on call name ip6tables-apply points to iptables-apply (which is good). Since iptables/ip6tables rule files are different, the reporter suggests that the DEFAULT_FILE variable should depend on whether iptables-apply or ip6tables-apply is run. References: http://bugs.debian.org/547734 Signed-off-by: Jan Engelhardt --- iptables/iptables-apply | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/iptables/iptables-apply b/iptables/iptables-apply index 5fec76b0..86b8d5a2 100755 --- a/iptables/iptables-apply +++ b/iptables/iptables-apply @@ -11,7 +11,6 @@ PROGNAME="${0##*/}"; VERSION=1.0 TIMEOUT=10 -DEFAULT_FILE=/etc/network/iptables function blurb() { @@ -87,6 +86,19 @@ for opt in $OPTS; do shift done +case "$PROGNAME" in + (*6*) + SAVE=ip6tables-save + RESTORE=ip6tables-restore + DEFAULT_FILE=/etc/network/ip6tables + ;; + (*) + SAVE=iptables-save + RESTORE=iptables-restore + DEFAULT_FILE=/etc/network/iptables + ;; +esac + FILE="${1:-$DEFAULT_FILE}"; if [[ -z "$FILE" ]]; then @@ -99,17 +111,6 @@ if [[ ! -r "$FILE" ]]; then exit 2 fi -case "${0##*/}" in - (*6*) - SAVE=ip6tables-save - RESTORE=ip6tables-restore - ;; - (*) - SAVE=iptables-save - RESTORE=iptables-restore - ;; -esac - COMMANDS=(tempfile "$SAVE" "$RESTORE") for cmd in "${COMMANDS[@]}"; do -- cgit v1.2.3 From 1c9508e1f3f853f33683eb7118e19b193a6c80b7 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 30 Jun 2011 13:19:15 +0200 Subject: doc: mention multiple verbosity flags "-vv" can be used to further increase the verbosity level. Document this. References: http://bugs.debian.org/616037 Signed-off-by: Jan Engelhardt --- iptables/ip6tables.8.in | 3 ++- iptables/iptables.8.in | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 48ba18e1..20e271de 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -333,7 +333,8 @@ byte counters are also listed, with the suffix 'K', 'M' or 'G' for 1000, 1,000,000 and 1,000,000,000 multipliers respectively (but see the \fB\-x\fP flag to change this). For appending, insertion, deletion and replacement, this causes -detailed information on the rule or rules to be printed. +detailed information on the rule or rules to be printed. \fB\-v\fP may be +specified multiple times to possibly emit more detailed debug statements. .TP \fB\-n\fP, \fB\-\-numeric\fP Numeric output. diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index d09bf7aa..3b717a11 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -332,7 +332,8 @@ byte counters are also listed, with the suffix 'K', 'M' or 'G' for 1000, 1,000,000 and 1,000,000,000 multipliers respectively (but see the \fB\-x\fP flag to change this). For appending, insertion, deletion and replacement, this causes -detailed information on the rule or rules to be printed. +detailed information on the rule or rules to be printed. \fB\-v\fP may be +specified multiple times to possibly emit more detailed debug statements. .TP \fB\-n\fP, \fB\-\-numeric\fP Numeric output. -- cgit v1.2.3 From 411a4e50ec1030f2dc51c5b0156e0c7255c81905 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 4 Jul 2011 12:44:43 +0200 Subject: build: install modules in arch-dependent location Make it possible to have multiple types of ELF classes for the extension modules by putting them in an arch-dependent path. Signed-off-by: Jan Engelhardt --- INSTALL | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index acb56cd5..e17e8441 100644 --- a/INSTALL +++ b/INSTALL @@ -31,7 +31,7 @@ Configuring and compiling --with-xtlibdir= The path to where Xtables extensions should be installed to. It - defaults to ${prefix}/libexec/xtables. + defaults to ${libdir}/xtables. --enable-devel (or --disable-devel) diff --git a/configure.ac b/configure.ac index 6c90caaf..5cb1b1bb 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,7 @@ AC_ARG_WITH([xtlibdir], AS_HELP_STRING([--with-xtlibdir=PATH], [Path where to install Xtables extensions [[LIBEXECDIR/xtables]]]), [xtlibdir="$withval"], - [xtlibdir="${libexecdir}/xtables"]) + [xtlibdir="${libdir}/xtables"]) AC_ARG_ENABLE([ipv4], AS_HELP_STRING([--disable-ipv4], [Do not build iptables]), [enable_ipv4="$enableval"], [enable_ipv4="yes"]) -- cgit v1.2.3 From 9cf0c00c226db02f8f3d129225844920704b97c1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 4 Jul 2011 13:02:51 +0200 Subject: doc: fix version string in ip6tables.8 Signed-off-by: Jan Engelhardt --- iptables/ip6tables.8.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 20e271de..0f7e3cce 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -1,4 +1,4 @@ -.TH IP6TABLES 8 "" "iptables 1.4.4" "iptables 1.4.4" +.TH IP6TABLES 8 "" "@PACKAGE_AND_VERSION@" "@PACKAGE_AND_VERSION@" .\" .\" Man page written by Andras Kis-Szabo .\" It is based on iptables man page. -- cgit v1.2.3 From d532d7663fd82984023a871aa953419ad1e905cb Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 4 Jul 2011 13:04:16 +0200 Subject: doc: the -m option cannot be inverted Signed-off-by: Jan Engelhardt --- iptables/ip6tables.8.in | 3 --- iptables/iptables.8.in | 3 --- 2 files changed, 6 deletions(-) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 0f7e3cce..748cebba 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -366,9 +366,6 @@ module. You can specify multiple extended match modules in one line, and you can use the \fB\-h\fP or \fB\-\-help\fP options after the module has been specified to receive help specific to that module. -.PP -The following are included in the base package, and most of these can -be preceded by a "\fB!\fP" to invert the sense of the match. .\" @MATCH@ .SH TARGET EXTENSIONS ip6tables can use extended target modules: the following are included diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 3b717a11..24618b7b 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -365,9 +365,6 @@ module. You can specify multiple extended match modules in one line, and you can use the \fB\-h\fP or \fB\-\-help\fP options after the module has been specified to receive help specific to that module. -.PP -The following are included in the base package, and most of these can -be preceded by a "\fB!\fP" to invert the sense of the match. .\" @MATCH@ .SH TARGET EXTENSIONS iptables can use extended target modules: the following are included -- cgit v1.2.3 From 32cea83f26a2c342b9410e6dfb0530b33f8af928 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 5 Jul 2011 15:08:37 +0200 Subject: iptables: restore negation for -f This move was missed in commit v1.4.11~77^2~6. References: http://bugs.debian.org/632695 Signed-off-by: Jan Engelhardt --- iptables/iptables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iptables/iptables.c b/iptables/iptables.c index 477e8f1d..6ceaf6b8 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -178,9 +178,9 @@ static const int inverse_for_options[NUMBER_OF_OPT] = /* -x */ 0, /* -i */ IPT_INV_VIA_IN, /* -o */ IPT_INV_VIA_OUT, -/* -f */ IPT_INV_FRAG, /*--line*/ 0, /* -c */ 0, +/* -f */ IPT_INV_FRAG, }; #define opts iptables_globals.opts -- cgit v1.2.3 From c0e69db337540b22a3b3f739b1143341e7b759b7 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 9 Jul 2011 16:01:18 +0200 Subject: libxtables: properly reject empty hostnames An empty hostname in the address list of an -s/-d argument, which may be the result of a typo, is interpreted as 0/0, which, when combined with -j ACCEPT, leads to an undesired opening of the firewall. References: http://bugzilla.netfilter.org/show_bug.cgi?id=727 Signed-off-by: Jan Engelhardt --- iptables/xtables.c | 46 ++++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/iptables/xtables.c b/iptables/xtables.c index c4b1c2a8..3b173959 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -1299,7 +1299,7 @@ void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, struct in_addr **maskpp, unsigned int *naddrs) { struct in_addr *addrp; - char buf[256], *p; + char buf[256], *p, *next; unsigned int len, i, j, n, count = 1; const char *loop = name; @@ -1314,23 +1314,17 @@ void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, loop = name; for (i = 0; i < count; ++i) { - if (loop == NULL) - break; - if (*loop == ',') - ++loop; - if (*loop == '\0') - break; - p = strchr(loop, ','); - if (p != NULL) - len = p - loop; + next = strchr(loop, ','); + if (next != NULL) + len = next - loop; else len = strlen(loop); - if (len == 0 || sizeof(buf) - 1 < len) - break; + if (len > sizeof(buf) - 1) + xt_params->exit_err(PARAMETER_PROBLEM, + "Hostname too long"); strncpy(buf, loop, len); buf[len] = '\0'; - loop += len; if ((p = strrchr(buf, '/')) != NULL) { *p = '\0'; addrp = parse_ipmask(p + 1); @@ -1368,6 +1362,9 @@ void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, } /* free what ipparse_hostnetwork had allocated: */ free(addrp); + if (next == NULL) + break; + loop = next + 1; } *naddrs = count; for (i = 0; i < count; ++i) @@ -1616,7 +1613,7 @@ xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, { static const struct in6_addr zero_addr; struct in6_addr *addrp; - char buf[256], *p; + char buf[256], *p, *next; unsigned int len, i, j, n, count = 1; const char *loop = name; @@ -1631,23 +1628,17 @@ xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, loop = name; for (i = 0; i < count /*NB: count can grow*/; ++i) { - if (loop == NULL) - break; - if (*loop == ',') - ++loop; - if (*loop == '\0') - break; - p = strchr(loop, ','); - if (p != NULL) - len = p - loop; + next = strchr(loop, ','); + if (next != NULL) + len = next - loop; else len = strlen(loop); - if (len == 0 || sizeof(buf) - 1 < len) - break; + if (len > sizeof(buf) - 1) + xt_params->exit_err(PARAMETER_PROBLEM, + "Hostname too long"); strncpy(buf, loop, len); buf[len] = '\0'; - loop += len; if ((p = strrchr(buf, '/')) != NULL) { *p = '\0'; addrp = parse_ip6mask(p + 1); @@ -1681,6 +1672,9 @@ xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, } /* free what ip6parse_hostnetwork had allocated: */ free(addrp); + if (next == NULL) + break; + loop = next + 1; } *naddrs = count; for (i = 0; i < count; ++i) -- cgit v1.2.3 From 0c384449ae9511157cd9b34d73f8f4cb71123a45 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 9 Jul 2011 16:19:09 +0200 Subject: libxtables: ignore whitespace in the multiaddress argument parser References: http://bugzilla.netfilter.org/show_bug.cgi?id=727 Signed-off-by: Jan Engelhardt --- iptables/xtables.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iptables/xtables.c b/iptables/xtables.c index 3b173959..0f025920 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -1314,6 +1314,8 @@ void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, loop = name; for (i = 0; i < count; ++i) { + while (isspace(*loop)) + ++loop; next = strchr(loop, ','); if (next != NULL) len = next - loop; @@ -1628,6 +1630,8 @@ xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, loop = name; for (i = 0; i < count /*NB: count can grow*/; ++i) { + while (isspace(*loop)) + ++loop; next = strchr(loop, ','); if (next != NULL) len = next - loop; -- cgit v1.2.3 From fbe9f1ecccb5ac02858fa7eee2979e0e4d97bb5f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 9 Jul 2011 19:37:31 +0200 Subject: option: remove last traces of intrapositional negation Intrapositional negation was deprecated in 1.4.3. Signed-off-by: Jan Engelhardt --- extensions/libxt_SET.c | 9 --------- extensions/libxt_rateest.c | 13 ------------- extensions/libxt_sctp.c | 4 ---- extensions/libxt_set.c | 4 ---- extensions/libxt_tcp.c | 5 ----- include/xtables.h.in | 2 -- iptables/ip6tables.c | 5 ----- iptables/iptables.c | 5 ----- iptables/xtables.c | 29 ----------------------------- 9 files changed, 76 deletions(-) diff --git a/extensions/libxt_SET.c b/extensions/libxt_SET.c index 51c0cec6..04466037 100644 --- a/extensions/libxt_SET.c +++ b/extensions/libxt_SET.c @@ -67,10 +67,6 @@ parse_target_v0(char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "--%s can be specified only once", what); - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --%s", what); - if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, @@ -173,11 +169,6 @@ parse_target(char **argv, int invert, struct xt_set_info *info, if (info->dim) xtables_error(PARAMETER_PROBLEM, "--%s can be specified only once", what); - - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --%s", what); - if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c index 5f42a137..86bbb06f 100644 --- a/extensions/libxt_rateest.c +++ b/extensions/libxt_rateest.c @@ -114,7 +114,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, switch (c) { case OPT_RATEEST1: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) xtables_error(PARAMETER_PROBLEM, "rateest: rateest can't be inverted"); @@ -128,7 +127,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST2: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) xtables_error(PARAMETER_PROBLEM, "rateest: rateest can't be inverted"); @@ -143,7 +141,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_BPS1: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) xtables_error(PARAMETER_PROBLEM, "rateest: rateest-bps can't be inverted"); @@ -167,7 +164,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_PPS1: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) xtables_error(PARAMETER_PROBLEM, "rateest: rateest-pps can't be inverted"); @@ -192,7 +188,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_BPS2: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) xtables_error(PARAMETER_PROBLEM, "rateest: rateest-bps can't be inverted"); @@ -216,7 +211,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_PPS2: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) xtables_error(PARAMETER_PROBLEM, "rateest: rateest-pps can't be inverted"); @@ -241,7 +235,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_DELTA: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) xtables_error(PARAMETER_PROBLEM, "rateest: rateest-delta can't be inverted"); @@ -255,8 +248,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_EQ: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - if (*flags & (1 << c)) xtables_error(PARAMETER_PROBLEM, "rateest: can't specify lt/gt/eq twice"); @@ -268,8 +259,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_LT: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - if (*flags & (1 << c)) xtables_error(PARAMETER_PROBLEM, "rateest: can't specify lt/gt/eq twice"); @@ -281,8 +270,6 @@ rateest_parse(int c, char **argv, int invert, unsigned int *flags, break; case OPT_RATEEST_GT: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - if (*flags & (1 << c)) xtables_error(PARAMETER_PROBLEM, "rateest: can't specify lt/gt/eq twice"); diff --git a/extensions/libxt_sctp.c b/extensions/libxt_sctp.c index 5dbc36f5..56a4cdf2 100644 --- a/extensions/libxt_sctp.c +++ b/extensions/libxt_sctp.c @@ -257,7 +257,6 @@ sctp_parse(int c, char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "Only one `--source-port' allowed"); einfo->flags |= XT_SCTP_SRC_PORTS; - xtables_check_inverse(optarg, &invert, &optind, 0, argv); parse_sctp_ports(optarg, einfo->spts); if (invert) einfo->invflags |= XT_SCTP_SRC_PORTS; @@ -269,7 +268,6 @@ sctp_parse(int c, char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "Only one `--destination-port' allowed"); einfo->flags |= XT_SCTP_DEST_PORTS; - xtables_check_inverse(optarg, &invert, &optind, 0, argv); parse_sctp_ports(optarg, einfo->dpts); if (invert) einfo->invflags |= XT_SCTP_DEST_PORTS; @@ -280,8 +278,6 @@ sctp_parse(int c, char **argv, int invert, unsigned int *flags, if (*flags & XT_SCTP_CHUNK_TYPES) xtables_error(PARAMETER_PROBLEM, "Only one `--chunk-types' allowed"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c index da722c73..6b39147e 100644 --- a/extensions/libxt_set.c +++ b/extensions/libxt_set.c @@ -64,8 +64,6 @@ set_parse_v0(int c, char **argv, int invert, unsigned int *flags, if (info->u.flags[0]) xtables_error(PARAMETER_PROBLEM, "--match-set can be specified only once"); - - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) info->u.flags[0] |= IPSET_MATCH_INV; @@ -151,8 +149,6 @@ set_parse_v1(int c, char **argv, int invert, unsigned int *flags, if (info->dim) xtables_error(PARAMETER_PROBLEM, "--match-set can be specified only once"); - - xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) info->flags |= IPSET_INV_MATCH; diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c index 4d914e39..3940d91e 100644 --- a/extensions/libxt_tcp.c +++ b/extensions/libxt_tcp.c @@ -148,7 +148,6 @@ tcp_parse(int c, char **argv, int invert, unsigned int *flags, if (*flags & TCP_SRC_PORTS) xtables_error(PARAMETER_PROBLEM, "Only one `--source-port' allowed"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); parse_tcp_ports(optarg, tcpinfo->spts); if (invert) tcpinfo->invflags |= XT_TCP_INV_SRCPT; @@ -159,7 +158,6 @@ tcp_parse(int c, char **argv, int invert, unsigned int *flags, if (*flags & TCP_DST_PORTS) xtables_error(PARAMETER_PROBLEM, "Only one `--destination-port' allowed"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); parse_tcp_ports(optarg, tcpinfo->dpts); if (invert) tcpinfo->invflags |= XT_TCP_INV_DSTPT; @@ -180,8 +178,6 @@ tcp_parse(int c, char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "Only one of `--syn' or `--tcp-flags' " " allowed"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, @@ -197,7 +193,6 @@ tcp_parse(int c, char **argv, int invert, unsigned int *flags, if (*flags & TCP_OPTION) xtables_error(PARAMETER_PROBLEM, "Only one `--tcp-option' allowed"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); parse_tcp_option(optarg, &tcpinfo->option); if (invert) tcpinfo->invflags |= XT_TCP_INV_OPTION; diff --git a/include/xtables.h.in b/include/xtables.h.in index 0dead268..d50df79a 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -432,8 +432,6 @@ xtables_parse_interface(const char *arg, char *vianame, unsigned char *mask); /* this is a special 64bit data type that is 8-byte aligned */ #define aligned_u64 u_int64_t __attribute__((aligned(8))) -int xtables_check_inverse(const char option[], int *invert, - int *my_optind, int argc, char **argv); extern struct xtables_globals *xt_params; #define xtables_error (xt_params->exit_err) diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index d13744ca..04e5224f 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1536,7 +1536,6 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand * Option selection */ case 'p': - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_PROTOCOL, &cs.fw6.ipv6.invflags, cs.invert); @@ -1562,14 +1561,12 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand break; case 's': - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_SOURCE, &cs.fw6.ipv6.invflags, cs.invert); shostnetworkmask = optarg; break; case 'd': - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_DESTINATION, &cs.fw6.ipv6.invflags, cs.invert); dhostnetworkmask = optarg; @@ -1594,7 +1591,6 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_VIANAMEIN, &cs.fw6.ipv6.invflags, cs.invert); xtables_parse_interface(optarg, @@ -1607,7 +1603,6 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw6.ipv6.invflags, cs.invert); xtables_parse_interface(optarg, diff --git a/iptables/iptables.c b/iptables/iptables.c index 6ceaf6b8..50dc1e7a 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1566,7 +1566,6 @@ int do_command4(int argc, char *argv[], char **table, struct iptc_handle **handl * Option selection */ case 'p': - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_PROTOCOL, &cs.fw.ip.invflags, cs.invert); @@ -1584,14 +1583,12 @@ int do_command4(int argc, char *argv[], char **table, struct iptc_handle **handl break; case 's': - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_SOURCE, &cs.fw.ip.invflags, cs.invert); shostnetworkmask = optarg; break; case 'd': - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_DESTINATION, &cs.fw.ip.invflags, cs.invert); dhostnetworkmask = optarg; @@ -1616,7 +1613,6 @@ int do_command4(int argc, char *argv[], char **table, struct iptc_handle **handl xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_VIANAMEIN, &cs.fw.ip.invflags, cs.invert); xtables_parse_interface(optarg, @@ -1629,7 +1625,6 @@ int do_command4(int argc, char *argv[], char **table, struct iptc_handle **handl xtables_error(PARAMETER_PROBLEM, "Empty interface is likely to be " "undesired"); - xtables_check_inverse(optarg, &cs.invert, &optind, argc, argv); set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw.ip.invflags, cs.invert); xtables_parse_interface(optarg, diff --git a/iptables/xtables.c b/iptables/xtables.c index 0f025920..b05df97b 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -1765,35 +1765,6 @@ void xtables_save_string(const char *value) } } -/** - * Check for option-intrapositional negation. - * Do not use in new code. - */ -int xtables_check_inverse(const char option[], int *invert, - int *my_optind, int argc, char **argv) -{ - if (option == NULL || strcmp(option, "!") != 0) - return false; - - fprintf(stderr, "Using intrapositioned negation " - "(`--option ! this`) is deprecated in favor of " - "extrapositioned (`! --option this`).\n"); - - if (*invert) - xt_params->exit_err(PARAMETER_PROBLEM, - "Multiple `!' flags not allowed"); - *invert = true; - if (my_optind != NULL) { - optarg = argv[*my_optind]; - ++*my_optind; - if (argc && *my_optind > argc) - xt_params->exit_err(PARAMETER_PROBLEM, - "no argument following `!'"); - } - - return true; -} - const struct xtables_pprot xtables_chain_protos[] = { {"tcp", IPPROTO_TCP}, {"sctp", IPPROTO_SCTP}, -- cgit v1.2.3 From 3eab786d6a687187556c92b3dc0f0664d8352471 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 10 Jul 2011 11:47:46 +0200 Subject: libxtables: set clone's initial data to NULL Avoid a crash in xs_init_match when a clone's m->udata points at the parent. Signed-off-by: Jan Engelhardt --- iptables/xtables.c | 1 + 1 file changed, 1 insertion(+) diff --git a/iptables/xtables.c b/iptables/xtables.c index b05df97b..1a5e568c 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -632,6 +632,7 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, /* Second and subsequent clones */ clone = xtables_malloc(sizeof(struct xtables_match)); memcpy(clone, ptr, sizeof(struct xtables_match)); + clone->udata = NULL; clone->mflags = 0; /* This is a clone: */ clone->next = clone; -- cgit v1.2.3 From 34d9ce1b80618eebcf63e933cf4a15cc5482c0d2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 10 Jul 2011 12:48:42 +0200 Subject: libxt_conntrack: restore network-byte order for v1,v2 References: http://bugs.debian.org/632804 References: http://marc.info/?l=netfilter-devel&m=130999299016674&w=2 Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.c | 46 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index e1d85755..96400a11 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -110,9 +110,41 @@ static const struct xt_option_entry conntrack_mt_opts_v0[] = { }; #undef s +#define s struct xt_conntrack_mtinfo2 /* for v1-v2 */ +/* We exploit the fact that v1-v2 share the same layout */ +static const struct xt_option_entry conntrack2_mt_opts[] = { + {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, + .flags = XTOPT_INVERT}, + {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctreplsrc", .id = O_CTREPLSRC, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctrepldst", .id = O_CTREPLDST, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctstatus", .id = O_CTSTATUS, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC, + .flags = XTOPT_INVERT}, + {.name = "ctorigsrcport", .id = O_CTORIGSRCPORT, .type = XTTYPE_PORT, + .flags = XTOPT_INVERT | XTOPT_NBO}, + {.name = "ctorigdstport", .id = O_CTORIGDSTPORT, .type = XTTYPE_PORT, + .flags = XTOPT_INVERT | XTOPT_NBO}, + {.name = "ctreplsrcport", .id = O_CTREPLSRCPORT, .type = XTTYPE_PORT, + .flags = XTOPT_INVERT | XTOPT_NBO}, + {.name = "ctrepldstport", .id = O_CTREPLDSTPORT, .type = XTTYPE_PORT, + .flags = XTOPT_INVERT | XTOPT_NBO}, + {.name = "ctdir", .id = O_CTDIR, .type = XTTYPE_STRING}, + XTOPT_TABLEEND, +}; +#undef s + #define s struct xt_conntrack_mtinfo3 /* for v1-v3 */ /* We exploit the fact that v1-v3 share the same layout */ -static const struct xt_option_entry conntrack_mt_opts[] = { +static const struct xt_option_entry conntrack3_mt_opts[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, @@ -992,7 +1024,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt4_print, .save = conntrack1_mt4_save, - .x6_options = conntrack_mt_opts, + .x6_options = conntrack2_mt_opts, }, { .version = XTABLES_VERSION, @@ -1006,7 +1038,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt6_print, .save = conntrack1_mt6_save, - .x6_options = conntrack_mt_opts, + .x6_options = conntrack2_mt_opts, }, { .version = XTABLES_VERSION, @@ -1020,7 +1052,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt_print, .save = conntrack2_mt_save, - .x6_options = conntrack_mt_opts, + .x6_options = conntrack2_mt_opts, }, { .version = XTABLES_VERSION, @@ -1034,7 +1066,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt6_print, .save = conntrack2_mt6_save, - .x6_options = conntrack_mt_opts, + .x6_options = conntrack2_mt_opts, }, { .version = XTABLES_VERSION, @@ -1048,7 +1080,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack3_mt_print, .save = conntrack3_mt_save, - .x6_options = conntrack_mt_opts, + .x6_options = conntrack3_mt_opts, }, { .version = XTABLES_VERSION, @@ -1062,7 +1094,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack3_mt6_print, .save = conntrack3_mt6_save, - .x6_options = conntrack_mt_opts, + .x6_options = conntrack3_mt_opts, }, }; -- cgit v1.2.3 From d22ceae71eaae9f641e002074fb49cd7925a7c2f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 10 Jul 2011 13:13:49 +0200 Subject: libxt_conntrack: move more data into the xt_option_entry Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index 96400a11..8e1777e3 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -93,7 +93,8 @@ static const struct xt_option_entry conntrack_mt_opts_v0[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, - .flags = XTOPT_INVERT}, + .flags = XTOPT_INVERT, + XTOPT_POINTER(s, tuple[IP_CT_DIR_ORIGINAL].dst.protonum)}, {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOST, .flags = XTOPT_INVERT}, {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOST, @@ -110,13 +111,13 @@ static const struct xt_option_entry conntrack_mt_opts_v0[] = { }; #undef s -#define s struct xt_conntrack_mtinfo2 /* for v1-v2 */ -/* We exploit the fact that v1-v2 share the same layout */ +#define s struct xt_conntrack_mtinfo2 +/* We exploit the fact that v1-v2 share the same xt_o_e layout */ static const struct xt_option_entry conntrack2_mt_opts[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, - .flags = XTOPT_INVERT}, + .flags = XTOPT_INVERT, XTOPT_POINTER(s, l4proto)}, {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK, .flags = XTOPT_INVERT}, {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK, @@ -148,7 +149,7 @@ static const struct xt_option_entry conntrack3_mt_opts[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, - .flags = XTOPT_INVERT}, + .flags = XTOPT_INVERT, XTOPT_POINTER(s, l4proto)}, {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK, .flags = XTOPT_INVERT}, {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK, @@ -337,8 +338,6 @@ static void conntrack_parse(struct xt_option_call *cb) case O_CTPROTO: if (cb->invert) sinfo->invflags |= XT_CONNTRACK_PROTO; - sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = cb->val.protocol; - if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0 && (sinfo->invflags & XT_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, @@ -401,7 +400,6 @@ static void conntrack_mt_parse(struct xt_option_call *cb, uint8_t rev) info->invert_flags |= XT_CONNTRACK_STATE; break; case O_CTPROTO: - info->l4proto = cb->val.protocol; if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "conntrack: rule would " "never match protocol"); -- cgit v1.2.3 From 1757ec846419c76da4e104f9675b40e05ac3eee6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 22 Jul 2011 12:11:03 +0200 Subject: extensions: use multi-target registration Signed-off-by: Jan Engelhardt --- extensions/libxt_TCPMSS.c | 56 +++++++++++++++++++++++------------------------ extensions/libxt_TEE.c | 56 +++++++++++++++++++++++------------------------ 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/extensions/libxt_TCPMSS.c b/extensions/libxt_TCPMSS.c index 2266326d..48ab0445 100644 --- a/extensions/libxt_TCPMSS.c +++ b/extensions/libxt_TCPMSS.c @@ -91,36 +91,36 @@ static void TCPMSS_save(const void *ip, const struct xt_entry_target *target) printf(" --set-mss %u", mssinfo->mss); } -static struct xtables_target tcpmss_target = { - .family = NFPROTO_IPV4, - .name = "TCPMSS", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), - .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), - .help = TCPMSS_help, - .print = TCPMSS_print, - .save = TCPMSS_save, - .x6_parse = TCPMSS_parse, - .x6_fcheck = TCPMSS_check, - .x6_options = TCPMSS4_opts, -}; - -static struct xtables_target tcpmss_target6 = { - .family = NFPROTO_IPV6, - .name = "TCPMSS", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), - .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), - .help = TCPMSS_help6, - .print = TCPMSS_print, - .save = TCPMSS_save, - .x6_parse = TCPMSS_parse, - .x6_fcheck = TCPMSS_check, - .x6_options = TCPMSS6_opts, +static struct xtables_target tcpmss_tg_reg[] = { + { + .family = NFPROTO_IPV4, + .name = "TCPMSS", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), + .help = TCPMSS_help, + .print = TCPMSS_print, + .save = TCPMSS_save, + .x6_parse = TCPMSS_parse, + .x6_fcheck = TCPMSS_check, + .x6_options = TCPMSS4_opts, + }, + { + .family = NFPROTO_IPV6, + .name = "TCPMSS", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), + .help = TCPMSS_help6, + .print = TCPMSS_print, + .save = TCPMSS_save, + .x6_parse = TCPMSS_parse, + .x6_fcheck = TCPMSS_check, + .x6_options = TCPMSS6_opts, + }, }; void _init(void) { - xtables_register_target(&tcpmss_target); - xtables_register_target(&tcpmss_target6); + xtables_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); } diff --git a/extensions/libxt_TEE.c b/extensions/libxt_TEE.c index c89e5809..92c7601c 100644 --- a/extensions/libxt_TEE.c +++ b/extensions/libxt_TEE.c @@ -92,36 +92,36 @@ static void tee_tg6_save(const void *ip, const struct xt_entry_target *target) printf(" --oif %s", info->oif); } -static struct xtables_target tee_tg_reg = { - .name = "TEE", - .version = XTABLES_VERSION, - .revision = 1, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), - .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), - .help = tee_tg_help, - .print = tee_tg_print, - .save = tee_tg_save, - .x6_parse = xtables_option_parse, - .x6_options = tee_tg_opts, -}; - -static struct xtables_target tee_tg6_reg = { - .name = "TEE", - .version = XTABLES_VERSION, - .revision = 1, - .family = NFPROTO_IPV6, - .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), - .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), - .help = tee_tg_help, - .print = tee_tg6_print, - .save = tee_tg6_save, - .x6_parse = xtables_option_parse, - .x6_options = tee_tg_opts, +static struct xtables_target tee_tg_reg[] = { + { + .name = "TEE", + .version = XTABLES_VERSION, + .revision = 1, + .family = NFPROTO_IPV4, + .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), + .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), + .help = tee_tg_help, + .print = tee_tg_print, + .save = tee_tg_save, + .x6_parse = xtables_option_parse, + .x6_options = tee_tg_opts, + }, + { + .name = "TEE", + .version = XTABLES_VERSION, + .revision = 1, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), + .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), + .help = tee_tg_help, + .print = tee_tg6_print, + .save = tee_tg6_save, + .x6_parse = xtables_option_parse, + .x6_options = tee_tg_opts, + }, }; void _init(void) { - xtables_register_target(&tee_tg_reg); - xtables_register_target(&tee_tg6_reg); + xtables_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); } -- cgit v1.2.3 From 4d8656ad9d0afd04820f125a85a7b673c7e74fe6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 22 Jul 2011 12:25:43 +0200 Subject: libxt_TCPMSS: restore build with IPv6-less libcs Commit v1.4.10-149-gea2a02f added an netinet/ip6.h include, which is not available on systems without IPv6 header files. Signed-off-by: Jan Engelhardt --- configure.ac | 1 + extensions/GNUmakefile.in | 2 +- extensions/libxt_TCPMSS.c | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 5cb1b1bb..6aa0b2a7 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,7 @@ if test "$ac_cv_header_linux_ip_vs_h" != "yes"; then fi; AC_SUBST([blacklist_modules]) +AC_CHECK_SIZEOF([struct ip6_hdr], [], [#include ]) AM_CONDITIONAL([ENABLE_STATIC], [test "$enable_static" = "yes"]) AM_CONDITIONAL([ENABLE_SHARED], [test "$enable_shared" = "yes"]) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index fbaf2eca..2b48d841 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -21,7 +21,7 @@ regular_CPPFLAGS := @regular_CPPFLAGS@ kinclude_CPPFLAGS := @kinclude_CPPFLAGS@ AM_CFLAGS := ${regular_CFLAGS} -AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CPPFLAGS} +AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_builddir} -I${top_srcdir}/include ${kinclude_CPPFLAGS} AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@ ifeq (${V},) diff --git a/extensions/libxt_TCPMSS.c b/extensions/libxt_TCPMSS.c index 48ab0445..4b71e44a 100644 --- a/extensions/libxt_TCPMSS.c +++ b/extensions/libxt_TCPMSS.c @@ -2,10 +2,10 @@ * * Copyright (c) 2000 Marc Boucher */ +#include "config.h" #include #include #include -#include #include enum { @@ -34,7 +34,7 @@ static void TCPMSS_help(void) static void TCPMSS_help6(void) { - __TCPMSS_help(sizeof(struct ip6_hdr)); + __TCPMSS_help(SIZEOF_STRUCT_IP6_HDR); } static const struct xt_option_entry TCPMSS4_opts[] = { @@ -47,7 +47,7 @@ static const struct xt_option_entry TCPMSS4_opts[] = { static const struct xt_option_entry TCPMSS6_opts[] = { {.name = "set-mss", .id = O_SET_MSS, .type = XTTYPE_UINT16, - .min = 0, .max = UINT16_MAX - sizeof(struct ip6_hdr), + .min = 0, .max = UINT16_MAX - SIZEOF_STRUCT_IP6_HDR, .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_tcpmss_info, mss)}, {.name = "clamp-mss-to-pmtu", .id = O_CLAMP_MSS, .type = XTTYPE_NONE}, XTOPT_TABLEEND, -- cgit v1.2.3 From 47b5855bc396876295c6432e553351123a62534b Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 22 Jul 2011 14:37:34 +0200 Subject: Bump version to 1.4.12 Signed-off-by: Patrick McHardy --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 5cb1b1bb..252ff39e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.11.1]) +AC_INIT([iptables], [1.4.12]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=7 -- cgit v1.2.3 From 67156c0b9a3d35f5e7836e5683d8ca0b46ac36ca Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 1 Aug 2011 20:08:42 +0200 Subject: libxt_string: define _GNU_SOURCE for strnlen On RHEL-5.6 and clones with its gcc-4.1.2 and glibc-2.5: libxt_string.c: In function "parse_string": libxt_string.c:84: warning: implicit declaration of function "strnlen" Signed-off-by: Jan Engelhardt --- extensions/libxt_string.c | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/libxt_string.c b/extensions/libxt_string.c index eef0b081..8cee3359 100644 --- a/extensions/libxt_string.c +++ b/extensions/libxt_string.c @@ -20,6 +20,7 @@ * updated to work with slightly modified * ipt_string_info. */ +#define _GNU_SOURCE 1 /* strnlen for older glibcs */ #include #include #include -- cgit v1.2.3 From 41a9b481693b4c43c16d0588cc558dd455168af0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 1 Aug 2011 20:14:57 +0200 Subject: build: workaround broken linux-headers on RHEL-5 maigc.h was not invented yet, but they do not ship proc_fs.h either, duh. Signed-off-by: Jan Engelhardt --- iptables/xtables.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iptables/xtables.c b/iptables/xtables.c index 1a5e568c..233efa30 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -37,6 +37,8 @@ # include /* for PROC_SUPER_MAGIC */ #elif defined(HAVE_LINUX_PROC_FS_H) # include /* Linux 2.4 */ +#else +# define PROC_SUPER_MAGIC 0x9fa0 #endif #include -- cgit v1.2.3 From 43896add0eb9c6bc94b7323e76f137d402e0f7fe Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 1 Aug 2011 20:22:04 +0200 Subject: build: strengthen check for overlong lladdr components ethermac[i] > UINT8_MAX is quite pointless, because ethermac[i] is just uint8_t. To catch values that are not in the range "00"-"ff", use a string length check (end-arg>2). I am willingly using 2 there, because no one is going to specify an Ethernet LL address as "0x00:0x24:0xbe:0xc2:0x7f:0x16" -- because it is always interpreted as hexadecimal anyway even without the 0x prefix. xtoptions.c: In function "xtopt_parse_ethermac": xtoptions.c:760:3: warning: comparison is always false due to limited range of data type xtoptions.c:766:2: warning: comparison is always false due to limited range of data type Signed-off-by: Jan Engelhardt --- iptables/xtoptions.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iptables/xtoptions.c b/iptables/xtoptions.c index 1423724b..7095e3ea 100644 --- a/iptables/xtoptions.c +++ b/iptables/xtoptions.c @@ -757,13 +757,13 @@ static void xtopt_parse_ethermac(struct xt_option_call *cb) for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) { cb->val.ethermac[i] = strtoul(arg, &end, 16); - if (cb->val.ethermac[i] > UINT8_MAX || *end != ':') + if (*end != ':' || end - arg > 2) goto out; arg = end + 1; } i = ARRAY_SIZE(cb->val.ethermac) - 1; cb->val.ethermac[i] = strtoul(arg, &end, 16); - if (cb->val.ethermac[i] > UINT8_MAX || *end != '\0') + if (*end != '\0' || end - arg > 2) goto out; if (cb->entry->flags & XTOPT_PUT) memcpy(XTOPT_MKPTR(cb), cb->val.ethermac, -- cgit v1.2.3 From fa2ce1ca2a3448350dee30c153dafe65abe7135d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 1 Aug 2011 21:26:01 +0200 Subject: build: abort autogen on subcommand failure Needed to stop an automated build process when automake requirements are not fulfilled. Signed-off-by: Jan Engelhardt --- autogen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index 62a89e1b..a0c4395f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh -e autoreconf -fi; rm -Rf autom4te*.cache; -- cgit v1.2.3 From 4982fe43cf247cda6ddb946a8f1fd58177124735 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 8 Aug 2011 02:38:41 +0200 Subject: libipq: add pkgconfig file This is just to make sure that projects (still) using it do so with the right cflags, e.g. for when the include file ends up in a non-standard location due to ./configure having been called with --include=/somewhere/else. Signed-off-by: Jan Engelhardt --- configure.ac | 3 ++- libipq/.gitignore | 1 + libipq/Makefile.am | 2 ++ libipq/libipq.pc.in | 11 +++++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 libipq/.gitignore create mode 100644 libipq/libipq.pc.in diff --git a/configure.ac b/configure.ac index 6aa0b2a7..ab824a4f 100644 --- a/configure.ac +++ b/configure.ac @@ -111,6 +111,7 @@ AC_SUBST([libxtables_vmajor]) AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc - libipq/Makefile libiptc/Makefile libiptc/libiptc.pc utils/Makefile + libipq/Makefile libipq/libipq.pc + libiptc/Makefile libiptc/libiptc.pc utils/Makefile include/xtables.h include/iptables/internal.h]) AC_OUTPUT diff --git a/libipq/.gitignore b/libipq/.gitignore new file mode 100644 index 00000000..6cb21a35 --- /dev/null +++ b/libipq/.gitignore @@ -0,0 +1 @@ +/libipq.pc diff --git a/libipq/Makefile.am b/libipq/Makefile.am index 93e5b1c8..9e3a2ca6 100644 --- a/libipq/Makefile.am +++ b/libipq/Makefile.am @@ -9,3 +9,5 @@ man_MANS = ipq_create_handle.3 ipq_destroy_handle.3 ipq_errstr.3 \ ipq_get_msgerr.3 ipq_get_packet.3 ipq_message_type.3 \ ipq_perror.3 ipq_read.3 ipq_set_mode.3 ipq_set_verdict.3 \ libipq.3 + +pkgconfig_DATA = libipq.pc diff --git a/libipq/libipq.pc.in b/libipq/libipq.pc.in new file mode 100644 index 00000000..ea31ec73 --- /dev/null +++ b/libipq/libipq.pc.in @@ -0,0 +1,11 @@ + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libipq +Description: Interface to the (old) ip_queue mechanism +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lipq +Cflags: -I${includedir} -- cgit v1.2.3 From bc3aeaafcf33e3e6a51948568f4f7a16304f619b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 15 Aug 2011 17:06:20 +0200 Subject: libxt_u32: fix missing allowance for inversion Signed-off-by: Jan Engelhardt --- extensions/libxt_u32.c | 2 +- tests/options-most.rules | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_u32.c b/extensions/libxt_u32.c index 774d5eac..6d024fb6 100644 --- a/extensions/libxt_u32.c +++ b/extensions/libxt_u32.c @@ -24,7 +24,7 @@ enum { static const struct xt_option_entry u32_opts[] = { {.name = "u32", .id = O_U32, .type = XTTYPE_STRING, - .flags = XTOPT_MAND}, + .flags = XTOPT_MAND | XTOPT_INVERT}, XTOPT_TABLEEND, }; diff --git a/tests/options-most.rules b/tests/options-most.rules index 7298a1f9..c2e30f24 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -40,7 +40,7 @@ -A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -A INPUT -p tcp -m tos --tos 0xff/0x01 --A INPUT -p tcp -m u32 --u32 "0x0=0x0" -m u32 --u32 "0x0=0x0" +-A INPUT -p tcp -m u32 ! --u32 "0x0=0x0" -m u32 ! --u32 "0x0=0x0" -A INPUT -p tcp -m hbh -m hbh -m hl --hl-eq 1 -m ipv6header --header hop-by-hop --soft -A INPUT -m ipv6header --header hop-by-hop --soft -m rt --rt-type 2 --rt-segsleft 2 --rt-len 5 -m rt --rt-type 0 --rt-segsleft 2 --rt-len 5 --rt-0-res --rt-0-addrs ::1 --rt-0-not-strict -m rt --rt-type 0 --rt-segsleft 2 --rt-len 5 --rt-0-res --rt-0-addrs ::1,::2 --rt-0-not-strict -A INPUT -p tcp -m cpu --cpu 1 -m tcp --sport 1:2 --dport 1:2 --tcp-option 1 --tcp-flags FIN,SYN,RST,ACK SYN -m cpu --cpu 1 -- cgit v1.2.3 From 085b233bd85173082cc872563505ad3755ac5455 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 20 Aug 2011 18:26:34 +0200 Subject: libxt_set: update man page about kernel support on the feature Signed-off-by: Jan Engelhardt --- extensions/libxt_SET.man | 5 ++--- extensions/libxt_set.man | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/extensions/libxt_SET.man b/extensions/libxt_SET.man index 739be414..63eb3831 100644 --- a/extensions/libxt_SET.man +++ b/extensions/libxt_SET.man @@ -21,6 +21,5 @@ one from the set definition when adding entry if it already exists, reset the timeout value to the specified one or to the default from the set definition .PP -Use of -j SET requires that ipset kernel support is provided. As standard -kernels do not ship this currently, the ipset or Xtables-addons package needs -to be installed. +Use of -j SET requires that ipset kernel support is provided, which, for +standard kernels, is the case since Linux 2.6.39. diff --git a/extensions/libxt_set.man b/extensions/libxt_set.man index 01b115f0..1ad90859 100644 --- a/extensions/libxt_set.man +++ b/extensions/libxt_set.man @@ -18,6 +18,5 @@ found in the specified set. The option \fB\-\-match\-set\fP can be replaced by \fB\-\-set\fP if that does not clash with an option of other extensions. .PP -Use of -m set requires that ipset kernel support is provided. As standard -kernels do not ship this currently, the ipset or Xtables-addons package needs -to be installed. +Use of -m set requires that ipset kernel support is provided, which, for +standard kernels, is the case since Linux 2.6.39. -- cgit v1.2.3 From 3dafef40228c372976eb714836ea097115d8fd03 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 20 Aug 2011 18:26:48 +0200 Subject: libxt_tcp: always print the mask parts 0xFF is unlikely to happen (given that ALL translates to 0x3F at most), but assuming that through magic, 0xFF was put into memory, iptables -S/iptables-save would ignore printing it, practically outputting just one argument to --tcp-flags which currently wants two. Signed-off-by: Jan Engelhardt --- extensions/libxt_tcp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c index 3940d91e..e849fa21 100644 --- a/extensions/libxt_tcp.c +++ b/extensions/libxt_tcp.c @@ -357,9 +357,7 @@ static void tcp_save(const void *ip, const struct xt_entry_match *match) if (tcpinfo->invflags & XT_TCP_INV_FLAGS) printf(" !"); printf(" --tcp-flags "); - if (tcpinfo->flg_mask != 0xFF) { - print_tcpf(tcpinfo->flg_mask); - } + print_tcpf(tcpinfo->flg_mask); printf(" "); print_tcpf(tcpinfo->flg_cmp); } -- cgit v1.2.3 From b6ad32fe050126e5557c19ab970547d1472e4728 Mon Sep 17 00:00:00 2001 From: Bernard Massot Date: Wed, 10 Aug 2011 14:56:00 +0200 Subject: doc: fix typo in libxt_TRACE References: http://bugzilla.netfilter.org/show_bug.cgi?id=736 Signed-off-by: Jan Engelhardt --- extensions/libxt_TRACE.man | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_TRACE.man b/extensions/libxt_TRACE.man index ea0ce0fa..8d590a52 100644 --- a/extensions/libxt_TRACE.man +++ b/extensions/libxt_TRACE.man @@ -1,4 +1,4 @@ -This target marks packes so that the kernel will log every rule which match +This target marks packets so that the kernel will log every rule which match the packets as those traverse the tables, chains, rules. .PP A logging backend, such as ip(6)t_LOG or nfnetlink_log, must be loaded for this -- cgit v1.2.3 From 886a89bf378e079e807cda2eb43573ca6c886d0a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 20 Aug 2011 21:00:45 +0200 Subject: libxt_set: put differing variable names in directly Signed-off-by: Jan Engelhardt --- extensions/libxt_SET.c | 13 +++---------- extensions/libxt_set.c | 11 +++-------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/extensions/libxt_SET.c b/extensions/libxt_SET.c index 04466037..a11db395 100644 --- a/extensions/libxt_SET.c +++ b/extensions/libxt_SET.c @@ -143,9 +143,6 @@ set_target_save_v0(const void *ip, const struct xt_entry_target *target) } /* Revision 1 */ - -#define set_target_help_v1 set_target_help_v0 - static void set_target_init_v1(struct xt_entry_target *target) { @@ -204,8 +201,6 @@ set_target_parse_v1(int c, char **argv, int invert, unsigned int *flags, return 1; } -#define set_target_check_v1 set_target_check_v0 - static void print_target(const char *prefix, const struct xt_set_info *info) { @@ -242,8 +237,6 @@ set_target_save_v1(const void *ip, const struct xt_entry_target *target) print_target("--del-set", &info->del_set); } -#define set_target_opts_v1 set_target_opts_v0 - /* Revision 2 */ static void @@ -376,13 +369,13 @@ static struct xtables_target set_tg_reg[] = { .family = NFPROTO_UNSPEC, .size = XT_ALIGN(sizeof(struct xt_set_info_target_v1)), .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v1)), - .help = set_target_help_v1, + .help = set_target_help_v0, .init = set_target_init_v1, .parse = set_target_parse_v1, - .final_check = set_target_check_v1, + .final_check = set_target_check_v0, .print = set_target_print_v1, .save = set_target_save_v1, - .extra_opts = set_target_opts_v1, + .extra_opts = set_target_opts_v0, }, { .name = "SET", diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c index 6b39147e..77e3f07e 100644 --- a/extensions/libxt_set.c +++ b/extensions/libxt_set.c @@ -128,11 +128,6 @@ set_save_v0(const void *ip, const struct xt_entry_match *match) } /* Revision 1 */ - -#define set_help_v1 set_help_v0 -#define set_opts_v1 set_opts_v0 -#define set_check_v1 set_check_v0 - static int set_parse_v1(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) @@ -232,12 +227,12 @@ static struct xtables_match set_mt_reg[] = { .family = NFPROTO_UNSPEC, .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), - .help = set_help_v1, + .help = set_help_v0, .parse = set_parse_v1, - .final_check = set_check_v1, + .final_check = set_check_v0, .print = set_print_v1, .save = set_save_v1, - .extra_opts = set_opts_v1, + .extra_opts = set_opts_v0, }, }; -- cgit v1.2.3 From 3716dfd7eac3afa7fb3098952550e510c8df0220 Mon Sep 17 00:00:00 2001 From: Dwight Davis Date: Fri, 12 Aug 2011 17:02:09 -0400 Subject: libxt_string: fix space around arguments Fix oversight from commit v1.4.11~80. References: http://bugs.debian.org/637499 Signed-off-by: Jan Engelhardt --- extensions/libxt_string.c | 4 ++-- tests/options-most.rules | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_string.c b/extensions/libxt_string.c index 8cee3359..257f5f85 100644 --- a/extensions/libxt_string.c +++ b/extensions/libxt_string.c @@ -229,7 +229,7 @@ print_hex_string(const char *str, const unsigned short int len) { unsigned int i; /* start hex block */ - printf("\"|"); + printf(" \"|"); for (i=0; i < len; i++) { /* see if we need to prepend a zero */ if ((unsigned char) str[i] <= 0x0F) @@ -238,7 +238,7 @@ print_hex_string(const char *str, const unsigned short int len) printf("%x", (unsigned char) str[i]); } /* close hex block */ - printf("|\" "); + printf("|\""); } static void diff --git a/tests/options-most.rules b/tests/options-most.rules index c2e30f24..4a3cd99f 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -37,6 +37,7 @@ -A INPUT -p tcp -m recent --rcheck --name DEFAULT --rsource -A INPUT -p tcp -m socket --transparent -A INPUT -p tcp -m string --string "foobar" --algo kmp --from 1 --to 2 --icase +-A INPUT -p tcp -m string --hex-string "|00|" --algo kmp --from 1 --to 2 --icase -A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -A INPUT -p tcp -m tos --tos 0xff/0x01 -- cgit v1.2.3 From 79e1f97a966e82155ebc00b30e3b60c48d060448 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 08:43:15 +0200 Subject: doc: clarify libxt_connlimit defaults Signed-off-by: Jan Engelhardt --- extensions/libxt_connlimit.man | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_connlimit.man b/extensions/libxt_connlimit.man index bd369a69..ad9f40fa 100644 --- a/extensions/libxt_connlimit.man +++ b/extensions/libxt_connlimit.man @@ -13,7 +13,8 @@ Group hosts using the prefix length. For IPv4, this must be a number between maximum prefix length for the applicable protocol is used. .TP \fB\-\-connlimit\-saddr\fP -Apply the limit onto the source group. +Apply the limit onto the source group. This is the default if +\-\-connlimit\-daddr is not specified. .TP \fB\-\-connlimit\-daddr\fP Apply the limit onto the destination group. -- cgit v1.2.3 From 107dca41800f7aeb6600438ea3aaf0fd66019417 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 08:46:49 +0200 Subject: libxt_conntrack: remove one misleading comment Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index 8e1777e3..a4011252 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -143,8 +143,8 @@ static const struct xt_option_entry conntrack2_mt_opts[] = { }; #undef s -#define s struct xt_conntrack_mtinfo3 /* for v1-v3 */ -/* We exploit the fact that v1-v3 share the same layout */ +#define s struct xt_conntrack_mtinfo3 +/* Difference from v2 is the non-NBO form. */ static const struct xt_option_entry conntrack3_mt_opts[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, -- cgit v1.2.3 From d152d6acd6751884621e0b760fecc0d652aea479 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 09:05:31 +0200 Subject: libxt_dccp: restore missing XTOPT_INVERT tags for options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This regression goes back to v1.4.11~19^2. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_dccp.c | 5 +++-- tests/options-most.rules | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c index 28c59b9d..0fc5f7d7 100644 --- a/extensions/libxt_dccp.c +++ b/extensions/libxt_dccp.c @@ -50,9 +50,10 @@ static const struct xt_option_entry dccp_opts[] = { .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)}, {.name = "dport", .id = O_DEST_PORT, .type = XTTYPE_PORTRC, .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)}, - {.name = "dccp-types", .id = O_DCCP_TYPES, .type = XTTYPE_STRING}, + {.name = "dccp-types", .id = O_DCCP_TYPES, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, {.name = "dccp-option", .id = O_DCCP_OPTION, .type = XTTYPE_UINT8, - .min = 1, .max = UINT8_MAX, .flags = XTOPT_PUT, + .min = 1, .max = UINT8_MAX, .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, option)}, XTOPT_TABLEEND, }; diff --git a/tests/options-most.rules b/tests/options-most.rules index 4a3cd99f..ab7f5866 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -46,6 +46,7 @@ -A INPUT -m ipv6header --header hop-by-hop --soft -m rt --rt-type 2 --rt-segsleft 2 --rt-len 5 -m rt --rt-type 0 --rt-segsleft 2 --rt-len 5 --rt-0-res --rt-0-addrs ::1 --rt-0-not-strict -m rt --rt-type 0 --rt-segsleft 2 --rt-len 5 --rt-0-res --rt-0-addrs ::1,::2 --rt-0-not-strict -A INPUT -p tcp -m cpu --cpu 1 -m tcp --sport 1:2 --dport 1:2 --tcp-option 1 --tcp-flags FIN,SYN,RST,ACK SYN -m cpu --cpu 1 -A INPUT -p dccp -m cpu --cpu 1 -m dccp --sport 1:2 --dport 3:4 -m cpu --cpu 1 +-A INPUT -p dccp -m dccp ! --sport 1:2 ! --dport 3:4 ! --dccp-types REQUEST,RESPONSE ! --dccp-option 1 -A INPUT -p udp -m cpu --cpu 1 -m udp --sport 1:2 --dport 3:4 -m cpu --cpu 1 -A INPUT -p sctp -m cpu --cpu 1 -m sctp --sport 1:2 --dport 3:4 --chunk-types all INIT,SACK -m cpu --cpu 1 -A INPUT -p esp -m esp --espspi 1:2 -- cgit v1.2.3 From 7e66a657d0fbb8a3f27fd78c7bb27859d44002aa Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 09:08:04 +0200 Subject: libxt_dccp: fix deprecated intrapositional ordering of ! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bug goes back to v1.4.3~63. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_dccp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c index 0fc5f7d7..4de07cca 100644 --- a/extensions/libxt_dccp.c +++ b/extensions/libxt_dccp.c @@ -262,13 +262,14 @@ static void dccp_save(const void *ip, const struct xt_entry_match *match) } if (einfo->flags & XT_DCCP_TYPE) { - printf(" --dccp-type"); - print_types(einfo->typemask, einfo->invflags & XT_DCCP_TYPE,0); + printf("%s --dccp-type", + einfo->invflags & XT_DCCP_TYPE ? " !" : ""); + print_types(einfo->typemask, false, 0); } if (einfo->flags & XT_DCCP_OPTION) { - printf(" --dccp-option %s%u", - einfo->typemask & XT_DCCP_OPTION ? "! " : "", + printf("%s --dccp-option %u", + einfo->typemask & XT_DCCP_OPTION ? " !" : "", einfo->option); } } -- cgit v1.2.3 From f677e7b10c72bd3007c89d51eea13a0c2c3d262b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 09:12:27 +0200 Subject: libxt_dccp: spell out option name on save MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This glitch goes back to commit v1.3.4~11. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_dccp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c index 4de07cca..09ef16e0 100644 --- a/extensions/libxt_dccp.c +++ b/extensions/libxt_dccp.c @@ -262,7 +262,7 @@ static void dccp_save(const void *ip, const struct xt_entry_match *match) } if (einfo->flags & XT_DCCP_TYPE) { - printf("%s --dccp-type", + printf("%s --dccp-types", einfo->invflags & XT_DCCP_TYPE ? " !" : ""); print_types(einfo->typemask, false, 0); } -- cgit v1.2.3 From ca48066aaa8179025c0b4e17ed40a4bc12487190 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 09:15:20 +0200 Subject: libxt_dccp: provide man pages options in short help too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This omission goes back to commit v1.3.4~11. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_dccp.c | 5 ++++- extensions/libxt_dccp.man | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c index 09ef16e0..4e52b38c 100644 --- a/extensions/libxt_dccp.c +++ b/extensions/libxt_dccp.c @@ -37,7 +37,10 @@ static void dccp_help(void) "[!] --source-port port[:port] match source port(s)\n" " --sport ...\n" "[!] --destination-port port[:port] match destination port(s)\n" -" --dport ...\n"); +" --dport ...\n" +"[!] --dccp-types type[,...] match when packet is one of the given types\n" +"[!] --dccp-option option match if option (by number!) is set\n" +); } #define s struct xt_dccp_info diff --git a/extensions/libxt_dccp.man b/extensions/libxt_dccp.man index 82c3f703..71beb4b1 100644 --- a/extensions/libxt_dccp.man +++ b/extensions/libxt_dccp.man @@ -9,4 +9,4 @@ list of packet types. Packet types are: .BR "REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID" . .TP [\fB!\fP] \fB\-\-dccp\-option\fP \fInumber\fP -Match if DCP option set. +Match if DCCP option set. -- cgit v1.2.3 From f17fd48448aafdc762a3b439864bcb1127b0da6c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 09:39:21 +0200 Subject: libxt_dccp: fix random output of ! on --dccp-option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dccp-option tests info->typemask, but it really should look at info->invflags instead. This bug goes back to commit v1.3.4~11. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_dccp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c index 4e52b38c..a35cabbd 100644 --- a/extensions/libxt_dccp.c +++ b/extensions/libxt_dccp.c @@ -272,7 +272,7 @@ static void dccp_save(const void *ip, const struct xt_entry_match *match) if (einfo->flags & XT_DCCP_OPTION) { printf("%s --dccp-option %u", - einfo->typemask & XT_DCCP_OPTION ? " !" : "", + einfo->invflags & XT_DCCP_OPTION ? " !" : "", einfo->option); } } -- cgit v1.2.3 From 83c342b36a7048ab86827e09a4916064837293d3 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 08:52:56 +0200 Subject: libxt_dscp: restore inversion support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_dscp.c | 5 +++-- tests/options-most.rules | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_dscp.c b/extensions/libxt_dscp.c index 69533d6b..02b22a4e 100644 --- a/extensions/libxt_dscp.c +++ b/extensions/libxt_dscp.c @@ -43,9 +43,10 @@ static void dscp_help(void) static const struct xt_option_entry dscp_opts[] = { {.name = "dscp", .id = O_DSCP, .excl = F_DSCP_CLASS, .type = XTTYPE_UINT8, .min = 0, .max = XT_DSCP_MAX, - .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_dscp_info, dscp)}, + .flags = XTOPT_INVERT | XTOPT_PUT, + XTOPT_POINTER(struct xt_dscp_info, dscp)}, {.name = "dscp-class", .id = O_DSCP_CLASS, .excl = F_DSCP, - .type = XTTYPE_STRING}, + .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, XTOPT_TABLEEND, }; diff --git a/tests/options-most.rules b/tests/options-most.rules index ab7f5866..4becc2ae 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -20,8 +20,8 @@ -A INPUT -p tcp -m connmark --mark 0x99 -A INPUT -p tcp -m conntrack --ctstate INVALID --ctproto 6 --ctorigsrc fe80::/64 --ctorigdst fe80::/64 --ctreplsrc fe80::/64 --ctrepldst fe80::/64 --ctorigsrcport 12 --ctorigdstport 13 --ctreplsrcport 14 --ctrepldstport 15 --ctstatus EXPECTED --ctexpire 1:2 --ctdir REPLY -A INPUT -p tcp -m cpu --cpu 2 --A INPUT -p tcp -m dscp --dscp 0x04 --A INPUT -p tcp -m dscp --dscp 0x00 +-A INPUT -p tcp -m dscp --dscp 0x04 -m dscp ! --dscp 0x04 +-A INPUT -p tcp -m dscp --dscp 0x00 -m dscp ! --dscp 0x00 -A INPUT -p tcp -m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-mode srcip,dstip --hashlimit-name f1 --hashlimit-htable-size 64 --hashlimit-htable-max 128 --hashlimit-htable-gcinterval 60 --hashlimit-htable-expire 120 --hashlimit-srcmask 24 --hashlimit-dstmask 24 -A INPUT -p tcp -m hashlimit --hashlimit-above 5/sec --hashlimit-burst 5 --hashlimit-name f1 -A INPUT -p tcp -m helper --helper ftp -- cgit v1.2.3 From c148c4ad2e28b94125c0c9954a887f0a473d598b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 09:46:12 +0200 Subject: libxt_hashlimit: default htable-expire must be in milliseconds Bug goes back to v1.4.12~3^2~11. Signed-off-by: Jan Engelhardt --- extensions/libxt_hashlimit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index a838680c..89320bb3 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -315,7 +315,7 @@ static void hashlimit_check(struct xt_fcheck_call *cb) xtables_error(PARAMETER_PROBLEM, "You have to specify --hashlimit"); if (!(cb->xflags & F_HTABLE_EXPIRE)) - info->cfg.expire = udata->mult; + info->cfg.expire = udata->mult * 1000; /* from s to msec */ } static void hashlimit_mt_check(struct xt_fcheck_call *cb) @@ -327,7 +327,7 @@ static void hashlimit_mt_check(struct xt_fcheck_call *cb) xtables_error(PARAMETER_PROBLEM, "You have to specify --hashlimit"); if (!(cb->xflags & F_HTABLE_EXPIRE)) - info->cfg.expire = udata->mult; + info->cfg.expire = udata->mult * 1000; /* from s to msec */ } static const struct rates -- cgit v1.2.3 From bca5b9afbe4b3823989f1e78f178203eb3bfa37d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 10:06:18 +0200 Subject: libxt_conntrack: fix --ctproto 0 output First, we are missing XTOPT_PUT when trying to use XTOPT_POINTER. (Next commit will flag this.) Furthermore, l4proto is of type uint16_t, while XTTYPE_PROTOCOL wants a uint8_t so the idea would not work => revert v1.4.12~1^2. Bug goes back to v1.4.12~1^2. Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index a4011252..060b9477 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -93,8 +93,7 @@ static const struct xt_option_entry conntrack_mt_opts_v0[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, - .flags = XTOPT_INVERT, - XTOPT_POINTER(s, tuple[IP_CT_DIR_ORIGINAL].dst.protonum)}, + .flags = XTOPT_INVERT}, {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOST, .flags = XTOPT_INVERT}, {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOST, @@ -117,7 +116,7 @@ static const struct xt_option_entry conntrack2_mt_opts[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, - .flags = XTOPT_INVERT, XTOPT_POINTER(s, l4proto)}, + .flags = XTOPT_INVERT}, {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK, .flags = XTOPT_INVERT}, {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK, @@ -149,7 +148,7 @@ static const struct xt_option_entry conntrack3_mt_opts[] = { {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, - .flags = XTOPT_INVERT, XTOPT_POINTER(s, l4proto)}, + .flags = XTOPT_INVERT}, {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK, .flags = XTOPT_INVERT}, {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK, @@ -336,6 +335,7 @@ static void conntrack_parse(struct xt_option_call *cb) sinfo->invflags |= XT_CONNTRACK_STATE; break; case O_CTPROTO: + sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = cb->val.protocol; if (cb->invert) sinfo->invflags |= XT_CONNTRACK_PROTO; if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0 @@ -400,6 +400,7 @@ static void conntrack_mt_parse(struct xt_option_call *cb, uint8_t rev) info->invert_flags |= XT_CONNTRACK_STATE; break; case O_CTPROTO: + info->l4proto = cb->val.protocol; if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "conntrack: rule would " "never match protocol"); -- cgit v1.2.3 From 735f3d76ccd3a7deab13703d7c227c87c666a97b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 10:14:28 +0200 Subject: xtoptions: flag use of XTOPT_POINTER without XTOPT_PUT When XTOPT_POINTER is used (and yields a non-zero offsetof), we can flag the absence of XTOPT_PUT. Signed-off-by: Jan Engelhardt --- iptables/xtoptions.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/iptables/xtoptions.c b/iptables/xtoptions.c index 7095e3ea..04344af4 100644 --- a/iptables/xtoptions.c +++ b/iptables/xtoptions.c @@ -847,8 +847,14 @@ void xtables_option_metavalidate(const char *name, xt_params->exit_err(OTHER_PROBLEM, "Extension %s uses invalid ID %u\n", name, entry->id); - if (!(entry->flags & XTOPT_PUT)) + if (!(entry->flags & XTOPT_PUT)) { + if (entry->ptroff != 0) + xt_params->exit_err(OTHER_PROBLEM, + "%s: ptroff for \"--%s\" is non-" + "zero but no XTOPT_PUT is specified. " + "Oversight?", name, entry->name); continue; + } if (entry->type >= ARRAY_SIZE(xtopt_psize) || xtopt_psize[entry->type] == 0) xt_params->exit_err(OTHER_PROBLEM, -- cgit v1.2.3 From 97dac48e7dfd3e2f35e33fdad72bda5b3dfc2241 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 11:41:13 +0200 Subject: libip6t_frag: restore inversion support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --fraglen also was not printed since v1.4.11~26^2~22. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libip6t_frag.c | 16 ++++++++++++++++ tests/options-most.rules | 2 ++ 2 files changed, 18 insertions(+) diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c index 47793860..d8bcaeee 100644 --- a/extensions/libip6t_frag.c +++ b/extensions/libip6t_frag.c @@ -50,6 +50,22 @@ static void frag_parse(struct xt_option_call *cb) case O_FRAGID: if (cb->nvals == 1) fraginfo->ids[1] = fraginfo->ids[0]; + if (cb->invert) + fraginfo->invflags |= IP6T_FRAG_INV_IDS; + /* + * Note however that IP6T_FRAG_IDS is not tested by anything, + * so it is merely here for completeness. + */ + fraginfo->flags |= IP6T_FRAG_IDS; + break; + case O_FRAGLEN: + /* + * As of Linux 3.0, the kernel does not check for + * fraglen at all. + */ + if (cb->invert) + fraginfo->invflags |= IP6T_FRAG_INV_LEN; + fraginfo->flags |= IP6T_FRAG_LEN; break; case O_FRAGRES: fraginfo->flags |= IP6T_FRAG_RES; diff --git a/tests/options-most.rules b/tests/options-most.rules index 4becc2ae..6839d89b 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -144,6 +144,8 @@ -A matches -A matches -m frag --fragid 5:4294967295 -A matches +-A matches -m frag ! --fragid 9:10 ! --fraglen 12 +-A matches -A matches -m rt --rt-segsleft 1 -A matches -A matches -m rt --rt-segsleft :2 -- cgit v1.2.3 From de1f06dca906bfcb82d7c7c2d555fbf3229d12b6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 11:49:21 +0200 Subject: libxt_hashlimit: remove inversion from hashlimit rev 0 Revision 0 indeed did not have inversion support, nor presence of --hashlimit-above. This glitch was added in v1.4.11~16^2~10. Signed-off-by: Jan Engelhardt --- extensions/libxt_hashlimit.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index 89320bb3..eb52b169 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -89,7 +89,7 @@ static void hashlimit_mt_help(void) #define s struct xt_hashlimit_info static const struct xt_option_entry hashlimit_opts[] = { {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE, - .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, + .type = XTTYPE_STRING}, {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32, .min = 1, .max = 10000, .flags = XTOPT_PUT, XTOPT_POINTER(s, cfg.burst)}, @@ -251,19 +251,10 @@ static void hashlimit_parse(struct xt_option_call *cb) xtables_option_parse(cb); switch (cb->entry->id) { case O_UPTO: - if (cb->invert) - info->cfg.mode |= XT_HASHLIMIT_INVERT; if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", "--hashlimit-upto", cb->arg); break; - case O_ABOVE: - if (!cb->invert) - info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-above", cb->arg); - break; case O_MODE: if (parse_mode(&info->cfg.mode, cb->arg) < 0) xtables_param_act(XTF_BAD_VALUE, "hashlimit", @@ -529,7 +520,7 @@ static struct xtables_match hashlimit_mt_reg[] = { .x6_fcheck = hashlimit_check, .print = hashlimit_print, .save = hashlimit_save, - .x6_options = hashlimit_mt_opts, + .x6_options = hashlimit_opts, .udata_size = sizeof(struct hashlimit_mt_udata), }, { -- cgit v1.2.3 From 975aeec7d34419fece8710997b6ec88cc0abb580 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 11:54:01 +0200 Subject: libip6t_hbh: restore setting IP6T_OPTS_LEN flag Bug origin is in commit v1.4.11~26^2~17. Signed-off-by: Jan Engelhardt --- extensions/libip6t_hbh.c | 1 + tests/options-most.rules | 2 ++ 2 files changed, 3 insertions(+) diff --git a/extensions/libip6t_hbh.c b/extensions/libip6t_hbh.c index 809e80d5..c0389ed8 100644 --- a/extensions/libip6t_hbh.c +++ b/extensions/libip6t_hbh.c @@ -108,6 +108,7 @@ static void hbh_parse(struct xt_option_call *cb) case O_HBH_LEN: if (cb->invert) optinfo->invflags |= IP6T_OPTS_INV_LEN; + optinfo->flags |= IP6T_OPTS_LEN; break; case O_HBH_OPTS: optinfo->optsnr = parse_options(cb->arg, optinfo->opts); diff --git a/tests/options-most.rules b/tests/options-most.rules index 6839d89b..12090911 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -94,6 +94,8 @@ -A matches -m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 1 --hashlimit-name mini3 -A matches -m hashlimit --hashlimit-upto 1/day --hashlimit-burst 1 --hashlimit-name mini4 -A matches +-A matches -m hbh ! --hbh-len 5 +-A matches -A matches -m ipvs --vaddr fe80::/64 --vport 1 --vdir REPLY --vmethod GATE --vportctl 21 -A matches -A matches -m length --length 1 -- cgit v1.2.3 From 0859fdf5d0ae24c88e64246164c4959ad3b0d098 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 11:59:58 +0200 Subject: libip6t_dst: restore setting IP6T_OPTS_LEN flag Bug origin is in commit v1.4.11~26^2~18. Signed-off-by: Jan Engelhardt --- extensions/libip6t_dst.c | 3 +++ tests/options-most.rules | 2 ++ 2 files changed, 5 insertions(+) diff --git a/extensions/libip6t_dst.c b/extensions/libip6t_dst.c index 4125bd3d..3fd4c019 100644 --- a/extensions/libip6t_dst.c +++ b/extensions/libip6t_dst.c @@ -111,6 +111,9 @@ static void dst_parse(struct xt_option_call *cb) xtables_option_parse(cb); switch (cb->entry->id) { + case O_DSTLEN: + optinfo->flags |= IP6T_OPTS_LEN; + break; case O_DSTOPTS: optinfo->optsnr = parse_options(cb->arg, optinfo->opts); optinfo->flags |= IP6T_OPTS_OPTS; diff --git a/tests/options-most.rules b/tests/options-most.rules index 12090911..cd6aab80 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -79,6 +79,8 @@ -A matches -A matches -m conntrack ! --ctstate NEW ! --ctproto tcp ! --ctorigsrc ::1/127 ! --ctorigdst ::2/127 ! --ctreplsrc ::2/127 ! --ctrepldst ::2/127 ! --ctorigsrcport 3 ! --ctorigdstport 4 ! --ctreplsrcport 5 ! --ctrepldstport 6 ! --ctstatus ASSURED ! --ctexpire 8:9 -A matches +-A matches -m dst ! --dst-len 12 +-A matches -A matches -p esp -m esp --espspi 1 -A matches -A matches -p esp -m esp --espspi :2 -- cgit v1.2.3 From c96e524e98de81b333d772aa9a4f9b93275525dd Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 12:11:15 +0200 Subject: libipt_ttl: document that negation is available Glitch since commit v1.2.1~75. Signed-off-by: Jan Engelhardt --- extensions/libipt_ttl.c | 2 +- extensions/libipt_ttl.man | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libipt_ttl.c b/extensions/libipt_ttl.c index 6370cb67..5fe08ccd 100644 --- a/extensions/libipt_ttl.c +++ b/extensions/libipt_ttl.c @@ -20,7 +20,7 @@ static void ttl_help(void) { printf( "ttl match options:\n" -" --ttl-eq value Match time to live value\n" +"[!] --ttl-eq value Match time to live value\n" " --ttl-lt value Match TTL < value\n" " --ttl-gt value Match TTL > value\n"); } diff --git a/extensions/libipt_ttl.man b/extensions/libipt_ttl.man index 849f7042..1f322779 100644 --- a/extensions/libipt_ttl.man +++ b/extensions/libipt_ttl.man @@ -1,6 +1,6 @@ This module matches the time to live field in the IP header. .TP -\fB\-\-ttl\-eq\fP \fIttl\fP +[\fB!\fP] \fB\-\-ttl\-eq\fP \fIttl\fP Matches the given TTL value. .TP \fB\-\-ttl\-gt\fP \fIttl\fP -- cgit v1.2.3 From c4e1c0992937bce3ac72987aa43f4f3c219cf3e3 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 12:25:06 +0200 Subject: libxt_owner: restore inversion support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug origin is in commit v1.4.11~16^2~7. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_owner.c | 3 ++- tests/options-most.rules | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_owner.c b/extensions/libxt_owner.c index d2fdfa91..d9adc12e 100644 --- a/extensions/libxt_owner.c +++ b/extensions/libxt_owner.c @@ -129,7 +129,8 @@ static const struct xt_option_entry owner_mt_opts[] = { .flags = XTOPT_INVERT}, {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, - {.name = "socket-exists", .id = O_SOCK_EXISTS, .type = XTTYPE_NONE}, + {.name = "socket-exists", .id = O_SOCK_EXISTS, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, XTOPT_TABLEEND, }; diff --git a/tests/options-most.rules b/tests/options-most.rules index cd6aab80..37aeabf8 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -57,6 +57,7 @@ -A INPUT -p mobility -A INPUT -p mobility -m mh --mh-type 3 -A OUTPUT -m owner --socket-exists --uid-owner 1-2 --gid-owner 2-3 +-A OUTPUT -m owner ! --socket-exists ! --uid-owner 0 ! --gid-owner 0 -A matches -m connbytes --connbytes 1 --connbytes-mode bytes --connbytes-dir both -A matches -A matches -m connbytes --connbytes :2 --connbytes-mode bytes --connbytes-dir both -- cgit v1.2.3 From c2a47ead16fc488fbf7fd8aa12d306cedf4da441 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 12:27:06 +0200 Subject: libxt_physdev: restore inversion support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug origin is in commit v1.4.11~26^2~4. References: Dave Täht via netfilter-devel on 2011-08-20 14:40:11 -0700 References: Signed-off-by: Jan Engelhardt --- extensions/libxt_physdev.c | 7 ++++--- tests/options-most.rules | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/extensions/libxt_physdev.c b/extensions/libxt_physdev.c index 8f57fe9f..a11faf40 100644 --- a/extensions/libxt_physdev.c +++ b/extensions/libxt_physdev.c @@ -27,11 +27,12 @@ static const struct xt_option_entry physdev_opts[] = { .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physindev)}, {.name = "physdev-out", .id = O_PHYSDEV_OUT, .type = XTTYPE_STRING, .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physoutdev)}, - {.name = "physdev-is-in", .id = O_PHYSDEV_IS_IN, .type = XTTYPE_NONE}, + {.name = "physdev-is-in", .id = O_PHYSDEV_IS_IN, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, {.name = "physdev-is-out", .id = O_PHYSDEV_IS_OUT, - .type = XTTYPE_NONE}, + .type = XTTYPE_NONE, .flags = XTOPT_INVERT}, {.name = "physdev-is-bridged", .id = O_PHYSDEV_IS_BRIDGED, - .type = XTTYPE_NONE}, + .type = XTTYPE_NONE, .flags = XTOPT_INVERT}, XTOPT_TABLEEND, }; #undef s diff --git a/tests/options-most.rules b/tests/options-most.rules index 37aeabf8..c2436499 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -111,6 +111,8 @@ -A matches -A matches -m length --length 5:65535 -A matches +-A matches -m physdev ! --physdev-is-in ! --physdev-is-out ! --physdev-is-bridged +-A matches -A matches -p tcp -m tcpmss --mss 1 -A matches -A matches -p tcp -m tcpmss --mss :2 -- cgit v1.2.3 From 03deef5241330db418652c42af4d517527743f22 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 12:39:04 +0200 Subject: libxt_policy: remove superfluous inversion --dir cannot be inverted. Signed-off-by: Jan Engelhardt --- extensions/libxt_policy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c index 97722d6c..54ec2294 100644 --- a/extensions/libxt_policy.c +++ b/extensions/libxt_policy.c @@ -40,8 +40,7 @@ static void policy_help(void) } static const struct xt_option_entry policy_opts[] = { - {.name = "dir", .id = O_DIRECTION, .type = XTTYPE_STRING, - .flags = XTOPT_INVERT}, + {.name = "dir", .id = O_DIRECTION, .type = XTTYPE_STRING}, {.name = "pol", .id = O_POLICY, .type = XTTYPE_STRING}, {.name = "strict", .id = O_STRICT, .type = XTTYPE_NONE}, {.name = "reqid", .id = O_REQID, .type = XTTYPE_UINT32, -- cgit v1.2.3 From 7e42bda9330afe717561c47a02a3f58c8ee1a246 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 12:46:08 +0200 Subject: tests: add negation tests for libxt_statistic Note: it is valid to check cb->invert before calling xtables_option_parse. Signed-off-by: Jan Engelhardt --- tests/options-most.rules | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/options-most.rules b/tests/options-most.rules index c2436499..0e876e65 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -123,6 +123,10 @@ -A matches -A matches -p tcp -m tcpmss --mss 5:65535 -A matches +-A matches -m statistic --mode random ! --probability 0.4 +-A matches +-A matches -m statistic --mode nth ! --every 5 --packet 2 +-A matches -A matches -m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --localtz -A matches -A matches -m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --kerneltz -- cgit v1.2.3 From 4a56bcbd49ef20a0203017c15ab1cec9bb140d1a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 13:04:38 +0200 Subject: libxt_hashlimit: observe new default gc-expire time when saving Since a while, --htable-gc-expire defaults to the chosen time quantum instead of 10 fixed seconds, which leads the expiry value to be always printed, which is redundant. Signed-off-by: Jan Engelhardt --- extensions/libxt_hashlimit.c | 33 ++++++++++++++++++++------------- tests/options-most.rules | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index eb52b169..da34cb22 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -23,7 +23,6 @@ /* miliseconds */ #define XT_HASHLIMIT_GCINTERVAL 1000 -#define XT_HASHLIMIT_EXPIRE 10000 struct hashlimit_mt_udata { uint32_t mult; @@ -187,7 +186,6 @@ static void hashlimit_init(struct xt_entry_match *m) r->cfg.burst = XT_HASHLIMIT_BURST; r->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL; - r->cfg.expire = XT_HASHLIMIT_EXPIRE; } @@ -198,7 +196,6 @@ static void hashlimit_mt4_init(struct xt_entry_match *match) info->cfg.mode = 0; info->cfg.burst = XT_HASHLIMIT_BURST; info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL; - info->cfg.expire = XT_HASHLIMIT_EXPIRE; info->cfg.srcmask = 32; info->cfg.dstmask = 32; } @@ -210,7 +207,6 @@ static void hashlimit_mt6_init(struct xt_entry_match *match) info->cfg.mode = 0; info->cfg.burst = XT_HASHLIMIT_BURST; info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL; - info->cfg.expire = XT_HASHLIMIT_EXPIRE; info->cfg.srcmask = 128; info->cfg.dstmask = 128; } @@ -330,7 +326,7 @@ static const struct rates { "min", XT_HASHLIMIT_SCALE*60 }, { "sec", XT_HASHLIMIT_SCALE } }; -static void print_rate(uint32_t period) +static uint32_t print_rate(uint32_t period) { unsigned int i; @@ -340,6 +336,8 @@ static void print_rate(uint32_t period) break; printf(" %u/%s", rates[i-1].mult / period, rates[i-1].name); + /* return in msec */ + return rates[i-1].mult / XT_HASHLIMIT_SCALE * 1000; } static void print_mode(unsigned int mode, char separator) @@ -374,7 +372,10 @@ static void hashlimit_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct xt_hashlimit_info *r = (const void *)match->data; - fputs(" limit: avg", stdout); print_rate(r->cfg.avg); + uint32_t quantum; + + fputs(" limit: avg", stdout); + quantum = print_rate(r->cfg.avg); printf(" burst %u", r->cfg.burst); fputs(" mode", stdout); print_mode(r->cfg.mode, '-'); @@ -384,18 +385,20 @@ static void hashlimit_print(const void *ip, printf(" htable-max %u", r->cfg.max); if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) printf(" htable-gcinterval %u", r->cfg.gc_interval); - if (r->cfg.expire != XT_HASHLIMIT_EXPIRE) + if (r->cfg.expire != quantum) printf(" htable-expire %u", r->cfg.expire); } static void hashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) { + uint32_t quantum; + if (info->cfg.mode & XT_HASHLIMIT_INVERT) fputs(" limit: above", stdout); else fputs(" limit: up to", stdout); - print_rate(info->cfg.avg); + quantum = print_rate(info->cfg.avg); printf(" burst %u", info->cfg.burst); if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) { @@ -408,7 +411,7 @@ hashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) printf(" htable-max %u", info->cfg.max); if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) printf(" htable-gcinterval %u", info->cfg.gc_interval); - if (info->cfg.expire != XT_HASHLIMIT_EXPIRE) + if (info->cfg.expire != quantum) printf(" htable-expire %u", info->cfg.expire); if (info->cfg.srcmask != dmask) @@ -438,8 +441,10 @@ hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match, static void hashlimit_save(const void *ip, const struct xt_entry_match *match) { const struct xt_hashlimit_info *r = (const void *)match->data; + uint32_t quantum; - fputs(" --hashlimit", stdout); print_rate(r->cfg.avg); + fputs(" --hashlimit", stdout); + quantum = print_rate(r->cfg.avg); printf(" --hashlimit-burst %u", r->cfg.burst); fputs(" --hashlimit-mode", stdout); @@ -453,18 +458,20 @@ static void hashlimit_save(const void *ip, const struct xt_entry_match *match) printf(" --hashlimit-htable-max %u", r->cfg.max); if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) printf(" --hashlimit-htable-gcinterval %u", r->cfg.gc_interval); - if (r->cfg.expire != XT_HASHLIMIT_EXPIRE) + if (r->cfg.expire != quantum) printf(" --hashlimit-htable-expire %u", r->cfg.expire); } static void hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) { + uint32_t quantum; + if (info->cfg.mode & XT_HASHLIMIT_INVERT) fputs(" --hashlimit-above", stdout); else fputs(" --hashlimit-upto", stdout); - print_rate(info->cfg.avg); + quantum = print_rate(info->cfg.avg); printf(" --hashlimit-burst %u", info->cfg.burst); if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | @@ -481,7 +488,7 @@ hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) printf(" --hashlimit-htable-max %u", info->cfg.max); if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) printf(" --hashlimit-htable-gcinterval %u", info->cfg.gc_interval); - if (info->cfg.expire != XT_HASHLIMIT_EXPIRE) + if (info->cfg.expire != quantum) printf(" --hashlimit-htable-expire %u", info->cfg.expire); if (info->cfg.srcmask != dmask) diff --git a/tests/options-most.rules b/tests/options-most.rules index 0e876e65..e54eb127 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -92,6 +92,7 @@ -A matches -A matches -p esp -m esp --espspi 5:4294967295 -A matches +-A matches -m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-name mini1 --hashlimit-htable-expire 2000 -A matches -m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-name mini1 -A matches -m hashlimit --hashlimit-upto 1/min --hashlimit-burst 1 --hashlimit-name mini2 -A matches -m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 1 --hashlimit-name mini3 -- cgit v1.2.3 From 131d4fb53b45be85b1315f72f958cadf7b24a63f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 21 Aug 2011 13:16:16 +0200 Subject: libxt_string: simplify hex output routine Signed-off-by: Jan Engelhardt --- extensions/libxt_string.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/extensions/libxt_string.c b/extensions/libxt_string.c index 257f5f85..365019f7 100644 --- a/extensions/libxt_string.c +++ b/extensions/libxt_string.c @@ -230,13 +230,8 @@ print_hex_string(const char *str, const unsigned short int len) unsigned int i; /* start hex block */ printf(" \"|"); - for (i=0; i < len; i++) { - /* see if we need to prepend a zero */ - if ((unsigned char) str[i] <= 0x0F) - printf("0%x", (unsigned char) str[i]); - else - printf("%x", (unsigned char) str[i]); - } + for (i=0; i < len; i++) + printf("%02x", (unsigned char)str[i]); /* close hex block */ printf("|\""); } -- cgit v1.2.3 From f4daf54e5c184680559de33eb08f2a0fb701dbe9 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 25 Aug 2011 12:11:20 +0200 Subject: libxt_string: replace hex codes by char equivalents Signed-off-by: Jan Engelhardt --- extensions/libxt_string.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/libxt_string.c b/extensions/libxt_string.c index 365019f7..472035fb 100644 --- a/extensions/libxt_string.c +++ b/extensions/libxt_string.c @@ -218,7 +218,7 @@ is_hex_string(const char *str, const unsigned short int len) if (! isprint(str[i])) return 1; /* string contains at least one non-printable char */ /* use hex output if the last char is a "\" */ - if ((unsigned char) str[len-1] == 0x5c) + if (str[len-1] == '\\') return 1; return 0; } @@ -242,8 +242,8 @@ print_string(const char *str, const unsigned short int len) unsigned int i; printf(" \""); for (i=0; i < len; i++) { - if ((unsigned char) str[i] == 0x22) /* escape any embedded quotes */ - printf("%c", 0x5c); + if (str[i] == '\"') /* escape any embedded quotes */ + putchar('\\'); printf("%c", (unsigned char) str[i]); } printf("\""); /* closing quote */ -- cgit v1.2.3 From f643eb37e49a212d40eb060bcdfafbc366c0d616 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 26 Aug 2011 12:45:02 +0200 Subject: src: remove unused IPTABLES_MULTI define This dead code has been lingering around since commit v1.4.5~7. Signed-off-by: Jan Engelhardt --- iptables/Makefile.am | 2 +- iptables/ip6tables-restore.c | 4 ---- iptables/ip6tables-save.c | 4 ---- iptables/ip6tables-standalone.c | 5 ----- iptables/iptables-restore.c | 5 ----- iptables/iptables-save.c | 5 ----- iptables/iptables-standalone.c | 5 ----- iptables/iptables-xml.c | 9 --------- 8 files changed, 1 insertion(+), 38 deletions(-) diff --git a/iptables/Makefile.am b/iptables/Makefile.am index a0682788..addb1598 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -15,7 +15,7 @@ libxtables_la_LIBADD = endif xtables_multi_SOURCES = xtables-multi.c iptables-xml.c -xtables_multi_CFLAGS = ${AM_CFLAGS} -DIPTABLES_MULTI +xtables_multi_CFLAGS = ${AM_CFLAGS} xtables_multi_LDFLAGS = -rdynamic xtables_multi_LDADD = ../extensions/libext.a if ENABLE_STATIC diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index ae147d55..985744d6 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -113,11 +113,7 @@ static void free_argv(void) { free(newargv[i]); } -#ifdef IPTABLES_MULTI int ip6tables_restore_main(int argc, char *argv[]) -#else -int main(int argc, char *argv[]) -#endif { struct ip6tc_handle *handle = NULL; char buffer[10240]; diff --git a/iptables/ip6tables-save.c b/iptables/ip6tables-save.c index 39a33256..ad0e70f0 100644 --- a/iptables/ip6tables-save.c +++ b/iptables/ip6tables-save.c @@ -131,11 +131,7 @@ static int do_output(const char *tablename) * :Chain name POLICY packets bytes * rule */ -#ifdef IPTABLES_MULTI int ip6tables_save_main(int argc, char *argv[]) -#else -int main(int argc, char *argv[]) -#endif { const char *tablename = NULL; int c; diff --git a/iptables/ip6tables-standalone.c b/iptables/ip6tables-standalone.c index 9d8d5a0f..6b829353 100644 --- a/iptables/ip6tables-standalone.c +++ b/iptables/ip6tables-standalone.c @@ -37,13 +37,8 @@ #include #include "ip6tables-multi.h" -#ifdef IPTABLES_MULTI int ip6tables_main(int argc, char *argv[]) -#else -int -main(int argc, char *argv[]) -#endif { int ret; char *table = "filter"; diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 1cb833c0..d0bd79a9 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -113,13 +113,8 @@ static void free_argv(void) { free(newargv[i]); } -#ifdef IPTABLES_MULTI int iptables_restore_main(int argc, char *argv[]) -#else -int -main(int argc, char *argv[]) -#endif { struct iptc_handle *handle = NULL; char buffer[10240]; diff --git a/iptables/iptables-save.c b/iptables/iptables-save.c index 7542bdc0..73fba12a 100644 --- a/iptables/iptables-save.c +++ b/iptables/iptables-save.c @@ -129,13 +129,8 @@ static int do_output(const char *tablename) * :Chain name POLICY packets bytes * rule */ -#ifdef IPTABLES_MULTI int iptables_save_main(int argc, char *argv[]) -#else -int -main(int argc, char *argv[]) -#endif { const char *tablename = NULL; int c; diff --git a/iptables/iptables-standalone.c b/iptables/iptables-standalone.c index 87f1d31a..1ebec33d 100644 --- a/iptables/iptables-standalone.c +++ b/iptables/iptables-standalone.c @@ -38,13 +38,8 @@ #include #include "iptables-multi.h" -#ifdef IPTABLES_MULTI int iptables_main(int argc, char *argv[]) -#else -int -main(int argc, char *argv[]) -#endif { int ret; char *table = "filter"; diff --git a/iptables/iptables-xml.c b/iptables/iptables-xml.c index 502b2d96..4ecddcb7 100644 --- a/iptables/iptables-xml.c +++ b/iptables/iptables-xml.c @@ -23,10 +23,6 @@ #define DEBUGP(x, args...) #endif -#ifndef IPTABLES_MULTI -int line = 0; -#endif - struct xtables_globals iptables_xml_globals = { .option_offset = 0, .program_version = IPTABLES_VERSION, @@ -617,13 +613,8 @@ do_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[]) do_rule_part(NULL, NULL, 1, argc, argv, argvattr); } -#ifdef IPTABLES_MULTI int iptables_xml_main(int argc, char *argv[]) -#else -int -main(int argc, char *argv[]) -#endif { char buffer[10240]; int c; -- cgit v1.2.3 From d51a97bc52ee81a962b761c7e58a5eb9f07a2c8a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 26 Aug 2011 14:46:40 +0200 Subject: libxt_string: escape the escaping char too References: http://bugzilla.netfilter.org/show_bug.cgi?id=740 Signed-off-by: Jan Engelhardt --- extensions/libxt_string.c | 2 +- tests/options-most.rules | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_string.c b/extensions/libxt_string.c index 472035fb..fb15980e 100644 --- a/extensions/libxt_string.c +++ b/extensions/libxt_string.c @@ -242,7 +242,7 @@ print_string(const char *str, const unsigned short int len) unsigned int i; printf(" \""); for (i=0; i < len; i++) { - if (str[i] == '\"') /* escape any embedded quotes */ + if (str[i] == '\"' || str[i] == '\\') putchar('\\'); printf("%c", (unsigned char) str[i]); } diff --git a/tests/options-most.rules b/tests/options-most.rules index e54eb127..ae28b82d 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -128,6 +128,10 @@ -A matches -A matches -m statistic --mode nth ! --every 5 --packet 2 -A matches +-A matches -m string --hex-string "action=|5C22|http|3A|" --algo bm +-A matches +-A matches -m string --hex-string "action=|5C|http|3A|" --algo bm +-A matches -A matches -m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --localtz -A matches -A matches -m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --kerneltz -- cgit v1.2.3 From debcf48f6a72914a9c06e99b175ad64ef1f6f1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= Date: Tue, 2 Aug 2011 10:00:40 +0900 Subject: libxt_TOS: update linux kernel version list for backported fix Signed-off-by: Jan Engelhardt --- extensions/libxt_TOS.man | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_TOS.man b/extensions/libxt_TOS.man index f9896740..58118ec2 100644 --- a/extensions/libxt_TOS.man +++ b/extensions/libxt_TOS.man @@ -28,9 +28,9 @@ Binary XOR the TOS value with \fIbits\fP. (Mnemonic for \fB\-\-set\-tos\fP \fIbits\fP\fB/0\fP. See NOTE below.) .PP NOTE: In Linux kernels up to and including 2.6.38, with the exception of -longterm releases 2.6.32.42 (or later) and 2.6.33.15 (or later), there is a bug -whereby IPv6 TOS mangling does not behave as documented and differs from the -IPv4 version. The TOS mask indicates the bits one wants to zero out, so it needs -to be inverted before applying it to the original TOS field. However, the +longterm releases 2.6.32 (>=.42), 2.6.33 (>=.15), and 2.6.35 (>=.14), there is +a bug whereby IPv6 TOS mangling does not behave as documented and differs from +the IPv4 version. The TOS mask indicates the bits one wants to zero out, so it +needs to be inverted before applying it to the original TOS field. However, the aformentioned kernels forgo the inversion which breaks --set-tos and its mnemonics. -- cgit v1.2.3 From fdb2a27825e558393fb715374c07873830d4d149 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 17:59:52 +0200 Subject: xtoptions: fill in fallback value for nvals Parsing for libxt_conntrack rev 2 is done by using rev 2's option structure, which specifies XTTYPE_PORT, and using rev 3's parser skeleton, which uses cb->nvals. Reading cb->nvals when not using XTTYPE_PORTRC (or any other multi-value type) is undefined behavior. Make it defined. Since XTTYPE_NONE is the only type that can take void, nvals logically ought to be 1. References: http://marc.info/?l=netfilter-devel&m=131370592105298&w=2 Signed-off-by: Jan Engelhardt --- iptables/xtoptions.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/iptables/xtoptions.c b/iptables/xtoptions.c index 04344af4..5f617a42 100644 --- a/iptables/xtoptions.c +++ b/iptables/xtoptions.c @@ -826,6 +826,12 @@ void xtables_option_parse(struct xt_option_call *cb) xt_params->exit_err(PARAMETER_PROBLEM, "%s: option \"--%s\" requires an argument.\n", cb->ext_name, entry->name); + /* + * Fill in fallback value for "nvals", in case an extension (as it + * happened with libxt_conntrack.2) tries to read it, despite not using + * a *RC option type. + */ + cb->nvals = 1; if (entry->type <= ARRAY_SIZE(xtopt_subparse) && xtopt_subparse[entry->type] != NULL) xtopt_subparse[entry->type](cb); -- cgit v1.2.3 From 3412bd0bfb8b8bac9834cbfd3392b3d5487133bf Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Thu, 18 Aug 2011 15:11:16 -0700 Subject: libxt_conntrack: improve error message on parsing violation Tom Eastep noted: $ iptables -A foo -m conntrack --ctorigdstport 22 iptables v1.4.12: conntrack rev 2 does not support port ranges Try `iptables -h' or 'iptables --help' for more information. Commit v1.4.12-41-g1ad6407 takes care of the actual cause of the bug, but let's include Tom's patch nevertheless for the better error message in case one actually does specify a range with rev 2. References: http://marc.info/?l=netfilter-devel&m=131370592105298&w=2 Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index 060b9477..fff69f8a 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -129,13 +129,20 @@ static const struct xt_option_entry conntrack2_mt_opts[] = { .flags = XTOPT_INVERT}, {.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC, .flags = XTOPT_INVERT}, - {.name = "ctorigsrcport", .id = O_CTORIGSRCPORT, .type = XTTYPE_PORT, + /* + * Rev 1 and 2 only store one port, and we would normally use + * %XTTYPE_PORT (rather than %XTTYPE_PORTRC) for that. The resulting + * error message - in case a user passed a range nevertheless - + * "port 22:23 resolved to nothing" is not quite as useful as using + * %XTTYPE_PORTC and libxt_conntrack's own range test. + */ + {.name = "ctorigsrcport", .id = O_CTORIGSRCPORT, .type = XTTYPE_PORTRC, .flags = XTOPT_INVERT | XTOPT_NBO}, - {.name = "ctorigdstport", .id = O_CTORIGDSTPORT, .type = XTTYPE_PORT, + {.name = "ctorigdstport", .id = O_CTORIGDSTPORT, .type = XTTYPE_PORTRC, .flags = XTOPT_INVERT | XTOPT_NBO}, - {.name = "ctreplsrcport", .id = O_CTREPLSRCPORT, .type = XTTYPE_PORT, + {.name = "ctreplsrcport", .id = O_CTREPLSRCPORT, .type = XTTYPE_PORTRC, .flags = XTOPT_INVERT | XTOPT_NBO}, - {.name = "ctrepldstport", .id = O_CTREPLDSTPORT, .type = XTTYPE_PORT, + {.name = "ctrepldstport", .id = O_CTREPLDSTPORT, .type = XTTYPE_PORTRC, .flags = XTOPT_INVERT | XTOPT_NBO}, {.name = "ctdir", .id = O_CTDIR, .type = XTTYPE_STRING}, XTOPT_TABLEEND, -- cgit v1.2.3 From 2ca6273c73b42e8c74afd5f8b1fe10c5c93ce363 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 27 Aug 2011 15:32:31 +0200 Subject: xtoptions: simplify xtables_parse_interface mask is already filled with zeros, there is no need to zero it again. References: http://marc.info/?l=netfilter-devel&m=131445196526269&w=2 Signed-off-by: Jan Engelhardt --- iptables/xtables.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/iptables/xtables.c b/iptables/xtables.c index 233efa30..e72aa284 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -515,15 +515,13 @@ void xtables_parse_interface(const char *arg, char *vianame, strcpy(vianame, arg); if (vialen == 0) - memset(mask, 0, IFNAMSIZ); + return; else if (vianame[vialen - 1] == '+') { memset(mask, 0xFF, vialen - 1); - memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); /* Don't remove `+' here! -HW */ } else { /* Include nul-terminator in match */ memset(mask, 0xFF, vialen + 1); - memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); for (i = 0; vianame[i]; i++) { if (vianame[i] == '/' || vianame[i] == ' ') { -- cgit v1.2.3 From a49002efbdc5813ee193aa8fde3da3e35ff0d38f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 28 Aug 2011 14:10:19 +0200 Subject: libxt_addrtype: rename from libipt_addrtype Signed-off-by: Jan Engelhardt --- extensions/libipt_addrtype.c | 308 ----------------------------------------- extensions/libipt_addrtype.man | 69 --------- extensions/libxt_addrtype.c | 308 +++++++++++++++++++++++++++++++++++++++++ extensions/libxt_addrtype.man | 69 +++++++++ 4 files changed, 377 insertions(+), 377 deletions(-) delete mode 100644 extensions/libipt_addrtype.c delete mode 100644 extensions/libipt_addrtype.man create mode 100644 extensions/libxt_addrtype.c create mode 100644 extensions/libxt_addrtype.man diff --git a/extensions/libipt_addrtype.c b/extensions/libipt_addrtype.c deleted file mode 100644 index 3dec626b..00000000 --- a/extensions/libipt_addrtype.c +++ /dev/null @@ -1,308 +0,0 @@ -/* Shared library add-on to iptables to add addrtype matching support - * - * This program is released under the terms of GNU GPL */ -#include -#include -#include -#include - -enum { - O_SRC_TYPE = 0, - O_DST_TYPE, - O_LIMIT_IFACE_IN, - O_LIMIT_IFACE_OUT, - F_SRC_TYPE = 1 << O_SRC_TYPE, - F_DST_TYPE = 1 << O_DST_TYPE, - F_LIMIT_IFACE_IN = 1 << O_LIMIT_IFACE_IN, - F_LIMIT_IFACE_OUT = 1 << O_LIMIT_IFACE_OUT, -}; - -/* from linux/rtnetlink.h, must match order of enumeration */ -static const char *const rtn_names[] = { - "UNSPEC", - "UNICAST", - "LOCAL", - "BROADCAST", - "ANYCAST", - "MULTICAST", - "BLACKHOLE", - "UNREACHABLE", - "PROHIBIT", - "THROW", - "NAT", - "XRESOLVE", - NULL -}; - -static void addrtype_help_types(void) -{ - int i; - - for (i = 0; rtn_names[i]; i++) - printf(" %s\n", rtn_names[i]); -} - -static void addrtype_help_v0(void) -{ - printf( -"Address type match options:\n" -" [!] --src-type type[,...] Match source address type\n" -" [!] --dst-type type[,...] Match destination address type\n" -"\n" -"Valid types: \n"); - addrtype_help_types(); -} - -static void addrtype_help_v1(void) -{ - printf( -"Address type match options:\n" -" [!] --src-type type[,...] Match source address type\n" -" [!] --dst-type type[,...] Match destination address type\n" -" --limit-iface-in Match only on the packet's incoming device\n" -" --limit-iface-out Match only on the packet's incoming device\n" -"\n" -"Valid types: \n"); - addrtype_help_types(); -} - -static int -parse_type(const char *name, size_t len, uint16_t *mask) -{ - int i; - - for (i = 0; rtn_names[i]; i++) - if (strncasecmp(name, rtn_names[i], len) == 0) { - /* build up bitmask for kernel module */ - *mask |= (1 << i); - return 1; - } - - return 0; -} - -static void parse_types(const char *arg, uint16_t *mask) -{ - const char *comma; - - while ((comma = strchr(arg, ',')) != NULL) { - if (comma == arg || !parse_type(arg, comma-arg, mask)) - xtables_error(PARAMETER_PROBLEM, - "addrtype: bad type `%s'", arg); - arg = comma + 1; - } - - if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask)) - xtables_error(PARAMETER_PROBLEM, "addrtype: bad type \"%s\"", arg); -} - -static void addrtype_parse_v0(struct xt_option_call *cb) -{ - struct ipt_addrtype_info *info = cb->data; - - xtables_option_parse(cb); - switch (cb->entry->id) { - case O_SRC_TYPE: - parse_types(cb->arg, &info->source); - if (cb->invert) - info->invert_source = 1; - break; - case O_DST_TYPE: - parse_types(cb->arg, &info->dest); - if (cb->invert) - info->invert_dest = 1; - break; - } -} - -static void addrtype_parse_v1(struct xt_option_call *cb) -{ - struct ipt_addrtype_info_v1 *info = cb->data; - - xtables_option_parse(cb); - switch (cb->entry->id) { - case O_SRC_TYPE: - parse_types(cb->arg, &info->source); - if (cb->invert) - info->flags |= IPT_ADDRTYPE_INVERT_SOURCE; - break; - case O_DST_TYPE: - parse_types(cb->arg, &info->dest); - if (cb->invert) - info->flags |= IPT_ADDRTYPE_INVERT_DEST; - break; - case O_LIMIT_IFACE_IN: - info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN; - break; - case O_LIMIT_IFACE_OUT: - info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT; - break; - } -} - -static void addrtype_check(struct xt_fcheck_call *cb) -{ - if (!(cb->xflags & (F_SRC_TYPE | F_DST_TYPE))) - xtables_error(PARAMETER_PROBLEM, - "addrtype: you must specify --src-type or --dst-type"); -} - -static void print_types(uint16_t mask) -{ - const char *sep = ""; - int i; - - for (i = 0; rtn_names[i]; i++) - if (mask & (1 << i)) { - printf("%s%s", sep, rtn_names[i]); - sep = ","; - } -} - -static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match, - int numeric) -{ - const struct ipt_addrtype_info *info = - (struct ipt_addrtype_info *) match->data; - - printf(" ADDRTYPE match"); - if (info->source) { - printf(" src-type "); - if (info->invert_source) - printf("!"); - print_types(info->source); - } - if (info->dest) { - printf(" dst-type"); - if (info->invert_dest) - printf("!"); - print_types(info->dest); - } -} - -static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match, - int numeric) -{ - const struct ipt_addrtype_info_v1 *info = - (struct ipt_addrtype_info_v1 *) match->data; - - printf(" ADDRTYPE match"); - if (info->source) { - printf(" src-type "); - if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) - printf("!"); - print_types(info->source); - } - if (info->dest) { - printf(" dst-type "); - if (info->flags & IPT_ADDRTYPE_INVERT_DEST) - printf("!"); - print_types(info->dest); - } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { - printf(" limit-in"); - } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { - printf(" limit-out"); - } -} - -static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match) -{ - const struct ipt_addrtype_info *info = - (struct ipt_addrtype_info *) match->data; - - if (info->source) { - if (info->invert_source) - printf(" !"); - printf(" --src-type "); - print_types(info->source); - } - if (info->dest) { - if (info->invert_dest) - printf(" !"); - printf(" --dst-type "); - print_types(info->dest); - } -} - -static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match) -{ - const struct ipt_addrtype_info_v1 *info = - (struct ipt_addrtype_info_v1 *) match->data; - - if (info->source) { - if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) - printf(" !"); - printf(" --src-type "); - print_types(info->source); - } - if (info->dest) { - if (info->flags & IPT_ADDRTYPE_INVERT_DEST) - printf(" !"); - printf(" --dst-type "); - print_types(info->dest); - } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { - printf(" --limit-iface-in"); - } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { - printf(" --limit-iface-out"); - } -} - -static const struct xt_option_entry addrtype_opts_v0[] = { - {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING, - .flags = XTOPT_INVERT}, - {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING, - .flags = XTOPT_INVERT}, - XTOPT_TABLEEND, -}; - -static const struct xt_option_entry addrtype_opts_v1[] = { - {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING, - .flags = XTOPT_INVERT}, - {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING, - .flags = XTOPT_INVERT}, - {.name = "limit-iface-in", .id = O_LIMIT_IFACE_IN, - .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_OUT}, - {.name = "limit-iface-out", .id = O_LIMIT_IFACE_OUT, - .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_IN}, - XTOPT_TABLEEND, -}; - -static struct xtables_match addrtype_mt_reg[] = { - { - .name = "addrtype", - .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_addrtype_info)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)), - .help = addrtype_help_v0, - .print = addrtype_print_v0, - .save = addrtype_save_v0, - .x6_parse = addrtype_parse_v0, - .x6_fcheck = addrtype_check, - .x6_options = addrtype_opts_v0, - }, - { - .name = "addrtype", - .revision = 1, - .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), - .help = addrtype_help_v1, - .print = addrtype_print_v1, - .save = addrtype_save_v1, - .x6_parse = addrtype_parse_v1, - .x6_fcheck = addrtype_check, - .x6_options = addrtype_opts_v1, - }, -}; - - -void _init(void) -{ - xtables_register_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg)); -} diff --git a/extensions/libipt_addrtype.man b/extensions/libipt_addrtype.man deleted file mode 100644 index 16fd9dfd..00000000 --- a/extensions/libipt_addrtype.man +++ /dev/null @@ -1,69 +0,0 @@ -This module matches packets based on their -.B address type. -Address types are used within the kernel networking stack and categorize -addresses into various groups. The exact definition of that group depends on the specific layer three protocol. -.PP -The following address types are possible: -.TP -.BI "UNSPEC" -an unspecified address (i.e. 0.0.0.0) -.TP -.BI "UNICAST" -an unicast address -.TP -.BI "LOCAL" -a local address -.TP -.BI "BROADCAST" -a broadcast address -.TP -.BI "ANYCAST" -an anycast packet -.TP -.BI "MULTICAST" -a multicast address -.TP -.BI "BLACKHOLE" -a blackhole address -.TP -.BI "UNREACHABLE" -an unreachable address -.TP -.BI "PROHIBIT" -a prohibited address -.TP -.BI "THROW" -FIXME -.TP -.BI "NAT" -FIXME -.TP -.BI "XRESOLVE" -.TP -[\fB!\fP] \fB\-\-src\-type\fP \fItype\fP -Matches if the source address is of given type -.TP -[\fB!\fP] \fB\-\-dst\-type\fP \fItype\fP -Matches if the destination address is of given type -.TP -.BI "\-\-limit\-iface\-in" -The address type checking can be limited to the interface the packet is coming -in. This option is only valid in the -.BR PREROUTING , -.B INPUT -and -.B FORWARD -chains. It cannot be specified with the -\fB\-\-limit\-iface\-out\fP -option. -.TP -\fB\-\-limit\-iface\-out\fP -The address type checking can be limited to the interface the packet is going -out. This option is only valid in the -.BR POSTROUTING , -.B OUTPUT -and -.B FORWARD -chains. It cannot be specified with the -\fB\-\-limit\-iface\-in\fP -option. diff --git a/extensions/libxt_addrtype.c b/extensions/libxt_addrtype.c new file mode 100644 index 00000000..3dec626b --- /dev/null +++ b/extensions/libxt_addrtype.c @@ -0,0 +1,308 @@ +/* Shared library add-on to iptables to add addrtype matching support + * + * This program is released under the terms of GNU GPL */ +#include +#include +#include +#include + +enum { + O_SRC_TYPE = 0, + O_DST_TYPE, + O_LIMIT_IFACE_IN, + O_LIMIT_IFACE_OUT, + F_SRC_TYPE = 1 << O_SRC_TYPE, + F_DST_TYPE = 1 << O_DST_TYPE, + F_LIMIT_IFACE_IN = 1 << O_LIMIT_IFACE_IN, + F_LIMIT_IFACE_OUT = 1 << O_LIMIT_IFACE_OUT, +}; + +/* from linux/rtnetlink.h, must match order of enumeration */ +static const char *const rtn_names[] = { + "UNSPEC", + "UNICAST", + "LOCAL", + "BROADCAST", + "ANYCAST", + "MULTICAST", + "BLACKHOLE", + "UNREACHABLE", + "PROHIBIT", + "THROW", + "NAT", + "XRESOLVE", + NULL +}; + +static void addrtype_help_types(void) +{ + int i; + + for (i = 0; rtn_names[i]; i++) + printf(" %s\n", rtn_names[i]); +} + +static void addrtype_help_v0(void) +{ + printf( +"Address type match options:\n" +" [!] --src-type type[,...] Match source address type\n" +" [!] --dst-type type[,...] Match destination address type\n" +"\n" +"Valid types: \n"); + addrtype_help_types(); +} + +static void addrtype_help_v1(void) +{ + printf( +"Address type match options:\n" +" [!] --src-type type[,...] Match source address type\n" +" [!] --dst-type type[,...] Match destination address type\n" +" --limit-iface-in Match only on the packet's incoming device\n" +" --limit-iface-out Match only on the packet's incoming device\n" +"\n" +"Valid types: \n"); + addrtype_help_types(); +} + +static int +parse_type(const char *name, size_t len, uint16_t *mask) +{ + int i; + + for (i = 0; rtn_names[i]; i++) + if (strncasecmp(name, rtn_names[i], len) == 0) { + /* build up bitmask for kernel module */ + *mask |= (1 << i); + return 1; + } + + return 0; +} + +static void parse_types(const char *arg, uint16_t *mask) +{ + const char *comma; + + while ((comma = strchr(arg, ',')) != NULL) { + if (comma == arg || !parse_type(arg, comma-arg, mask)) + xtables_error(PARAMETER_PROBLEM, + "addrtype: bad type `%s'", arg); + arg = comma + 1; + } + + if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask)) + xtables_error(PARAMETER_PROBLEM, "addrtype: bad type \"%s\"", arg); +} + +static void addrtype_parse_v0(struct xt_option_call *cb) +{ + struct ipt_addrtype_info *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SRC_TYPE: + parse_types(cb->arg, &info->source); + if (cb->invert) + info->invert_source = 1; + break; + case O_DST_TYPE: + parse_types(cb->arg, &info->dest); + if (cb->invert) + info->invert_dest = 1; + break; + } +} + +static void addrtype_parse_v1(struct xt_option_call *cb) +{ + struct ipt_addrtype_info_v1 *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SRC_TYPE: + parse_types(cb->arg, &info->source); + if (cb->invert) + info->flags |= IPT_ADDRTYPE_INVERT_SOURCE; + break; + case O_DST_TYPE: + parse_types(cb->arg, &info->dest); + if (cb->invert) + info->flags |= IPT_ADDRTYPE_INVERT_DEST; + break; + case O_LIMIT_IFACE_IN: + info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN; + break; + case O_LIMIT_IFACE_OUT: + info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT; + break; + } +} + +static void addrtype_check(struct xt_fcheck_call *cb) +{ + if (!(cb->xflags & (F_SRC_TYPE | F_DST_TYPE))) + xtables_error(PARAMETER_PROBLEM, + "addrtype: you must specify --src-type or --dst-type"); +} + +static void print_types(uint16_t mask) +{ + const char *sep = ""; + int i; + + for (i = 0; rtn_names[i]; i++) + if (mask & (1 << i)) { + printf("%s%s", sep, rtn_names[i]); + sep = ","; + } +} + +static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct ipt_addrtype_info *info = + (struct ipt_addrtype_info *) match->data; + + printf(" ADDRTYPE match"); + if (info->source) { + printf(" src-type "); + if (info->invert_source) + printf("!"); + print_types(info->source); + } + if (info->dest) { + printf(" dst-type"); + if (info->invert_dest) + printf("!"); + print_types(info->dest); + } +} + +static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct ipt_addrtype_info_v1 *info = + (struct ipt_addrtype_info_v1 *) match->data; + + printf(" ADDRTYPE match"); + if (info->source) { + printf(" src-type "); + if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) + printf("!"); + print_types(info->source); + } + if (info->dest) { + printf(" dst-type "); + if (info->flags & IPT_ADDRTYPE_INVERT_DEST) + printf("!"); + print_types(info->dest); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { + printf(" limit-in"); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + printf(" limit-out"); + } +} + +static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match) +{ + const struct ipt_addrtype_info *info = + (struct ipt_addrtype_info *) match->data; + + if (info->source) { + if (info->invert_source) + printf(" !"); + printf(" --src-type "); + print_types(info->source); + } + if (info->dest) { + if (info->invert_dest) + printf(" !"); + printf(" --dst-type "); + print_types(info->dest); + } +} + +static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match) +{ + const struct ipt_addrtype_info_v1 *info = + (struct ipt_addrtype_info_v1 *) match->data; + + if (info->source) { + if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) + printf(" !"); + printf(" --src-type "); + print_types(info->source); + } + if (info->dest) { + if (info->flags & IPT_ADDRTYPE_INVERT_DEST) + printf(" !"); + printf(" --dst-type "); + print_types(info->dest); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { + printf(" --limit-iface-in"); + } + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + printf(" --limit-iface-out"); + } +} + +static const struct xt_option_entry addrtype_opts_v0[] = { + {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + XTOPT_TABLEEND, +}; + +static const struct xt_option_entry addrtype_opts_v1[] = { + {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "limit-iface-in", .id = O_LIMIT_IFACE_IN, + .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_OUT}, + {.name = "limit-iface-out", .id = O_LIMIT_IFACE_OUT, + .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_IN}, + XTOPT_TABLEEND, +}; + +static struct xtables_match addrtype_mt_reg[] = { + { + .name = "addrtype", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV4, + .size = XT_ALIGN(sizeof(struct ipt_addrtype_info)), + .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)), + .help = addrtype_help_v0, + .print = addrtype_print_v0, + .save = addrtype_save_v0, + .x6_parse = addrtype_parse_v0, + .x6_fcheck = addrtype_check, + .x6_options = addrtype_opts_v0, + }, + { + .name = "addrtype", + .revision = 1, + .version = XTABLES_VERSION, + .family = NFPROTO_IPV4, + .size = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), + .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), + .help = addrtype_help_v1, + .print = addrtype_print_v1, + .save = addrtype_save_v1, + .x6_parse = addrtype_parse_v1, + .x6_fcheck = addrtype_check, + .x6_options = addrtype_opts_v1, + }, +}; + + +void _init(void) +{ + xtables_register_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg)); +} diff --git a/extensions/libxt_addrtype.man b/extensions/libxt_addrtype.man new file mode 100644 index 00000000..16fd9dfd --- /dev/null +++ b/extensions/libxt_addrtype.man @@ -0,0 +1,69 @@ +This module matches packets based on their +.B address type. +Address types are used within the kernel networking stack and categorize +addresses into various groups. The exact definition of that group depends on the specific layer three protocol. +.PP +The following address types are possible: +.TP +.BI "UNSPEC" +an unspecified address (i.e. 0.0.0.0) +.TP +.BI "UNICAST" +an unicast address +.TP +.BI "LOCAL" +a local address +.TP +.BI "BROADCAST" +a broadcast address +.TP +.BI "ANYCAST" +an anycast packet +.TP +.BI "MULTICAST" +a multicast address +.TP +.BI "BLACKHOLE" +a blackhole address +.TP +.BI "UNREACHABLE" +an unreachable address +.TP +.BI "PROHIBIT" +a prohibited address +.TP +.BI "THROW" +FIXME +.TP +.BI "NAT" +FIXME +.TP +.BI "XRESOLVE" +.TP +[\fB!\fP] \fB\-\-src\-type\fP \fItype\fP +Matches if the source address is of given type +.TP +[\fB!\fP] \fB\-\-dst\-type\fP \fItype\fP +Matches if the destination address is of given type +.TP +.BI "\-\-limit\-iface\-in" +The address type checking can be limited to the interface the packet is coming +in. This option is only valid in the +.BR PREROUTING , +.B INPUT +and +.B FORWARD +chains. It cannot be specified with the +\fB\-\-limit\-iface\-out\fP +option. +.TP +\fB\-\-limit\-iface\-out\fP +The address type checking can be limited to the interface the packet is going +out. This option is only valid in the +.BR POSTROUTING , +.B OUTPUT +and +.B FORWARD +chains. It cannot be specified with the +\fB\-\-limit\-iface\-in\fP +option. -- cgit v1.2.3 From 3775fb69f63b76191bc3571bfa8538c18173d90f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 28 Aug 2011 14:16:14 +0200 Subject: libxt_addrtype: add support for revision 1 Rev 1 was added to the kernel in commit v2.6.39-rc1~468^2~10^2~1 but there was no corresponding iptables patch so far. Cc: Florian Westphal Signed-off-by: Jan Engelhardt --- extensions/libxt_addrtype.c | 56 +++++++++++++++-------------------- include/linux/netfilter/xt_addrtype.h | 44 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 32 deletions(-) create mode 100644 include/linux/netfilter/xt_addrtype.h diff --git a/extensions/libxt_addrtype.c b/extensions/libxt_addrtype.c index 3dec626b..59072b35 100644 --- a/extensions/libxt_addrtype.c +++ b/extensions/libxt_addrtype.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include enum { O_SRC_TYPE = 0, @@ -98,7 +98,7 @@ static void parse_types(const char *arg, uint16_t *mask) static void addrtype_parse_v0(struct xt_option_call *cb) { - struct ipt_addrtype_info *info = cb->data; + struct xt_addrtype_info *info = cb->data; xtables_option_parse(cb); switch (cb->entry->id) { @@ -117,25 +117,25 @@ static void addrtype_parse_v0(struct xt_option_call *cb) static void addrtype_parse_v1(struct xt_option_call *cb) { - struct ipt_addrtype_info_v1 *info = cb->data; + struct xt_addrtype_info_v1 *info = cb->data; xtables_option_parse(cb); switch (cb->entry->id) { case O_SRC_TYPE: parse_types(cb->arg, &info->source); if (cb->invert) - info->flags |= IPT_ADDRTYPE_INVERT_SOURCE; + info->flags |= XT_ADDRTYPE_INVERT_SOURCE; break; case O_DST_TYPE: parse_types(cb->arg, &info->dest); if (cb->invert) - info->flags |= IPT_ADDRTYPE_INVERT_DEST; + info->flags |= XT_ADDRTYPE_INVERT_DEST; break; case O_LIMIT_IFACE_IN: - info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN; + info->flags |= XT_ADDRTYPE_LIMIT_IFACE_IN; break; case O_LIMIT_IFACE_OUT: - info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT; + info->flags |= XT_ADDRTYPE_LIMIT_IFACE_OUT; break; } } @@ -162,8 +162,7 @@ static void print_types(uint16_t mask) static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match, int numeric) { - const struct ipt_addrtype_info *info = - (struct ipt_addrtype_info *) match->data; + const struct xt_addrtype_info *info = (const void *)match->data; printf(" ADDRTYPE match"); if (info->source) { @@ -183,34 +182,30 @@ static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match, int numeric) { - const struct ipt_addrtype_info_v1 *info = - (struct ipt_addrtype_info_v1 *) match->data; + const struct xt_addrtype_info_v1 *info = (const void *)match->data; printf(" ADDRTYPE match"); if (info->source) { printf(" src-type "); - if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) + if (info->flags & XT_ADDRTYPE_INVERT_SOURCE) printf("!"); print_types(info->source); } if (info->dest) { printf(" dst-type "); - if (info->flags & IPT_ADDRTYPE_INVERT_DEST) + if (info->flags & XT_ADDRTYPE_INVERT_DEST) printf("!"); print_types(info->dest); } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { + if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) printf(" limit-in"); - } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) printf(" limit-out"); - } } static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match) { - const struct ipt_addrtype_info *info = - (struct ipt_addrtype_info *) match->data; + const struct xt_addrtype_info *info = (const void *)match->data; if (info->source) { if (info->invert_source) @@ -228,27 +223,24 @@ static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match) static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match) { - const struct ipt_addrtype_info_v1 *info = - (struct ipt_addrtype_info_v1 *) match->data; + const struct xt_addrtype_info_v1 *info = (const void *)match->data; if (info->source) { - if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE) + if (info->flags & XT_ADDRTYPE_INVERT_SOURCE) printf(" !"); printf(" --src-type "); print_types(info->source); } if (info->dest) { - if (info->flags & IPT_ADDRTYPE_INVERT_DEST) + if (info->flags & XT_ADDRTYPE_INVERT_DEST) printf(" !"); printf(" --dst-type "); print_types(info->dest); } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { + if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) printf(" --limit-iface-in"); - } - if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) printf(" --limit-iface-out"); - } } static const struct xt_option_entry addrtype_opts_v0[] = { @@ -276,8 +268,8 @@ static struct xtables_match addrtype_mt_reg[] = { .name = "addrtype", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_addrtype_info)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)), + .size = XT_ALIGN(sizeof(struct xt_addrtype_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_addrtype_info)), .help = addrtype_help_v0, .print = addrtype_print_v0, .save = addrtype_save_v0, @@ -289,9 +281,9 @@ static struct xtables_match addrtype_mt_reg[] = { .name = "addrtype", .revision = 1, .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)), + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_addrtype_info_v1)), + .userspacesize = XT_ALIGN(sizeof(struct xt_addrtype_info_v1)), .help = addrtype_help_v1, .print = addrtype_print_v1, .save = addrtype_save_v1, diff --git a/include/linux/netfilter/xt_addrtype.h b/include/linux/netfilter/xt_addrtype.h new file mode 100644 index 00000000..b156baa9 --- /dev/null +++ b/include/linux/netfilter/xt_addrtype.h @@ -0,0 +1,44 @@ +#ifndef _XT_ADDRTYPE_H +#define _XT_ADDRTYPE_H + +#include + +enum { + XT_ADDRTYPE_INVERT_SOURCE = 0x0001, + XT_ADDRTYPE_INVERT_DEST = 0x0002, + XT_ADDRTYPE_LIMIT_IFACE_IN = 0x0004, + XT_ADDRTYPE_LIMIT_IFACE_OUT = 0x0008, +}; + + +/* rtn_type enum values from rtnetlink.h, but shifted */ +enum { + XT_ADDRTYPE_UNSPEC = 1 << 0, + XT_ADDRTYPE_UNICAST = 1 << 1, /* 1 << RTN_UNICAST */ + XT_ADDRTYPE_LOCAL = 1 << 2, /* 1 << RTN_LOCAL, etc */ + XT_ADDRTYPE_BROADCAST = 1 << 3, + XT_ADDRTYPE_ANYCAST = 1 << 4, + XT_ADDRTYPE_MULTICAST = 1 << 5, + XT_ADDRTYPE_BLACKHOLE = 1 << 6, + XT_ADDRTYPE_UNREACHABLE = 1 << 7, + XT_ADDRTYPE_PROHIBIT = 1 << 8, + XT_ADDRTYPE_THROW = 1 << 9, + XT_ADDRTYPE_NAT = 1 << 10, + XT_ADDRTYPE_XRESOLVE = 1 << 11, +}; + +struct xt_addrtype_info_v1 { + __u16 source; /* source-type mask */ + __u16 dest; /* dest-type mask */ + __u32 flags; +}; + +/* revision 0 */ +struct xt_addrtype_info { + __u16 source; /* source-type mask */ + __u16 dest; /* dest-type mask */ + __u32 invert_source; + __u32 invert_dest; +}; + +#endif -- cgit v1.2.3 From dbe77cc974cee656eae37e75039dd1a410a4535b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 28 Aug 2011 14:19:43 +0200 Subject: include: refresh include files from kernel 3.1-rc3 Signed-off-by: Jan Engelhardt --- include/linux/kernel.h | 33 --- include/linux/netfilter.h | 18 +- include/linux/netfilter/ipset/ip_set.h | 225 +++++++++++++++++++++ include/linux/netfilter/nf_conntrack_common.h | 14 ++ .../linux/netfilter/nf_conntrack_tuple_common.h | 3 +- include/linux/netfilter/x_tables.h | 5 + include/linux/netfilter/xt_CT.h | 2 + include/linux/netfilter/xt_TCPOPTSTRIP.h | 2 + include/linux/netfilter/xt_TPROXY.h | 2 + include/linux/netfilter/xt_cluster.h | 2 + include/linux/netfilter/xt_connbytes.h | 4 +- include/linux/netfilter/xt_connlimit.h | 2 + include/linux/netfilter/xt_physdev.h | 3 - include/linux/netfilter/xt_policy.h | 11 - include/linux/netfilter/xt_quota.h | 4 +- include/linux/netfilter/xt_sctp.h | 4 +- include/linux/netfilter/xt_set.h | 81 +------- include/linux/netfilter/xt_socket.h | 2 + include/linux/netfilter/xt_time.h | 2 + include/linux/netfilter/xt_u32.h | 2 + include/linux/netfilter_ipv4/ip_tables.h | 82 ++++---- include/linux/netfilter_ipv4/ipt_CLUSTERIP.h | 16 +- include/linux/netfilter_ipv4/ipt_ECN.h | 8 +- include/linux/netfilter_ipv4/ipt_SAME.h | 8 +- include/linux/netfilter_ipv4/ipt_TTL.h | 6 +- include/linux/netfilter_ipv4/ipt_addrtype.h | 16 +- include/linux/netfilter_ipv4/ipt_ah.h | 6 +- include/linux/netfilter_ipv4/ipt_ecn.h | 10 +- include/linux/netfilter_ipv4/ipt_ttl.h | 6 +- include/linux/netfilter_ipv6/ip6_tables.h | 100 ++++----- include/linux/netfilter_ipv6/ip6t_HL.h | 6 +- include/linux/netfilter_ipv6/ip6t_REJECT.h | 4 +- include/linux/netfilter_ipv6/ip6t_ah.h | 10 +- include/linux/netfilter_ipv6/ip6t_frag.h | 10 +- include/linux/netfilter_ipv6/ip6t_hl.h | 6 +- include/linux/netfilter_ipv6/ip6t_ipv6header.h | 8 +- include/linux/netfilter_ipv6/ip6t_mh.h | 6 +- include/linux/netfilter_ipv6/ip6t_opts.h | 12 +- include/linux/netfilter_ipv6/ip6t_rt.h | 13 +- include/linux/types.h | 13 ++ 40 files changed, 475 insertions(+), 292 deletions(-) create mode 100644 include/linux/netfilter/ipset/ip_set.h diff --git a/include/linux/kernel.h b/include/linux/kernel.h index d1671a01..d4c59f65 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -8,7 +8,6 @@ #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) - #define SI_LOAD_SHIFT 16 struct sysinfo { long uptime; /* Seconds since boot */ @@ -27,36 +26,4 @@ struct sysinfo { char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ }; -/* Force a compilation error if condition is true */ -#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition)) - -/* Force a compilation error if condition is constant and true */ -#define MAYBE_BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2 * !!(cond)])) - -/* Force a compilation error if a constant expression is not a power of 2 */ -#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \ - BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0)) - -/* Force a compilation error if condition is true, but also produce a - result (of value 0 and type size_t), so the expression can be used - e.g. in a structure initializer (or where-ever else comma expressions - aren't permitted). */ -#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) -#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) - -/* Trap pasters of __FUNCTION__ at compile-time */ -#define __FUNCTION__ (__func__) - -/* This helps us to avoid #ifdef CONFIG_NUMA */ -#ifdef CONFIG_NUMA -#define NUMA_BUILD 1 -#else -#define NUMA_BUILD 0 -#endif - -/* Rebuild everything on CONFIG_FTRACE_MCOUNT_RECORD */ -#ifdef CONFIG_FTRACE_MCOUNT_RECORD -# define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD -#endif - #endif diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 2eb00b6c..54771312 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -3,6 +3,7 @@ #include +#include /* Responses from hook functions. */ #define NF_DROP 0 @@ -14,14 +15,20 @@ #define NF_MAX_VERDICT NF_STOP /* we overload the higher bits for encoding auxiliary data such as the queue - * number. Not nice, but better than additional function arguments. */ -#define NF_VERDICT_MASK 0x0000ffff -#define NF_VERDICT_BITS 16 + * number or errno values. Not nice, but better than additional function + * arguments. */ +#define NF_VERDICT_MASK 0x000000ff + +/* extra verdict flags have mask 0x0000ff00 */ +#define NF_VERDICT_FLAG_QUEUE_BYPASS 0x00008000 +/* queue number (NF_QUEUE) or errno (NF_DROP) */ #define NF_VERDICT_QMASK 0xffff0000 #define NF_VERDICT_QBITS 16 -#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE) +#define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE) + +#define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP) /* only for userspace compatibility */ /* Generic cache responses from hook functions. @@ -29,6 +36,9 @@ #define NFC_UNKNOWN 0x4000 #define NFC_ALTERED 0x8000 +/* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */ +#define NF_VERDICT_BITS 16 + enum nf_inet_hooks { NF_INET_PRE_ROUTING, NF_INET_LOCAL_IN, diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h new file mode 100644 index 00000000..79cb0779 --- /dev/null +++ b/include/linux/netfilter/ipset/ip_set.h @@ -0,0 +1,225 @@ +#ifndef _IP_SET_H +#define _IP_SET_H + +/* Copyright (C) 2000-2002 Joakim Axelsson + * Patrick Schaaf + * Martin Josefsson + * Copyright (C) 2003-2011 Jozsef Kadlecsik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +/* The protocol version */ +#define IPSET_PROTOCOL 6 + +/* The max length of strings including NUL: set and type identifiers */ +#define IPSET_MAXNAMELEN 32 + +/* Message types and commands */ +enum ipset_cmd { + IPSET_CMD_NONE, + IPSET_CMD_PROTOCOL, /* 1: Return protocol version */ + IPSET_CMD_CREATE, /* 2: Create a new (empty) set */ + IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */ + IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */ + IPSET_CMD_RENAME, /* 5: Rename a set */ + IPSET_CMD_SWAP, /* 6: Swap two sets */ + IPSET_CMD_LIST, /* 7: List sets */ + IPSET_CMD_SAVE, /* 8: Save sets */ + IPSET_CMD_ADD, /* 9: Add an element to a set */ + IPSET_CMD_DEL, /* 10: Delete an element from a set */ + IPSET_CMD_TEST, /* 11: Test an element in a set */ + IPSET_CMD_HEADER, /* 12: Get set header data only */ + IPSET_CMD_TYPE, /* 13: Get set type */ + IPSET_MSG_MAX, /* Netlink message commands */ + + /* Commands in userspace: */ + IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */ + IPSET_CMD_HELP, /* 15: Get help */ + IPSET_CMD_VERSION, /* 16: Get program version */ + IPSET_CMD_QUIT, /* 17: Quit from interactive mode */ + + IPSET_CMD_MAX, + + IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */ +}; + +/* Attributes at command level */ +enum { + IPSET_ATTR_UNSPEC, + IPSET_ATTR_PROTOCOL, /* 1: Protocol version */ + IPSET_ATTR_SETNAME, /* 2: Name of the set */ + IPSET_ATTR_TYPENAME, /* 3: Typename */ + IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */ + IPSET_ATTR_REVISION, /* 4: Settype revision */ + IPSET_ATTR_FAMILY, /* 5: Settype family */ + IPSET_ATTR_FLAGS, /* 6: Flags at command level */ + IPSET_ATTR_DATA, /* 7: Nested attributes */ + IPSET_ATTR_ADT, /* 8: Multiple data containers */ + IPSET_ATTR_LINENO, /* 9: Restore lineno */ + IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */ + IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */ + __IPSET_ATTR_CMD_MAX, +}; +#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1) + +/* CADT specific attributes */ +enum { + IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1, + IPSET_ATTR_IP_FROM = IPSET_ATTR_IP, + IPSET_ATTR_IP_TO, /* 2 */ + IPSET_ATTR_CIDR, /* 3 */ + IPSET_ATTR_PORT, /* 4 */ + IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT, + IPSET_ATTR_PORT_TO, /* 5 */ + IPSET_ATTR_TIMEOUT, /* 6 */ + IPSET_ATTR_PROTO, /* 7 */ + IPSET_ATTR_CADT_FLAGS, /* 8 */ + IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */ + /* Reserve empty slots */ + IPSET_ATTR_CADT_MAX = 16, + /* Create-only specific attributes */ + IPSET_ATTR_GC, + IPSET_ATTR_HASHSIZE, + IPSET_ATTR_MAXELEM, + IPSET_ATTR_NETMASK, + IPSET_ATTR_PROBES, + IPSET_ATTR_RESIZE, + IPSET_ATTR_SIZE, + /* Kernel-only */ + IPSET_ATTR_ELEMENTS, + IPSET_ATTR_REFERENCES, + IPSET_ATTR_MEMSIZE, + + __IPSET_ATTR_CREATE_MAX, +}; +#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1) + +/* ADT specific attributes */ +enum { + IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1, + IPSET_ATTR_NAME, + IPSET_ATTR_NAMEREF, + IPSET_ATTR_IP2, + IPSET_ATTR_CIDR2, + IPSET_ATTR_IP2_TO, + IPSET_ATTR_IFACE, + __IPSET_ATTR_ADT_MAX, +}; +#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1) + +/* IP specific attributes */ +enum { + IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1, + IPSET_ATTR_IPADDR_IPV6, + __IPSET_ATTR_IPADDR_MAX, +}; +#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1) + +/* Error codes */ +enum ipset_errno { + IPSET_ERR_PRIVATE = 4096, + IPSET_ERR_PROTOCOL, + IPSET_ERR_FIND_TYPE, + IPSET_ERR_MAX_SETS, + IPSET_ERR_BUSY, + IPSET_ERR_EXIST_SETNAME2, + IPSET_ERR_TYPE_MISMATCH, + IPSET_ERR_EXIST, + IPSET_ERR_INVALID_CIDR, + IPSET_ERR_INVALID_NETMASK, + IPSET_ERR_INVALID_FAMILY, + IPSET_ERR_TIMEOUT, + IPSET_ERR_REFERENCED, + IPSET_ERR_IPADDR_IPV4, + IPSET_ERR_IPADDR_IPV6, + + /* Type specific error codes */ + IPSET_ERR_TYPE_SPECIFIC = 4352, +}; + +/* Flags at command level */ +enum ipset_cmd_flags { + IPSET_FLAG_BIT_EXIST = 0, + IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST), + IPSET_FLAG_BIT_LIST_SETNAME = 1, + IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME), + IPSET_FLAG_BIT_LIST_HEADER = 2, + IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER), +}; + +/* Flags at CADT attribute level */ +enum ipset_cadt_flags { + IPSET_FLAG_BIT_BEFORE = 0, + IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE), + IPSET_FLAG_BIT_PHYSDEV = 1, + IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV), +}; + +/* Commands with settype-specific attributes */ +enum ipset_adt { + IPSET_ADD, + IPSET_DEL, + IPSET_TEST, + IPSET_ADT_MAX, + IPSET_CREATE = IPSET_ADT_MAX, + IPSET_CADT_MAX, +}; + +/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t + * and IPSET_INVALID_ID if you want to increase the max number of sets. + */ +typedef __u16 ip_set_id_t; + +#define IPSET_INVALID_ID 65535 + +enum ip_set_dim { + IPSET_DIM_ZERO = 0, + IPSET_DIM_ONE, + IPSET_DIM_TWO, + IPSET_DIM_THREE, + /* Max dimension in elements. + * If changed, new revision of iptables match/target is required. + */ + IPSET_DIM_MAX = 6, +}; + +/* Option flags for kernel operations */ +enum ip_set_kopt { + IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO), + IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), + IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), + IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), +}; + + +/* Interface to iptables/ip6tables */ + +#define SO_IP_SET 83 + +union ip_set_name_index { + char name[IPSET_MAXNAMELEN]; + ip_set_id_t index; +}; + +#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */ +struct ip_set_req_get_set { + unsigned op; + unsigned version; + union ip_set_name_index set; +}; + +#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */ +/* Uses ip_set_req_get_set */ + +#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */ +struct ip_set_req_version { + unsigned op; + unsigned version; +}; + +#endif /*_IP_SET_H */ diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 34a7fc65..38aa52d7 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -18,6 +18,9 @@ enum ip_conntrack_info { /* >= this indicates reply direction */ IP_CT_IS_REPLY, + IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY, + IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY, + IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY, /* Number of distinct IP_CT types (no NEW in reply dirn). */ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 }; @@ -76,6 +79,10 @@ enum ip_conntrack_status { /* Conntrack is a template */ IPS_TEMPLATE_BIT = 11, IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT), + + /* Conntrack is a fake untracked entry */ + IPS_UNTRACKED_BIT = 12, + IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), }; /* Connection tracking event types */ @@ -94,6 +101,13 @@ enum ip_conntrack_events { enum ip_conntrack_expect_events { IPEXP_NEW, /* new expectation */ + IPEXP_DESTROY, /* destroyed expectation */ }; +/* expectation flags */ +#define NF_CT_EXPECT_PERMANENT 0x1 +#define NF_CT_EXPECT_INACTIVE 0x2 +#define NF_CT_EXPECT_USERSPACE 0x4 + + #endif /* _NF_CONNTRACK_COMMON_H */ diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h index 8e145f0d..2ea22b01 100644 --- a/include/linux/netfilter/nf_conntrack_tuple_common.h +++ b/include/linux/netfilter/nf_conntrack_tuple_common.h @@ -1,8 +1,7 @@ #ifndef _NF_CONNTRACK_TUPLE_COMMON_H #define _NF_CONNTRACK_TUPLE_COMMON_H -enum ip_conntrack_dir -{ +enum ip_conntrack_dir { IP_CT_DIR_ORIGINAL, IP_CT_DIR_REPLY, IP_CT_DIR_MAX diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index fa2d9578..41209700 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -66,6 +66,11 @@ struct xt_standard_target { int verdict; }; +struct xt_error_target { + struct xt_entry_target target; + char errorname[XT_FUNCTION_MAXNAMELEN]; +}; + /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision * kernel supports, if >= revision. */ struct xt_get_revision { diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h index fbf4c565..b56e7681 100644 --- a/include/linux/netfilter/xt_CT.h +++ b/include/linux/netfilter/xt_CT.h @@ -1,6 +1,8 @@ #ifndef _XT_CT_H #define _XT_CT_H +#include + #define XT_CT_NOTRACK 0x1 struct xt_ct_target_info { diff --git a/include/linux/netfilter/xt_TCPOPTSTRIP.h b/include/linux/netfilter/xt_TCPOPTSTRIP.h index 342ef14b..71573184 100644 --- a/include/linux/netfilter/xt_TCPOPTSTRIP.h +++ b/include/linux/netfilter/xt_TCPOPTSTRIP.h @@ -1,6 +1,8 @@ #ifndef _XT_TCPOPTSTRIP_H #define _XT_TCPOPTSTRIP_H +#include + #define tcpoptstrip_set_bit(bmap, idx) \ (bmap[(idx) >> 5] |= 1U << (idx & 31)) #define tcpoptstrip_test_bit(bmap, idx) \ diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h index 8097e0b4..902043c2 100644 --- a/include/linux/netfilter/xt_TPROXY.h +++ b/include/linux/netfilter/xt_TPROXY.h @@ -1,6 +1,8 @@ #ifndef _XT_TPROXY_H #define _XT_TPROXY_H +#include + /* TPROXY target is capable of marking the packet to perform * redirection. We can get rid of that whenever we get support for * mutliple targets in the same rule. */ diff --git a/include/linux/netfilter/xt_cluster.h b/include/linux/netfilter/xt_cluster.h index 66cfa3c7..9b883c8f 100644 --- a/include/linux/netfilter/xt_cluster.h +++ b/include/linux/netfilter/xt_cluster.h @@ -1,6 +1,8 @@ #ifndef _XT_CLUSTER_MATCH_H #define _XT_CLUSTER_MATCH_H +#include + enum xt_cluster_flags { XT_CLUSTER_F_INV = (1 << 0) }; diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h index 92fcbb0d..f1d6c15b 100644 --- a/include/linux/netfilter/xt_connbytes.h +++ b/include/linux/netfilter/xt_connbytes.h @@ -17,8 +17,8 @@ enum xt_connbytes_direction { struct xt_connbytes_info { struct { - aligned_u64 from; /* count to be matched */ - aligned_u64 to; /* count to be matched */ + __aligned_u64 from; /* count to be matched */ + __aligned_u64 to; /* count to be matched */ } count; __u8 what; /* ipt_connbytes_what */ __u8 direction; /* ipt_connbytes_direction */ diff --git a/include/linux/netfilter/xt_connlimit.h b/include/linux/netfilter/xt_connlimit.h index ba774d30..f9e8c67c 100644 --- a/include/linux/netfilter/xt_connlimit.h +++ b/include/linux/netfilter/xt_connlimit.h @@ -1,6 +1,8 @@ #ifndef _XT_CONNLIMIT_H #define _XT_CONNLIMIT_H +#include + struct xt_connlimit_data; enum { diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h index 8555e399..7d53660a 100644 --- a/include/linux/netfilter/xt_physdev.h +++ b/include/linux/netfilter/xt_physdev.h @@ -3,9 +3,6 @@ #include -#ifdef __KERNEL__ -#include -#endif #define XT_PHYSDEV_OP_IN 0x01 #define XT_PHYSDEV_OP_OUT 0x02 diff --git a/include/linux/netfilter/xt_policy.h b/include/linux/netfilter/xt_policy.h index be8ead05..d246eac8 100644 --- a/include/linux/netfilter/xt_policy.h +++ b/include/linux/netfilter/xt_policy.h @@ -26,30 +26,19 @@ struct xt_policy_spec { reqid:1; }; -#ifndef __KERNEL__ union xt_policy_addr { struct in_addr a4; struct in6_addr a6; }; -#endif struct xt_policy_elem { union { -#ifdef __KERNEL__ - struct { - union nf_inet_addr saddr; - union nf_inet_addr smask; - union nf_inet_addr daddr; - union nf_inet_addr dmask; - }; -#else struct { union xt_policy_addr saddr; union xt_policy_addr smask; union xt_policy_addr daddr; union xt_policy_addr dmask; }; -#endif }; __be32 spi; __u32 reqid; diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h index 8bda65f0..9314723f 100644 --- a/include/linux/netfilter/xt_quota.h +++ b/include/linux/netfilter/xt_quota.h @@ -1,6 +1,8 @@ #ifndef _XT_QUOTA_H #define _XT_QUOTA_H +#include + enum xt_quota_flags { XT_QUOTA_INVERT = 0x1, }; @@ -11,7 +13,7 @@ struct xt_quota_priv; struct xt_quota_info { __u32 flags; __u32 pad; - aligned_u64 quota; + __aligned_u64 quota; /* Used internally by the kernel */ struct xt_quota_priv *master; diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h index 29287be6..a501e619 100644 --- a/include/linux/netfilter/xt_sctp.h +++ b/include/linux/netfilter/xt_sctp.h @@ -66,7 +66,7 @@ struct xt_sctp_info { #define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \ __sctp_chunkmap_is_clear((chunkmap), ARRAY_SIZE(chunkmap)) -static inline bool +static __inline__ bool __sctp_chunkmap_is_clear(const __u32 *chunkmap, unsigned int n) { unsigned int i; @@ -78,7 +78,7 @@ __sctp_chunkmap_is_clear(const __u32 *chunkmap, unsigned int n) #define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \ __sctp_chunkmap_is_all_set((chunkmap), ARRAY_SIZE(chunkmap)) -static inline bool +static __inline__ bool __sctp_chunkmap_is_all_set(const __u32 *chunkmap, unsigned int n) { unsigned int i; diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h index 4379ce9f..e3a9978f 100644 --- a/include/linux/netfilter/xt_set.h +++ b/include/linux/netfilter/xt_set.h @@ -1,62 +1,8 @@ #ifndef _XT_SET_H #define _XT_SET_H -/* The protocol version */ -#define IPSET_PROTOCOL 5 - -/* The max length of strings including NUL: set and type identifiers */ -#define IPSET_MAXNAMELEN 32 - -/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t - * and IPSET_INVALID_ID if you want to increase the max number of sets. - */ -typedef uint16_t ip_set_id_t; - -#define IPSET_INVALID_ID 65535 - -enum ip_set_dim { - IPSET_DIM_ZERO = 0, - IPSET_DIM_ONE, - IPSET_DIM_TWO, - IPSET_DIM_THREE, - /* Max dimension in elements. - * If changed, new revision of iptables match/target is required. - */ - IPSET_DIM_MAX = 6, -}; - -/* Option flags for kernel operations */ -enum ip_set_kopt { - IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO), - IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), - IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), - IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), -}; - -/* Interface to iptables/ip6tables */ - -#define SO_IP_SET 83 - -union ip_set_name_index { - char name[IPSET_MAXNAMELEN]; - ip_set_id_t index; -}; - -#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */ -struct ip_set_req_get_set { - unsigned op; - unsigned version; - union ip_set_name_index set; -}; - -#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */ -/* Uses ip_set_req_get_set */ - -#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */ -struct ip_set_req_version { - unsigned op; - unsigned version; -}; +#include +#include /* Revision 0 interface: backward compatible with netfilter/iptables */ @@ -70,11 +16,11 @@ struct ip_set_req_version { struct xt_set_info_v0 { ip_set_id_t index; union { - u_int32_t flags[IPSET_DIM_MAX + 1]; + __u32 flags[IPSET_DIM_MAX + 1]; struct { - u_int32_t __flags[IPSET_DIM_MAX]; - u_int8_t dim; - u_int8_t flags; + __u32 __flags[IPSET_DIM_MAX]; + __u8 dim; + __u8 flags; } compat; } u; }; @@ -89,12 +35,12 @@ struct xt_set_info_target_v0 { struct xt_set_info_v0 del_set; }; -/* Revision 1 match and target */ +/* Revision 1 match and target */ struct xt_set_info { ip_set_id_t index; - u_int8_t dim; - u_int8_t flags; + __u8 dim; + __u8 flags; }; /* match and target infos */ @@ -109,16 +55,11 @@ struct xt_set_info_target_v1 { /* Revision 2 target */ -enum ipset_cmd_flags { - IPSET_FLAG_BIT_EXIST = 0, - IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST), -}; - struct xt_set_info_target_v2 { struct xt_set_info add_set; struct xt_set_info del_set; - u_int32_t flags; - u_int32_t timeout; + __u32 flags; + __u32 timeout; }; #endif /*_XT_SET_H*/ diff --git a/include/linux/netfilter/xt_socket.h b/include/linux/netfilter/xt_socket.h index 6f475b8f..26d7217b 100644 --- a/include/linux/netfilter/xt_socket.h +++ b/include/linux/netfilter/xt_socket.h @@ -1,6 +1,8 @@ #ifndef _XT_SOCKET_H #define _XT_SOCKET_H +#include + enum { XT_SOCKET_TRANSPARENT = 1 << 0, }; diff --git a/include/linux/netfilter/xt_time.h b/include/linux/netfilter/xt_time.h index b8bd4568..7c37fac5 100644 --- a/include/linux/netfilter/xt_time.h +++ b/include/linux/netfilter/xt_time.h @@ -1,6 +1,8 @@ #ifndef _XT_TIME_H #define _XT_TIME_H 1 +#include + struct xt_time_info { __u32 date_start; __u32 date_stop; diff --git a/include/linux/netfilter/xt_u32.h b/include/linux/netfilter/xt_u32.h index e8c3d872..04d1bfea 100644 --- a/include/linux/netfilter/xt_u32.h +++ b/include/linux/netfilter/xt_u32.h @@ -1,6 +1,8 @@ #ifndef _XT_U32_H #define _XT_U32_H 1 +#include + enum xt_u32_ops { XT_U32_AND, XT_U32_LEFTSH, diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 735f4b1b..57fd82a1 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -27,6 +27,41 @@ #define ipt_target xt_target #define ipt_table xt_table #define ipt_get_revision xt_get_revision +#define ipt_entry_match xt_entry_match +#define ipt_entry_target xt_entry_target +#define ipt_standard_target xt_standard_target +#define ipt_error_target xt_error_target +#define ipt_counters xt_counters +#define IPT_CONTINUE XT_CONTINUE +#define IPT_RETURN XT_RETURN + +/* This group is older than old (iptables < v1.4.0-rc1~89) */ +#include +#define ipt_udp xt_udp +#define ipt_tcp xt_tcp +#define IPT_TCP_INV_SRCPT XT_TCP_INV_SRCPT +#define IPT_TCP_INV_DSTPT XT_TCP_INV_DSTPT +#define IPT_TCP_INV_FLAGS XT_TCP_INV_FLAGS +#define IPT_TCP_INV_OPTION XT_TCP_INV_OPTION +#define IPT_TCP_INV_MASK XT_TCP_INV_MASK +#define IPT_UDP_INV_SRCPT XT_UDP_INV_SRCPT +#define IPT_UDP_INV_DSTPT XT_UDP_INV_DSTPT +#define IPT_UDP_INV_MASK XT_UDP_INV_MASK + +/* The argument to IPT_SO_ADD_COUNTERS. */ +#define ipt_counters_info xt_counters_info +/* Standard return verdict, or do jump. */ +#define IPT_STANDARD_TARGET XT_STANDARD_TARGET +/* Error verdict. */ +#define IPT_ERROR_TARGET XT_ERROR_TARGET + +/* fn returns 0 to continue iteration */ +#define IPT_MATCH_ITERATE(e, fn, args...) \ + XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args) + +/* fn returns 0 to continue iteration */ +#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ + XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) /* Yes, Virginia, you have to zero the padding. */ struct ipt_ip { @@ -46,12 +81,6 @@ struct ipt_ip { u_int8_t invflags; }; -#define ipt_entry_match xt_entry_match -#define ipt_entry_target xt_entry_target -#define ipt_standard_target xt_standard_target - -#define ipt_counters xt_counters - /* Values for "flag" field in struct ipt_ip (general ip structure). */ #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ @@ -110,23 +139,6 @@ struct ipt_entry { #define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) #define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET -#define IPT_CONTINUE XT_CONTINUE -#define IPT_RETURN XT_RETURN - -#include -#define ipt_udp xt_udp -#define ipt_tcp xt_tcp - -#define IPT_TCP_INV_SRCPT XT_TCP_INV_SRCPT -#define IPT_TCP_INV_DSTPT XT_TCP_INV_DSTPT -#define IPT_TCP_INV_FLAGS XT_TCP_INV_FLAGS -#define IPT_TCP_INV_OPTION XT_TCP_INV_OPTION -#define IPT_TCP_INV_MASK XT_TCP_INV_MASK - -#define IPT_UDP_INV_SRCPT XT_UDP_INV_SRCPT -#define IPT_UDP_INV_DSTPT XT_UDP_INV_DSTPT -#define IPT_UDP_INV_MASK XT_UDP_INV_MASK - /* ICMP matching stuff */ struct ipt_icmp { u_int8_t type; /* type to match */ @@ -140,7 +152,7 @@ struct ipt_icmp { /* The argument to IPT_SO_GET_INFO */ struct ipt_getinfo { /* Which table: caller fills this in. */ - char name[IPT_TABLE_MAXNAMELEN]; + char name[XT_TABLE_MAXNAMELEN]; /* Kernel fills these in. */ /* Which hook entry points are valid: bitmask */ @@ -162,7 +174,7 @@ struct ipt_getinfo { /* The argument to IPT_SO_SET_REPLACE. */ struct ipt_replace { /* Which table. */ - char name[IPT_TABLE_MAXNAMELEN]; + char name[XT_TABLE_MAXNAMELEN]; /* Which hook entry points are valid: bitmask. You can't change this. */ @@ -190,13 +202,10 @@ struct ipt_replace { struct ipt_entry entries[0]; }; -/* The argument to IPT_SO_ADD_COUNTERS. */ -#define ipt_counters_info xt_counters_info - /* The argument to IPT_SO_GET_ENTRIES. */ struct ipt_get_entries { /* Which table: user fills this in. */ - char name[IPT_TABLE_MAXNAMELEN]; + char name[XT_TABLE_MAXNAMELEN]; /* User fills this in: total entry size. */ unsigned int size; @@ -205,26 +214,13 @@ struct ipt_get_entries { struct ipt_entry entrytable[0]; }; -/* Standard return verdict, or do jump. */ -#define IPT_STANDARD_TARGET XT_STANDARD_TARGET -/* Error verdict. */ -#define IPT_ERROR_TARGET XT_ERROR_TARGET - /* Helper functions */ -static __inline__ struct ipt_entry_target * +static __inline__ struct xt_entry_target * ipt_get_target(struct ipt_entry *e) { return (void *)e + e->target_offset; } -/* fn returns 0 to continue iteration */ -#define IPT_MATCH_ITERATE(e, fn, args...) \ - XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args) - -/* fn returns 0 to continue iteration */ -#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ - XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) - /* * Main firewall chains definitions and global var's definitions. */ diff --git a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h index e5a3687c..c6a204c9 100644 --- a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h +++ b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h @@ -1,6 +1,8 @@ #ifndef _IPT_CLUSTERIP_H_target #define _IPT_CLUSTERIP_H_target +#include + enum clusterip_hashmode { CLUSTERIP_HASHMODE_SIP = 0, CLUSTERIP_HASHMODE_SIP_SPT, @@ -17,15 +19,15 @@ struct clusterip_config; struct ipt_clusterip_tgt_info { - u_int32_t flags; + __u32 flags; /* only relevant for new ones */ - u_int8_t clustermac[6]; - u_int16_t num_total_nodes; - u_int16_t num_local_nodes; - u_int16_t local_nodes[CLUSTERIP_MAX_NODES]; - u_int32_t hash_mode; - u_int32_t hash_initval; + __u8 clustermac[6]; + __u16 num_total_nodes; + __u16 num_local_nodes; + __u16 local_nodes[CLUSTERIP_MAX_NODES]; + __u32 hash_mode; + __u32 hash_initval; /* Used internally by the kernel */ struct clusterip_config *config; diff --git a/include/linux/netfilter_ipv4/ipt_ECN.h b/include/linux/netfilter_ipv4/ipt_ECN.h index 7ca45918..bb88d531 100644 --- a/include/linux/netfilter_ipv4/ipt_ECN.h +++ b/include/linux/netfilter_ipv4/ipt_ECN.h @@ -8,6 +8,8 @@ */ #ifndef _IPT_ECN_TARGET_H #define _IPT_ECN_TARGET_H + +#include #include #define IPT_ECN_IP_MASK (~XT_DSCP_MASK) @@ -19,11 +21,11 @@ #define IPT_ECN_OP_MASK 0xce struct ipt_ECN_info { - u_int8_t operation; /* bitset of operations */ - u_int8_t ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ + __u8 operation; /* bitset of operations */ + __u8 ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ union { struct { - u_int8_t ece:1, cwr:1; /* TCP ECT bits */ + __u8 ece:1, cwr:1; /* TCP ECT bits */ } tcp; } proto; }; diff --git a/include/linux/netfilter_ipv4/ipt_SAME.h b/include/linux/netfilter_ipv4/ipt_SAME.h index 2529660c..5bca7826 100644 --- a/include/linux/netfilter_ipv4/ipt_SAME.h +++ b/include/linux/netfilter_ipv4/ipt_SAME.h @@ -1,15 +1,17 @@ #ifndef _IPT_SAME_H #define _IPT_SAME_H +#include + #define IPT_SAME_MAX_RANGE 10 #define IPT_SAME_NODST 0x01 struct ipt_same_info { unsigned char info; - u_int32_t rangesize; - u_int32_t ipnum; - u_int32_t *iparray; + __u32 rangesize; + __u32 ipnum; + __u32 *iparray; /* hangs off end. */ struct nf_nat_range range[IPT_SAME_MAX_RANGE]; diff --git a/include/linux/netfilter_ipv4/ipt_TTL.h b/include/linux/netfilter_ipv4/ipt_TTL.h index ee6611ed..f6ac169d 100644 --- a/include/linux/netfilter_ipv4/ipt_TTL.h +++ b/include/linux/netfilter_ipv4/ipt_TTL.h @@ -4,6 +4,8 @@ #ifndef _IPT_TTL_H #define _IPT_TTL_H +#include + enum { IPT_TTL_SET = 0, IPT_TTL_INC, @@ -13,8 +15,8 @@ enum { #define IPT_TTL_MAXMODE IPT_TTL_DEC struct ipt_TTL_info { - u_int8_t mode; - u_int8_t ttl; + __u8 mode; + __u8 ttl; }; diff --git a/include/linux/netfilter_ipv4/ipt_addrtype.h b/include/linux/netfilter_ipv4/ipt_addrtype.h index 446de6ae..0da42237 100644 --- a/include/linux/netfilter_ipv4/ipt_addrtype.h +++ b/include/linux/netfilter_ipv4/ipt_addrtype.h @@ -1,6 +1,8 @@ #ifndef _IPT_ADDRTYPE_H #define _IPT_ADDRTYPE_H +#include + enum { IPT_ADDRTYPE_INVERT_SOURCE = 0x0001, IPT_ADDRTYPE_INVERT_DEST = 0x0002, @@ -9,17 +11,17 @@ enum { }; struct ipt_addrtype_info_v1 { - u_int16_t source; /* source-type mask */ - u_int16_t dest; /* dest-type mask */ - u_int32_t flags; + __u16 source; /* source-type mask */ + __u16 dest; /* dest-type mask */ + __u32 flags; }; /* revision 0 */ struct ipt_addrtype_info { - u_int16_t source; /* source-type mask */ - u_int16_t dest; /* dest-type mask */ - u_int32_t invert_source; - u_int32_t invert_dest; + __u16 source; /* source-type mask */ + __u16 dest; /* dest-type mask */ + __u32 invert_source; + __u32 invert_dest; }; #endif diff --git a/include/linux/netfilter_ipv4/ipt_ah.h b/include/linux/netfilter_ipv4/ipt_ah.h index 2e555b4d..4e02bb01 100644 --- a/include/linux/netfilter_ipv4/ipt_ah.h +++ b/include/linux/netfilter_ipv4/ipt_ah.h @@ -1,9 +1,11 @@ #ifndef _IPT_AH_H #define _IPT_AH_H +#include + struct ipt_ah { - u_int32_t spis[2]; /* Security Parameter Index */ - u_int8_t invflags; /* Inverse flags */ + __u32 spis[2]; /* Security Parameter Index */ + __u8 invflags; /* Inverse flags */ }; diff --git a/include/linux/netfilter_ipv4/ipt_ecn.h b/include/linux/netfilter_ipv4/ipt_ecn.h index 9945baa4..eabf95fb 100644 --- a/include/linux/netfilter_ipv4/ipt_ecn.h +++ b/include/linux/netfilter_ipv4/ipt_ecn.h @@ -8,6 +8,8 @@ */ #ifndef _IPT_ECN_H #define _IPT_ECN_H + +#include #include #define IPT_ECN_IP_MASK (~XT_DSCP_MASK) @@ -20,12 +22,12 @@ /* match info */ struct ipt_ecn_info { - u_int8_t operation; - u_int8_t invert; - u_int8_t ip_ect; + __u8 operation; + __u8 invert; + __u8 ip_ect; union { struct { - u_int8_t ect; + __u8 ect; } tcp; } proto; }; diff --git a/include/linux/netfilter_ipv4/ipt_ttl.h b/include/linux/netfilter_ipv4/ipt_ttl.h index ee24fd86..37bee444 100644 --- a/include/linux/netfilter_ipv4/ipt_ttl.h +++ b/include/linux/netfilter_ipv4/ipt_ttl.h @@ -4,6 +4,8 @@ #ifndef _IPT_TTL_H #define _IPT_TTL_H +#include + enum { IPT_TTL_EQ = 0, /* equals */ IPT_TTL_NE, /* not equals */ @@ -13,8 +15,8 @@ enum { struct ipt_ttl_info { - u_int8_t mode; - u_int8_t ttl; + __u8 mode; + __u8 ttl; }; diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 61790323..3f19a97d 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -23,11 +23,38 @@ #define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN #define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN - #define ip6t_match xt_match #define ip6t_target xt_target #define ip6t_table xt_table #define ip6t_get_revision xt_get_revision +#define ip6t_entry_match xt_entry_match +#define ip6t_entry_target xt_entry_target +#define ip6t_standard_target xt_standard_target +#define ip6t_error_target xt_error_target +#define ip6t_counters xt_counters +#define IP6T_CONTINUE XT_CONTINUE +#define IP6T_RETURN XT_RETURN + +/* Pre-iptables-1.4.0 */ +#include +#define ip6t_tcp xt_tcp +#define ip6t_udp xt_udp +#define IP6T_TCP_INV_SRCPT XT_TCP_INV_SRCPT +#define IP6T_TCP_INV_DSTPT XT_TCP_INV_DSTPT +#define IP6T_TCP_INV_FLAGS XT_TCP_INV_FLAGS +#define IP6T_TCP_INV_OPTION XT_TCP_INV_OPTION +#define IP6T_TCP_INV_MASK XT_TCP_INV_MASK +#define IP6T_UDP_INV_SRCPT XT_UDP_INV_SRCPT +#define IP6T_UDP_INV_DSTPT XT_UDP_INV_DSTPT +#define IP6T_UDP_INV_MASK XT_UDP_INV_MASK + +#define ip6t_counters_info xt_counters_info +#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET +#define IP6T_ERROR_TARGET XT_ERROR_TARGET +#define IP6T_MATCH_ITERATE(e, fn, args...) \ + XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args) +#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ + XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args) /* Yes, Virginia, you have to zero the padding. */ struct ip6t_ip6 { @@ -56,12 +83,6 @@ struct ip6t_ip6 { u_int8_t invflags; }; -#define ip6t_entry_match xt_entry_match -#define ip6t_entry_target xt_entry_target -#define ip6t_standard_target xt_standard_target - -#define ip6t_counters xt_counters - /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper protocols */ @@ -106,17 +127,12 @@ struct ip6t_entry { /* Standard entry */ struct ip6t_standard { struct ip6t_entry entry; - struct ip6t_standard_target target; -}; - -struct ip6t_error_target { - struct ip6t_entry_target target; - char errorname[IP6T_FUNCTION_MAXNAMELEN]; + struct xt_standard_target target; }; struct ip6t_error { struct ip6t_entry entry; - struct ip6t_error_target target; + struct xt_error_target target; }; #define IP6T_ENTRY_INIT(__size) \ @@ -128,16 +144,16 @@ struct ip6t_error { #define IP6T_STANDARD_INIT(__verdict) \ { \ .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)), \ - .target = XT_TARGET_INIT(IP6T_STANDARD_TARGET, \ - sizeof(struct ip6t_standard_target)), \ + .target = XT_TARGET_INIT(XT_STANDARD_TARGET, \ + sizeof(struct xt_standard_target)), \ .target.verdict = -(__verdict) - 1, \ } #define IP6T_ERROR_INIT \ { \ .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)), \ - .target = XT_TARGET_INIT(IP6T_ERROR_TARGET, \ - sizeof(struct ip6t_error_target)), \ + .target = XT_TARGET_INIT(XT_ERROR_TARGET, \ + sizeof(struct xt_error_target)), \ .target.errorname = "ERROR", \ } @@ -160,30 +176,6 @@ struct ip6t_error { #define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 5) #define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET -/* CONTINUE verdict for targets */ -#define IP6T_CONTINUE XT_CONTINUE - -/* For standard target */ -#define IP6T_RETURN XT_RETURN - -/* TCP/UDP matching stuff */ -#include - -#define ip6t_tcp xt_tcp -#define ip6t_udp xt_udp - -/* Values for "inv" field in struct ipt_tcp. */ -#define IP6T_TCP_INV_SRCPT XT_TCP_INV_SRCPT -#define IP6T_TCP_INV_DSTPT XT_TCP_INV_DSTPT -#define IP6T_TCP_INV_FLAGS XT_TCP_INV_FLAGS -#define IP6T_TCP_INV_OPTION XT_TCP_INV_OPTION -#define IP6T_TCP_INV_MASK XT_TCP_INV_MASK - -/* Values for "invflags" field in struct ipt_udp. */ -#define IP6T_UDP_INV_SRCPT XT_UDP_INV_SRCPT -#define IP6T_UDP_INV_DSTPT XT_UDP_INV_DSTPT -#define IP6T_UDP_INV_MASK XT_UDP_INV_MASK - /* ICMP matching stuff */ struct ip6t_icmp { u_int8_t type; /* type to match */ @@ -197,7 +189,7 @@ struct ip6t_icmp { /* The argument to IP6T_SO_GET_INFO */ struct ip6t_getinfo { /* Which table: caller fills this in. */ - char name[IP6T_TABLE_MAXNAMELEN]; + char name[XT_TABLE_MAXNAMELEN]; /* Kernel fills these in. */ /* Which hook entry points are valid: bitmask */ @@ -219,7 +211,7 @@ struct ip6t_getinfo { /* The argument to IP6T_SO_SET_REPLACE. */ struct ip6t_replace { /* Which table. */ - char name[IP6T_TABLE_MAXNAMELEN]; + char name[XT_TABLE_MAXNAMELEN]; /* Which hook entry points are valid: bitmask. You can't change this. */ @@ -247,13 +239,10 @@ struct ip6t_replace { struct ip6t_entry entries[0]; }; -/* The argument to IP6T_SO_ADD_COUNTERS. */ -#define ip6t_counters_info xt_counters_info - /* The argument to IP6T_SO_GET_ENTRIES. */ struct ip6t_get_entries { /* Which table: user fills this in. */ - char name[IP6T_TABLE_MAXNAMELEN]; + char name[XT_TABLE_MAXNAMELEN]; /* User fills this in: total entry size. */ unsigned int size; @@ -262,26 +251,13 @@ struct ip6t_get_entries { struct ip6t_entry entrytable[0]; }; -/* Standard return verdict, or do jump. */ -#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET -/* Error verdict. */ -#define IP6T_ERROR_TARGET XT_ERROR_TARGET - /* Helper functions */ -static __inline__ struct ip6t_entry_target * +static __inline__ struct xt_entry_target * ip6t_get_target(struct ip6t_entry *e) { return (void *)e + e->target_offset; } -/* fn returns 0 to continue iteration */ -#define IP6T_MATCH_ITERATE(e, fn, args...) \ - XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args) - -/* fn returns 0 to continue iteration */ -#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ - XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args) - /* * Main firewall chains definitions and global var's definitions. */ diff --git a/include/linux/netfilter_ipv6/ip6t_HL.h b/include/linux/netfilter_ipv6/ip6t_HL.h index afb7813d..ebd8ead1 100644 --- a/include/linux/netfilter_ipv6/ip6t_HL.h +++ b/include/linux/netfilter_ipv6/ip6t_HL.h @@ -5,6 +5,8 @@ #ifndef _IP6T_HL_H #define _IP6T_HL_H +#include + enum { IP6T_HL_SET = 0, IP6T_HL_INC, @@ -14,8 +16,8 @@ enum { #define IP6T_HL_MAXMODE IP6T_HL_DEC struct ip6t_HL_info { - u_int8_t mode; - u_int8_t hop_limit; + __u8 mode; + __u8 hop_limit; }; diff --git a/include/linux/netfilter_ipv6/ip6t_REJECT.h b/include/linux/netfilter_ipv6/ip6t_REJECT.h index 6be65041..205ed62e 100644 --- a/include/linux/netfilter_ipv6/ip6t_REJECT.h +++ b/include/linux/netfilter_ipv6/ip6t_REJECT.h @@ -1,6 +1,8 @@ #ifndef _IP6T_REJECT_H #define _IP6T_REJECT_H +#include + enum ip6t_reject_with { IP6T_ICMP6_NO_ROUTE, IP6T_ICMP6_ADM_PROHIBITED, @@ -12,7 +14,7 @@ enum ip6t_reject_with { }; struct ip6t_reject_info { - u_int32_t with; /* reject type */ + __u32 with; /* reject type */ }; #endif /*_IP6T_REJECT_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_ah.h b/include/linux/netfilter_ipv6/ip6t_ah.h index 17a745cf..5da2b65c 100644 --- a/include/linux/netfilter_ipv6/ip6t_ah.h +++ b/include/linux/netfilter_ipv6/ip6t_ah.h @@ -1,11 +1,13 @@ #ifndef _IP6T_AH_H #define _IP6T_AH_H +#include + struct ip6t_ah { - u_int32_t spis[2]; /* Security Parameter Index */ - u_int32_t hdrlen; /* Header Length */ - u_int8_t hdrres; /* Test of the Reserved Filed */ - u_int8_t invflags; /* Inverse flags */ + __u32 spis[2]; /* Security Parameter Index */ + __u32 hdrlen; /* Header Length */ + __u8 hdrres; /* Test of the Reserved Filed */ + __u8 invflags; /* Inverse flags */ }; #define IP6T_AH_SPI 0x01 diff --git a/include/linux/netfilter_ipv6/ip6t_frag.h b/include/linux/netfilter_ipv6/ip6t_frag.h index 3724d085..b47f61b9 100644 --- a/include/linux/netfilter_ipv6/ip6t_frag.h +++ b/include/linux/netfilter_ipv6/ip6t_frag.h @@ -1,11 +1,13 @@ #ifndef _IP6T_FRAG_H #define _IP6T_FRAG_H +#include + struct ip6t_frag { - u_int32_t ids[2]; /* Security Parameter Index */ - u_int32_t hdrlen; /* Header Length */ - u_int8_t flags; /* */ - u_int8_t invflags; /* Inverse flags */ + __u32 ids[2]; /* Security Parameter Index */ + __u32 hdrlen; /* Header Length */ + __u8 flags; /* */ + __u8 invflags; /* Inverse flags */ }; #define IP6T_FRAG_IDS 0x01 diff --git a/include/linux/netfilter_ipv6/ip6t_hl.h b/include/linux/netfilter_ipv6/ip6t_hl.h index 5ef91b83..6e76dbc6 100644 --- a/include/linux/netfilter_ipv6/ip6t_hl.h +++ b/include/linux/netfilter_ipv6/ip6t_hl.h @@ -5,6 +5,8 @@ #ifndef _IP6T_HL_H #define _IP6T_HL_H +#include + enum { IP6T_HL_EQ = 0, /* equals */ IP6T_HL_NE, /* not equals */ @@ -14,8 +16,8 @@ enum { struct ip6t_hl_info { - u_int8_t mode; - u_int8_t hop_limit; + __u8 mode; + __u8 hop_limit; }; diff --git a/include/linux/netfilter_ipv6/ip6t_ipv6header.h b/include/linux/netfilter_ipv6/ip6t_ipv6header.h index 01dfd445..efae3a20 100644 --- a/include/linux/netfilter_ipv6/ip6t_ipv6header.h +++ b/include/linux/netfilter_ipv6/ip6t_ipv6header.h @@ -8,10 +8,12 @@ on whether they contain certain headers */ #ifndef __IPV6HEADER_H #define __IPV6HEADER_H +#include + struct ip6t_ipv6header_info { - u_int8_t matchflags; - u_int8_t invflags; - u_int8_t modeflag; + __u8 matchflags; + __u8 invflags; + __u8 modeflag; }; #define MASK_HOPOPTS 128 diff --git a/include/linux/netfilter_ipv6/ip6t_mh.h b/include/linux/netfilter_ipv6/ip6t_mh.h index 18549bca..a7729a50 100644 --- a/include/linux/netfilter_ipv6/ip6t_mh.h +++ b/include/linux/netfilter_ipv6/ip6t_mh.h @@ -1,10 +1,12 @@ #ifndef _IP6T_MH_H #define _IP6T_MH_H +#include + /* MH matching stuff */ struct ip6t_mh { - u_int8_t types[2]; /* MH type range */ - u_int8_t invflags; /* Inverse flags */ + __u8 types[2]; /* MH type range */ + __u8 invflags; /* Inverse flags */ }; /* Values for "invflags" field in struct ip6t_mh. */ diff --git a/include/linux/netfilter_ipv6/ip6t_opts.h b/include/linux/netfilter_ipv6/ip6t_opts.h index 62d89bcd..17d419a8 100644 --- a/include/linux/netfilter_ipv6/ip6t_opts.h +++ b/include/linux/netfilter_ipv6/ip6t_opts.h @@ -1,14 +1,16 @@ #ifndef _IP6T_OPTS_H #define _IP6T_OPTS_H +#include + #define IP6T_OPTS_OPTSNR 16 struct ip6t_opts { - u_int32_t hdrlen; /* Header Length */ - u_int8_t flags; /* */ - u_int8_t invflags; /* Inverse flags */ - u_int16_t opts[IP6T_OPTS_OPTSNR]; /* opts */ - u_int8_t optsnr; /* Nr of OPts */ + __u32 hdrlen; /* Header Length */ + __u8 flags; /* */ + __u8 invflags; /* Inverse flags */ + __u16 opts[IP6T_OPTS_OPTSNR]; /* opts */ + __u8 optsnr; /* Nr of OPts */ }; #define IP6T_OPTS_LEN 0x01 diff --git a/include/linux/netfilter_ipv6/ip6t_rt.h b/include/linux/netfilter_ipv6/ip6t_rt.h index ab91bfd2..7605a5ff 100644 --- a/include/linux/netfilter_ipv6/ip6t_rt.h +++ b/include/linux/netfilter_ipv6/ip6t_rt.h @@ -1,18 +1,19 @@ #ifndef _IP6T_RT_H #define _IP6T_RT_H +#include /*#include */ #define IP6T_RT_HOPS 16 struct ip6t_rt { - u_int32_t rt_type; /* Routing Type */ - u_int32_t segsleft[2]; /* Segments Left */ - u_int32_t hdrlen; /* Header Length */ - u_int8_t flags; /* */ - u_int8_t invflags; /* Inverse flags */ + __u32 rt_type; /* Routing Type */ + __u32 segsleft[2]; /* Segments Left */ + __u32 hdrlen; /* Header Length */ + __u8 flags; /* */ + __u8 invflags; /* Inverse flags */ struct in6_addr addrs[IP6T_RT_HOPS]; /* Hops */ - u_int8_t addrnr; /* Nr of Addresses */ + __u8 addrnr; /* Nr of Addresses */ }; #define IP6T_RT_TYP 0x01 diff --git a/include/linux/types.h b/include/linux/types.h index 8b483c80..630cd3bb 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -34,5 +34,18 @@ typedef __u64 __bitwise __be64; typedef __u16 __bitwise __sum16; typedef __u32 __bitwise __wsum; +/* + * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid + * common 32/64-bit compat problems. + * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other + * architectures) and to 8-byte boundaries on 64-bit architetures. The new + * aligned_64 type enforces 8-byte alignment so that structs containing + * aligned_64 values have the same alignment on 32-bit and 64-bit architectures. + * No conversions are necessary between 32-bit user-space and a 64-bit kernel. + */ +#define __aligned_u64 __u64 __attribute__((aligned(8))) +#define __aligned_be64 __be64 __attribute__((aligned(8))) +#define __aligned_le64 __le64 __attribute__((aligned(8))) + #endif /* __ASSEMBLY__ */ #endif /* _LINUX_TYPES_H */ -- cgit v1.2.3 From 5df067f91b8ffa7801d09e6dd13fe9bf4b7b490b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 1 Sep 2011 18:30:42 +0200 Subject: Bump version to 1.4.12.1 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 84fa47a4..22b7bf15 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.12]) +AC_INIT([iptables], [1.4.12.1]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=7 -- cgit v1.2.3 From d4e72dc1c684c2f8361d87e6bde2902cd2ee8efb Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 3 Sep 2011 13:34:40 +0200 Subject: libxt_statistic: link with -lm $ ldd -r libxt_statistic.so undefined symbol: lround (./libxt_statistic.so) References: https://bugs.archlinux.org/task/25358 Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 5 ++++- iptables/Makefile.am | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 2b48d841..dbf210cc 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -90,11 +90,14 @@ init%.o: init%.c # Shared libraries # lib%.so: lib%.oo - ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<; + ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< ${$*_LIBADD}; lib%.oo: ${srcdir}/lib%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; +# Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD +xt_statistic_LIBADD = -lm + # # Static bits diff --git a/iptables/Makefile.am b/iptables/Makefile.am index addb1598..f6db32d0 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -6,12 +6,17 @@ AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir} lib_LTLIBRARIES = libxtables.la libxtables_la_SOURCES = xtables.c xtoptions.c libxtables_la_LDFLAGS = -version-info ${libxtables_vcurrent}:0:${libxtables_vage} +libxtables_la_LIBADD = +if ENABLE_STATIC +# With --enable-static, shipped extensions are linked into the main executable, +# so we need all the LIBADDs here too +libxtables_la_LIBADD += -lm +endif if ENABLE_SHARED libxtables_la_CFLAGS = ${AM_CFLAGS} -libxtables_la_LIBADD = -ldl +libxtables_la_LIBADD += -ldl else libxtables_la_CFLAGS = ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -libxtables_la_LIBADD = endif xtables_multi_SOURCES = xtables-multi.c iptables-xml.c -- cgit v1.2.3 From 9249ad37b2342eb48009e18f3982362e1018ea5a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 3 Sep 2011 13:35:53 +0200 Subject: libxt_RATEEST: link with -lm $ ldd -r libxt_RATEEST.so undefined symbol: log (./libxt_RATEEST.so) Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index dbf210cc..107c9d59 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -96,6 +96,7 @@ lib%.oo: ${srcdir}/lib%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD +xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm -- cgit v1.2.3 From 751da923262746bf8fd3195e178504fb18c37dc5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 3 Sep 2011 14:11:53 +0200 Subject: build: scan for unreferenced symbols To be notified of occurrences where we are missing any libraries, run some ldd checks post building. Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 107c9d59..a9edb1e6 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -68,7 +68,16 @@ targets_install := .PHONY: all install clean distclean FORCE -all: ${targets} +all: ${targets} check + +check: ${targets} + @echo " CHECK unknown symbols in .so files"; \ + . ../iptables/libxtables.la; \ + for i in "" lib*.so; do \ + [ -z "$$i" ] && continue; \ + LD_PRELOAD="$$dlname" LD_LIBRARY_PATH=../iptables/.libs \ + ldd -r $$i 2>&1 >/dev/null; \ + done; install: ${targets_install} @mkdir -p "${DESTDIR}${xtlibdir}"; -- cgit v1.2.3 From f56b8a8bf4b1041cb875fd8439778f35276bdb30 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 3 Sep 2011 14:27:55 +0200 Subject: iptables: move kernel version find routing into libxtables That way, the remaining unreferenced symbols that do appear in libipt_DNAT and libipt_SNAT as part of the new check can be resolved, and the ugly -rdynamic hack can finally be removed. Signed-off-by: Jan Engelhardt --- Makefile.am | 3 ++- include/iptables.h | 8 -------- include/xtables.h.in | 8 ++++++++ iptables/Makefile.am | 1 - iptables/iptables.c | 18 ------------------ iptables/xtables.c | 18 ++++++++++++++++++ 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Makefile.am b/Makefile.am index 34b35012..9167e8e3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign subdir-objects -SUBDIRS = extensions libiptc iptables +SUBDIRS = libiptc iptables if ENABLE_DEVEL SUBDIRS += include endif @@ -13,6 +13,7 @@ endif if HAVE_LIBNFNETLINK SUBDIRS += utils endif +SUBDIRS += extensions .PHONY: tarball tarball: diff --git a/include/iptables.h b/include/iptables.h index 65b32909..89217e29 100644 --- a/include/iptables.h +++ b/include/iptables.h @@ -18,14 +18,6 @@ extern int for_each_chain4(int (*fn)(const ipt_chainlabel, int, struct iptc_hand extern void print_rule4(const struct ipt_entry *e, struct iptc_handle *handle, const char *chain, int counters); -/* kernel revision handling */ -extern int kernel_version; -extern void get_kernel_version(void); -#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) -#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF) -#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF) -#define LINUX_VERSION_PATCH(x) ( (x) & 0xFF) - extern struct xtables_globals iptables_globals; #endif /*_IPTABLES_USER_H*/ diff --git a/include/xtables.h.in b/include/xtables.h.in index d50df79a..28e29337 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -477,6 +477,14 @@ extern void xtables_save_string(const char *value); extern const struct xtables_pprot xtables_chain_protos[]; extern u_int16_t xtables_parse_protocol(const char *s); +/* kernel revision handling */ +extern int kernel_version; +extern void get_kernel_version(void); +#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) +#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF) +#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF) +#define LINUX_VERSION_PATCH(x) ( (x) & 0xFF) + /* xtoptions.c */ extern void xtables_option_metavalidate(const char *, const struct xt_option_entry *); diff --git a/iptables/Makefile.am b/iptables/Makefile.am index f6db32d0..af620f76 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -21,7 +21,6 @@ endif xtables_multi_SOURCES = xtables-multi.c iptables-xml.c xtables_multi_CFLAGS = ${AM_CFLAGS} -xtables_multi_LDFLAGS = -rdynamic xtables_multi_LDADD = ../extensions/libext.a if ENABLE_STATIC xtables_multi_CFLAGS += -DALL_INCLUSIVE diff --git a/iptables/iptables.c b/iptables/iptables.c index 50dc1e7a..830ddbcb 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -39,7 +39,6 @@ #include #include #include -#include #include "xshared.h" #ifndef TRUE @@ -187,8 +186,6 @@ static const int inverse_for_options[NUMBER_OF_OPT] = #define prog_name iptables_globals.program_name #define prog_vers iptables_globals.program_version -int kernel_version; - /* Primitive headers... */ /* defined in netinet/in.h */ #if 0 @@ -1281,21 +1278,6 @@ static void clear_rule_matches(struct xtables_rule_match **matches) *matches = NULL; } -void -get_kernel_version(void) { - static struct utsname uts; - int x = 0, y = 0, z = 0; - - if (uname(&uts) == -1) { - fprintf(stderr, "Unable to retrieve kernel version.\n"); - xtables_free_opts(1); - exit(1); - } - - sscanf(uts.release, "%d.%d.%d", &x, &y, &z); - kernel_version = LINUX_VERSION(x, y, z); -} - static void command_jump(struct iptables_command_state *cs) { size_t size; diff --git a/iptables/xtables.c b/iptables/xtables.c index e72aa284..014e115b 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #if defined(HAVE_LINUX_MAGIC_H) @@ -1812,3 +1813,20 @@ xtables_parse_protocol(const char *s) "unknown protocol \"%s\" specified", s); return -1; } + +int kernel_version; + +void get_kernel_version(void) +{ + static struct utsname uts; + int x = 0, y = 0, z = 0; + + if (uname(&uts) == -1) { + fprintf(stderr, "Unable to retrieve kernel version.\n"); + xtables_free_opts(1); + exit(1); + } + + sscanf(uts.release, "%d.%d.%d", &x, &y, &z); + kernel_version = LINUX_VERSION(x, y, z); +} -- cgit v1.2.3 From 153c23d9b14285b24aae3e96da0b547dcc7ee051 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Fri, 2 Sep 2011 17:45:51 -0700 Subject: libxt_CONNSECMARK: fix spacing in output ~# iptables -t mangle -A foo -j CONNSECMARK --save ~# iptables -t mangle -S [...] -A foo -j CONNSECMARK--save Signed-off-by: Jan Engelhardt --- extensions/libxt_CONNSECMARK.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_CONNSECMARK.c b/extensions/libxt_CONNSECMARK.c index df2e6b82..0b3cd79d 100644 --- a/extensions/libxt_CONNSECMARK.c +++ b/extensions/libxt_CONNSECMARK.c @@ -87,7 +87,7 @@ CONNSECMARK_save(const void *ip, const struct xt_entry_target *target) const struct xt_connsecmark_target_info *info = (struct xt_connsecmark_target_info*)target->data; - printf("--"); + printf(" --"); print_connsecmark(info); } -- cgit v1.2.3 From 5e5ea1ccf61d96879531929874109c17c1894908 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 8 Sep 2011 17:08:37 +0200 Subject: build: sort file list before build Manpage subsections are already sorted for obvious reasons. Since $(wildcard) can actually return results unordered (just what the OS can do) do the sorting with the .o file list too, for developer comfort. Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index a9edb1e6..60f28c0c 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -37,9 +37,9 @@ endif # # Wildcard module list # -pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(wildcard ${srcdir}/libxt_*.c)) -@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(wildcard ${srcdir}/libipt_*.c)) -@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(wildcard ${srcdir}/libip6t_*.c)) +pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c))) +@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c))) +@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c))) pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod}) pf4_build_mod := $(filter-out @blacklist_modules@,${pf4_build_mod}) pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod}) @@ -198,11 +198,11 @@ initext6.c: .initext6.dd # # Manual pages # -ex_matches = $(sort $(shell echo $(1) | LC_ALL=POSIX grep -Eo '\b[[:lower:][:digit:]_]+\b')) -ex_targets = $(sort $(shell echo $(1) | LC_ALL=POSIX grep -Eo '\b[[:upper:][:digit:]_]+\b')) +ex_matches = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:lower:][:digit:]_]+\b') +ex_targets = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:upper:][:digit:]_]+\b') man_run = \ ${AM_VERBOSE_GEN} \ - for ext in $(1); do \ + for ext in $(sort ${1}); do \ f="${srcdir}/libxt_$$ext.man"; \ cf="${srcdir}/libxt_$$ext.c"; \ if [ -f "$$f" ] && grep -Eq "$(3)|NFPROTO_UNSPEC" "$$cf"; then \ -- cgit v1.2.3 From 5fa68e820a641039e48045a82560ed13471ecff4 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 09:21:46 +0200 Subject: doc: fix undesired newline in ip6tables-restore(8) Signed-off-by: Jan Engelhardt --- iptables/ip6tables-restore.8 | 1 - 1 file changed, 1 deletion(-) diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index 02648070..aa09768f 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -32,7 +32,6 @@ I/O redirection provided by your shell to read from a file restore the values of all packet and byte counters .TP \fB\-n\fR, \fB\-\-noflush\fR -.TP don't flush the previous contents of the table. If not specified, .B ip6tables-restore flushes (deletes) all previous contents of the respective IPv6 Table. -- cgit v1.2.3 From b171b546cb529e2996df05fe91cba058fae9fd99 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 09:29:30 +0200 Subject: ip6tables-restore: implement missing -T option Commit v1.4.0-rc1-12-ge8665f8 forgot to port the change to the ip6tables part. Signed-off-by: Jan Engelhardt --- iptables/ip6tables-restore.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 985744d6..1487504b 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -36,6 +36,7 @@ static const struct option options[] = { {.name = "help", .has_arg = false, .val = 'h'}, {.name = "noflush", .has_arg = false, .val = 'n'}, {.name = "modprobe", .has_arg = true, .val = 'M'}, + {.name = "table", .has_arg = true, .val = 'T'}, {NULL}, }; @@ -121,6 +122,7 @@ int ip6tables_restore_main(int argc, char *argv[]) char curtable[IP6T_TABLE_MAXNAMELEN + 1]; FILE *in; int in_table = 0, testing = 0; + const char *tablename = NULL; line = 0; @@ -137,7 +139,7 @@ int ip6tables_restore_main(int argc, char *argv[]) init_extensions6(); #endif - while ((c = getopt_long(argc, argv, "bcvthnM:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "bcvthnM:T:", options, NULL)) != -1) { switch (c) { case 'b': binary = 1; @@ -161,6 +163,9 @@ int ip6tables_restore_main(int argc, char *argv[]) case 'M': xtables_modprobe_program = optarg; break; + case 'T': + tablename = optarg; + break; } } @@ -216,6 +221,8 @@ int ip6tables_restore_main(int argc, char *argv[]) strncpy(curtable, table, IP6T_TABLE_MAXNAMELEN); curtable[IP6T_TABLE_MAXNAMELEN] = '\0'; + if (tablename != NULL && strcmp(tablename, table) != 0) + continue; if (handle) ip6tc_free(handle); @@ -442,6 +449,8 @@ int ip6tables_restore_main(int argc, char *argv[]) free_argv(); fflush(stdout); } + if (tablename != NULL && strcmp(tablename, curtable) != 0) + continue; if (!ret) { fprintf(stderr, "%s: line %u failed\n", ip6tables_globals.program_name, -- cgit v1.2.3 From 1e4965232d77ab752c9c781afcf854f4b173c7b1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 09:31:35 +0200 Subject: doc: document iptables-restore's -T option Commit v1.4.0-rc1-12-ge8665f8 completely forgot this. Signed-off-by: Jan Engelhardt --- iptables/ip6tables-restore.8 | 3 +++ iptables/iptables-restore.8 | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index aa09768f..59a3b2e5 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -33,6 +33,9 @@ restore the values of all packet and byte counters .TP \fB\-n\fR, \fB\-\-noflush\fR don't flush the previous contents of the table. If not specified, +.TP +\fB\-T\fP, \fB\-\-table\fP \fIname\fP +Restore only the named table even if the input stream contains other ones. .B ip6tables-restore flushes (deletes) all previous contents of the respective IPv6 Table. .SH BUGS diff --git a/iptables/iptables-restore.8 b/iptables/iptables-restore.8 index a52bcebe..0dd20cb1 100644 --- a/iptables/iptables-restore.8 +++ b/iptables/iptables-restore.8 @@ -21,7 +21,7 @@ .SH NAME iptables-restore \(em Restore IP Tables .SH SYNOPSIS -\fBiptables\-restore\fP [\fB\-c\fP] [\fB\-n\fP] +\fBiptables\-restore\fP [\fB\-c\fP] [\fB\-n\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B iptables-restore @@ -35,6 +35,9 @@ restore the values of all packet and byte counters don't flush the previous contents of the table. If not specified, .B iptables-restore flushes (deletes) all previous contents of the respective IP Table. +.TP +\fB\-T\fP, \fB\-\-table\fP \fIname\fP +Restore only the named table even if the input stream contains other ones. .SH BUGS None known as of iptables-1.2.1 release .SH AUTHOR -- cgit v1.2.3 From 9cf67deb62f127902e686c48b951861bf848d0ab Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 11 Sep 2011 17:24:26 +0200 Subject: libiptc: resolve compile failure CC libip4tc.lo In file included from libip4tc.c:118:0: libiptc.c:70:8: error: redefinition of "struct xt_error_target" ../include/linux/netfilter/x_tables.h:69:8: note: originally defined here Remove libiptc's duplicate definition and substitute names. Signed-off-by: Jan Engelhardt --- libiptc/libiptc.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 42d9784a..2214077e 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -67,12 +67,6 @@ static const char *hooknames[] = { }; /* Convenience structures */ -struct ipt_error_target -{ - STRUCT_ENTRY_TARGET t; - char error[TABLE_MAXNAMELEN]; -}; - struct chain_head; struct rule_head; @@ -1092,10 +1086,10 @@ static int parse_table(struct xtc_handle *h) /* Convenience structures */ struct iptcb_chain_start{ STRUCT_ENTRY e; - struct ipt_error_target name; + struct xt_error_target name; }; #define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ - ALIGN(sizeof(struct ipt_error_target))) + ALIGN(sizeof(struct xt_error_target))) struct iptcb_chain_foot { STRUCT_ENTRY e; @@ -1106,10 +1100,10 @@ struct iptcb_chain_foot { struct iptcb_chain_error { STRUCT_ENTRY entry; - struct ipt_error_target target; + struct xt_error_target target; }; #define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ - ALIGN(sizeof(struct ipt_error_target))) + ALIGN(sizeof(struct xt_error_target))) @@ -1152,10 +1146,10 @@ static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struc head = (void *)repl->entries + c->head_offset; head->e.target_offset = sizeof(STRUCT_ENTRY); head->e.next_offset = IPTCB_CHAIN_START_SIZE; - strcpy(head->name.t.u.user.name, ERROR_TARGET); - head->name.t.u.target_size = - ALIGN(sizeof(struct ipt_error_target)); - strcpy(head->name.error, c->name); + strcpy(head->name.target.u.user.name, ERROR_TARGET); + head->name.target.u.target_size = + ALIGN(sizeof(struct xt_error_target)); + strcpy(head->name.errorname, c->name); } else { repl->hook_entry[c->hooknum-1] = c->head_offset; repl->underflow[c->hooknum-1] = c->foot_offset; @@ -1198,7 +1192,7 @@ static int iptcc_compile_chain_offsets(struct xtc_handle *h, struct chain_head * if (!iptcc_is_builtin(c)) { /* Chain has header */ *offset += sizeof(STRUCT_ENTRY) - + ALIGN(sizeof(struct ipt_error_target)); + + ALIGN(sizeof(struct xt_error_target)); (*num)++; } @@ -1238,7 +1232,7 @@ static int iptcc_compile_table_prep(struct xtc_handle *h, unsigned int *size) /* Append one error rule at end of chain */ num++; offset += sizeof(STRUCT_ENTRY) - + ALIGN(sizeof(struct ipt_error_target)); + + ALIGN(sizeof(struct xt_error_target)); /* ruleset size is now in offset */ *size = offset; @@ -1261,10 +1255,10 @@ static int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl) error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; error->entry.target_offset = sizeof(STRUCT_ENTRY); error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; - error->target.t.u.user.target_size = - ALIGN(sizeof(struct ipt_error_target)); - strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); - strcpy((char *)&error->target.error, "ERROR"); + error->target.target.u.user.target_size = + ALIGN(sizeof(struct xt_error_target)); + strcpy((char *)&error->target.target.u.user.name, ERROR_TARGET); + strcpy((char *)&error->target.errorname, "ERROR"); return 1; } -- cgit v1.2.3 From 296dca39be1166c4b7c6367c1b97ee95aebddfc3 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 13:06:37 +0200 Subject: iptables-save: remove binary dumping dead code Was never implemented, kill it. Signed-off-by: Jan Engelhardt --- iptables/ip6tables-save.c | 80 ++++++++++++++++++++--------------------------- iptables/iptables-save.c | 80 ++++++++++++++++++++--------------------------- 2 files changed, 68 insertions(+), 92 deletions(-) diff --git a/iptables/ip6tables-save.c b/iptables/ip6tables-save.c index ad0e70f0..38b0c2f2 100644 --- a/iptables/ip6tables-save.c +++ b/iptables/ip6tables-save.c @@ -22,10 +22,9 @@ #include #endif -static int show_binary = 0, show_counters = 0; +static int show_counters = 0; static const struct option options[] = { - {.name = "binary", .has_arg = false, .val = 'b'}, {.name = "counters", .has_arg = false, .val = 'c'}, {.name = "dump", .has_arg = false, .val = 'd'}, {.name = "table", .has_arg = true, .val = 't'}, @@ -76,52 +75,45 @@ static int do_output(const char *tablename) xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n", ip6tc_strerror(errno)); - if (!show_binary) { - time_t now = time(NULL); - - printf("# Generated by ip6tables-save v%s on %s", - IPTABLES_VERSION, ctime(&now)); - printf("*%s\n", tablename); - - /* Dump out chain names first, - * thereby preventing dependency conflicts */ - for (chain = ip6tc_first_chain(h); - chain; - chain = ip6tc_next_chain(h)) { - - printf(":%s ", chain); - if (ip6tc_builtin(chain, h)) { - struct ip6t_counters count; - printf("%s ", - ip6tc_get_policy(chain, &count, h)); - printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); - } else { - printf("- [0:0]\n"); - } + time_t now = time(NULL); + + printf("# Generated by ip6tables-save v%s on %s", + IPTABLES_VERSION, ctime(&now)); + printf("*%s\n", tablename); + + /* Dump out chain names first, + * thereby preventing dependency conflicts */ + for (chain = ip6tc_first_chain(h); + chain; + chain = ip6tc_next_chain(h)) { + + printf(":%s ", chain); + if (ip6tc_builtin(chain, h)) { + struct ip6t_counters count; + printf("%s ", + ip6tc_get_policy(chain, &count, h)); + printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); + } else { + printf("- [0:0]\n"); } + } + for (chain = ip6tc_first_chain(h); + chain; + chain = ip6tc_next_chain(h)) { + const struct ip6t_entry *e; - for (chain = ip6tc_first_chain(h); - chain; - chain = ip6tc_next_chain(h)) { - const struct ip6t_entry *e; - - /* Dump out rules */ - e = ip6tc_first_rule(chain, h); - while(e) { - print_rule6(e, h, chain, show_counters); - e = ip6tc_next_rule(e, h); - } + /* Dump out rules */ + e = ip6tc_first_rule(chain, h); + while(e) { + print_rule6(e, h, chain, show_counters); + e = ip6tc_next_rule(e, h); } - - now = time(NULL); - printf("COMMIT\n"); - printf("# Completed on %s", ctime(&now)); - } else { - /* Binary, huh? OK. */ - xtables_error(OTHER_PROBLEM, "Binary NYI\n"); } + now = time(NULL); + printf("COMMIT\n"); + printf("# Completed on %s", ctime(&now)); ip6tc_free(h); return 1; @@ -151,10 +143,6 @@ int ip6tables_save_main(int argc, char *argv[]) while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) { switch (c) { - case 'b': - show_binary = 1; - break; - case 'c': show_counters = 1; break; diff --git a/iptables/iptables-save.c b/iptables/iptables-save.c index 73fba12a..a25a186e 100644 --- a/iptables/iptables-save.c +++ b/iptables/iptables-save.c @@ -21,10 +21,9 @@ #include #endif -static int show_binary = 0, show_counters = 0; +static int show_counters = 0; static const struct option options[] = { - {.name = "binary", .has_arg = false, .val = 'b'}, {.name = "counters", .has_arg = false, .val = 'c'}, {.name = "dump", .has_arg = false, .val = 'd'}, {.name = "table", .has_arg = true, .val = 't'}, @@ -74,52 +73,45 @@ static int do_output(const char *tablename) xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n", iptc_strerror(errno)); - if (!show_binary) { - time_t now = time(NULL); - - printf("# Generated by iptables-save v%s on %s", - IPTABLES_VERSION, ctime(&now)); - printf("*%s\n", tablename); - - /* Dump out chain names first, - * thereby preventing dependency conflicts */ - for (chain = iptc_first_chain(h); - chain; - chain = iptc_next_chain(h)) { - - printf(":%s ", chain); - if (iptc_builtin(chain, h)) { - struct ipt_counters count; - printf("%s ", - iptc_get_policy(chain, &count, h)); - printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); - } else { - printf("- [0:0]\n"); - } + time_t now = time(NULL); + + printf("# Generated by iptables-save v%s on %s", + IPTABLES_VERSION, ctime(&now)); + printf("*%s\n", tablename); + + /* Dump out chain names first, + * thereby preventing dependency conflicts */ + for (chain = iptc_first_chain(h); + chain; + chain = iptc_next_chain(h)) { + + printf(":%s ", chain); + if (iptc_builtin(chain, h)) { + struct ipt_counters count; + printf("%s ", + iptc_get_policy(chain, &count, h)); + printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); + } else { + printf("- [0:0]\n"); } + } + for (chain = iptc_first_chain(h); + chain; + chain = iptc_next_chain(h)) { + const struct ipt_entry *e; - for (chain = iptc_first_chain(h); - chain; - chain = iptc_next_chain(h)) { - const struct ipt_entry *e; - - /* Dump out rules */ - e = iptc_first_rule(chain, h); - while(e) { - print_rule4(e, h, chain, show_counters); - e = iptc_next_rule(e, h); - } + /* Dump out rules */ + e = iptc_first_rule(chain, h); + while(e) { + print_rule4(e, h, chain, show_counters); + e = iptc_next_rule(e, h); } - - now = time(NULL); - printf("COMMIT\n"); - printf("# Completed on %s", ctime(&now)); - } else { - /* Binary, huh? OK. */ - xtables_error(OTHER_PROBLEM, "Binary NYI\n"); } + now = time(NULL); + printf("COMMIT\n"); + printf("# Completed on %s", ctime(&now)); iptc_free(h); return 1; @@ -150,10 +142,6 @@ iptables_save_main(int argc, char *argv[]) while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) { switch (c) { - case 'b': - show_binary = 1; - break; - case 'c': show_counters = 1; break; -- cgit v1.2.3 From 160f25b09fc5695a65a8aaf485ebece85e1f853c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 10:59:31 +0200 Subject: libiptc: remove unused HOOK_DROPPING thing Signed-off-by: Jan Engelhardt --- libiptc/libip4tc.c | 12 ------------ libiptc/libiptc.c | 3 --- 2 files changed, 15 deletions(-) diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c index cf66709e..3b0c15af 100644 --- a/libiptc/libip4tc.c +++ b/libiptc/libip4tc.c @@ -36,9 +36,6 @@ typedef unsigned int socklen_t; #define HOOK_FORWARD NF_IP_FORWARD #define HOOK_LOCAL_OUT NF_IP_LOCAL_OUT #define HOOK_POST_ROUTING NF_IP_POST_ROUTING -#ifdef NF_IP_DROPPING -#define HOOK_DROPPING NF_IP_DROPPING -#endif #define STRUCT_ENTRY_TARGET struct ipt_entry_target #define STRUCT_ENTRY struct ipt_entry @@ -426,15 +423,6 @@ do_check(struct iptc_handle *h, unsigned int line) assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n); user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT]; - -#ifdef NF_IP_DROPPING - } else if (strcmp(h->info.name, "drop") == 0) { - assert(h->info.valid_hooks == (1 << NF_IP_DROPPING)); - - /* Hook should be first */ - assert(h->info.hook_entry[NF_IP_DROPPING] == 0); - user_offset = 0; -#endif } else { fprintf(stderr, "Unknown table `%s'\n", h->info.name); abort(); diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 2214077e..0a29a690 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -61,9 +61,6 @@ static const char *hooknames[] = { [HOOK_FORWARD] = "FORWARD", [HOOK_LOCAL_OUT] = "OUTPUT", [HOOK_POST_ROUTING] = "POSTROUTING", -#ifdef HOOK_DROPPING - [HOOK_DROPPING] = "DROPPING" -#endif }; /* Convenience structures */ -- cgit v1.2.3 From 2325c0fedf7507f94aa3bb11cc65a70d33836f8f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 11:12:49 +0200 Subject: libiptc: combine common types Make an xt_chainlabel type out of ipt_chainlabel and ip6t_chainlabel, and add backward-API #defines. The ABI naturally does not change either, so no soversion bump. Signed-off-by: Jan Engelhardt --- include/Makefile.am | 2 +- include/libiptc/libip6tc.h | 3 ++- include/libiptc/libiptc.h | 3 ++- include/libiptc/xtcshared.h | 6 ++++++ 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 include/libiptc/xtcshared.h diff --git a/include/Makefile.am b/include/Makefile.am index 0a1abea4..6f7da598 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -9,4 +9,4 @@ endif nobase_include_HEADERS += \ libiptc/ipt_kernel_headers.h libiptc/libiptc.h \ - libiptc/libip6tc.h libiptc/libxtc.h + libiptc/libip6tc.h libiptc/libxtc.h libiptc/xtcshared.h diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index 4f2d1f87..55e0bfc9 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -10,10 +10,11 @@ # include /* INT_MAX in ip6_tables.h */ #endif #include +#include struct ip6tc_handle; -typedef char ip6t_chainlabel[32]; +#define ip6t_chainlabel xt_chainlabel #define IP6TC_LABEL_ACCEPT "ACCEPT" #define IP6TC_LABEL_DROP "DROP" diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index 3497d6ae..ccbf6bff 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -10,6 +10,7 @@ # include /* INT_MAX in ip_tables.h */ #endif #include +#include #ifdef __cplusplus extern "C" { @@ -17,7 +18,7 @@ extern "C" { struct iptc_handle; -typedef char ipt_chainlabel[32]; +#define ipt_chainlabel xt_chainlabel #define IPTC_LABEL_ACCEPT "ACCEPT" #define IPTC_LABEL_DROP "DROP" diff --git a/include/libiptc/xtcshared.h b/include/libiptc/xtcshared.h new file mode 100644 index 00000000..aaf87a4b --- /dev/null +++ b/include/libiptc/xtcshared.h @@ -0,0 +1,6 @@ +#ifndef _LIBXTC_SHARED_H +#define _LIBXTC_SHARED_H 1 + +typedef char xt_chainlabel[32]; + +#endif /* _LIBXTC_SHARED_H */ -- cgit v1.2.3 From 7e5e866a36a76c153e5903b8251f90cfe07a1d34 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 11:16:16 +0200 Subject: libiptc: replace ipt_chainlabel by xt_chainlabel Signed-off-by: Jan Engelhardt --- include/ip6tables.h | 6 +++--- include/iptables.h | 6 +++--- include/libiptc/libip6tc.h | 38 +++++++++++++++++++------------------- include/libiptc/libiptc.h | 38 +++++++++++++++++++------------------- iptables/ip6tables.c | 30 +++++++++++++++--------------- iptables/iptables.c | 30 +++++++++++++++--------------- libiptc/libip4tc.c | 2 +- libiptc/libip6tc.c | 2 +- 8 files changed, 76 insertions(+), 76 deletions(-) diff --git a/include/ip6tables.h b/include/ip6tables.h index e976361f..1def3938 100644 --- a/include/ip6tables.h +++ b/include/ip6tables.h @@ -10,9 +10,9 @@ extern int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **handle); -extern int for_each_chain6(int (*fn)(const ip6t_chainlabel, int, struct ip6tc_handle *), int verbose, int builtinstoo, struct ip6tc_handle *handle); -extern int flush_entries6(const ip6t_chainlabel chain, int verbose, struct ip6tc_handle *handle); -extern int delete_chain6(const ip6t_chainlabel chain, int verbose, struct ip6tc_handle *handle); +extern int for_each_chain6(int (*fn)(const xt_chainlabel, int, struct ip6tc_handle *), int verbose, int builtinstoo, struct ip6tc_handle *handle); +extern int flush_entries6(const xt_chainlabel chain, int verbose, struct ip6tc_handle *handle); +extern int delete_chain6(const xt_chainlabel chain, int verbose, struct ip6tc_handle *handle); void print_rule6(const struct ip6t_entry *e, struct ip6tc_handle *h, const char *chain, int counters); extern struct xtables_globals ip6tables_globals; diff --git a/include/iptables.h b/include/iptables.h index 89217e29..6edd369c 100644 --- a/include/iptables.h +++ b/include/iptables.h @@ -9,11 +9,11 @@ /* Your shared library should call one of these. */ extern int do_command4(int argc, char *argv[], char **table, struct iptc_handle **handle); -extern int delete_chain4(const ipt_chainlabel chain, int verbose, +extern int delete_chain4(const xt_chainlabel chain, int verbose, struct iptc_handle *handle); -extern int flush_entries4(const ipt_chainlabel chain, int verbose, +extern int flush_entries4(const xt_chainlabel chain, int verbose, struct iptc_handle *handle); -extern int for_each_chain4(int (*fn)(const ipt_chainlabel, int, struct iptc_handle *), +extern int for_each_chain4(int (*fn)(const xt_chainlabel, int, struct iptc_handle *), int verbose, int builtinstoo, struct iptc_handle *handle); extern void print_rule4(const struct ipt_entry *e, struct iptc_handle *handle, const char *chain, int counters); diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index 55e0bfc9..6332073f 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -59,89 +59,89 @@ const char *ip6tc_get_policy(const char *chain, /* Rule numbers start at 1 for the first rule. */ /* Insert the entry `fw' in chain `chain' into position `rulenum'. */ -int ip6tc_insert_entry(const ip6t_chainlabel chain, +int ip6tc_insert_entry(const xt_chainlabel chain, const struct ip6t_entry *e, unsigned int rulenum, struct ip6tc_handle *handle); /* Atomically replace rule `rulenum' in `chain' with `fw'. */ -int ip6tc_replace_entry(const ip6t_chainlabel chain, +int ip6tc_replace_entry(const xt_chainlabel chain, const struct ip6t_entry *e, unsigned int rulenum, struct ip6tc_handle *handle); /* Append entry `fw' to chain `chain'. Equivalent to insert with rulenum = length of chain. */ -int ip6tc_append_entry(const ip6t_chainlabel chain, +int ip6tc_append_entry(const xt_chainlabel chain, const struct ip6t_entry *e, struct ip6tc_handle *handle); /* Check whether a matching rule exists */ -int ip6tc_check_entry(const ip6t_chainlabel chain, +int ip6tc_check_entry(const xt_chainlabel chain, const struct ip6t_entry *origfw, unsigned char *matchmask, struct ip6tc_handle *handle); /* Delete the first rule in `chain' which matches `fw'. */ -int ip6tc_delete_entry(const ip6t_chainlabel chain, +int ip6tc_delete_entry(const xt_chainlabel chain, const struct ip6t_entry *origfw, unsigned char *matchmask, struct ip6tc_handle *handle); /* Delete the rule in position `rulenum' in `chain'. */ -int ip6tc_delete_num_entry(const ip6t_chainlabel chain, +int ip6tc_delete_num_entry(const xt_chainlabel chain, unsigned int rulenum, struct ip6tc_handle *handle); /* Check the packet `fw' on chain `chain'. Returns the verdict, or NULL and sets errno. */ -const char *ip6tc_check_packet(const ip6t_chainlabel chain, +const char *ip6tc_check_packet(const xt_chainlabel chain, struct ip6t_entry *, struct ip6tc_handle *handle); /* Flushes the entries in the given chain (ie. empties chain). */ -int ip6tc_flush_entries(const ip6t_chainlabel chain, +int ip6tc_flush_entries(const xt_chainlabel chain, struct ip6tc_handle *handle); /* Zeroes the counters in a chain. */ -int ip6tc_zero_entries(const ip6t_chainlabel chain, +int ip6tc_zero_entries(const xt_chainlabel chain, struct ip6tc_handle *handle); /* Creates a new chain. */ -int ip6tc_create_chain(const ip6t_chainlabel chain, +int ip6tc_create_chain(const xt_chainlabel chain, struct ip6tc_handle *handle); /* Deletes a chain. */ -int ip6tc_delete_chain(const ip6t_chainlabel chain, +int ip6tc_delete_chain(const xt_chainlabel chain, struct ip6tc_handle *handle); /* Renames a chain. */ -int ip6tc_rename_chain(const ip6t_chainlabel oldname, - const ip6t_chainlabel newname, +int ip6tc_rename_chain(const xt_chainlabel oldname, + const xt_chainlabel newname, struct ip6tc_handle *handle); /* Sets the policy on a built-in chain. */ -int ip6tc_set_policy(const ip6t_chainlabel chain, - const ip6t_chainlabel policy, +int ip6tc_set_policy(const xt_chainlabel chain, + const xt_chainlabel policy, struct ip6t_counters *counters, struct ip6tc_handle *handle); /* Get the number of references to this chain */ -int ip6tc_get_references(unsigned int *ref, const ip6t_chainlabel chain, +int ip6tc_get_references(unsigned int *ref, const xt_chainlabel chain, struct ip6tc_handle *handle); /* read packet and byte counters for a specific rule */ -struct ip6t_counters *ip6tc_read_counter(const ip6t_chainlabel chain, +struct ip6t_counters *ip6tc_read_counter(const xt_chainlabel chain, unsigned int rulenum, struct ip6tc_handle *handle); /* zero packet and byte counters for a specific rule */ -int ip6tc_zero_counter(const ip6t_chainlabel chain, +int ip6tc_zero_counter(const xt_chainlabel chain, unsigned int rulenum, struct ip6tc_handle *handle); /* set packet and byte counters for a specific rule */ -int ip6tc_set_counter(const ip6t_chainlabel chain, +int ip6tc_set_counter(const xt_chainlabel chain, unsigned int rulenum, struct ip6t_counters *counters, struct ip6tc_handle *handle); diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index ccbf6bff..ded4d974 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -63,91 +63,91 @@ const char *iptc_get_policy(const char *chain, /* Rule numbers start at 1 for the first rule. */ /* Insert the entry `e' in chain `chain' into position `rulenum'. */ -int iptc_insert_entry(const ipt_chainlabel chain, +int iptc_insert_entry(const xt_chainlabel chain, const struct ipt_entry *e, unsigned int rulenum, struct iptc_handle *handle); /* Atomically replace rule `rulenum' in `chain' with `e'. */ -int iptc_replace_entry(const ipt_chainlabel chain, +int iptc_replace_entry(const xt_chainlabel chain, const struct ipt_entry *e, unsigned int rulenum, struct iptc_handle *handle); /* Append entry `e' to chain `chain'. Equivalent to insert with rulenum = length of chain. */ -int iptc_append_entry(const ipt_chainlabel chain, +int iptc_append_entry(const xt_chainlabel chain, const struct ipt_entry *e, struct iptc_handle *handle); /* Check whether a mathching rule exists */ -int iptc_check_entry(const ipt_chainlabel chain, +int iptc_check_entry(const xt_chainlabel chain, const struct ipt_entry *origfw, unsigned char *matchmask, struct iptc_handle *handle); /* Delete the first rule in `chain' which matches `e', subject to matchmask (array of length == origfw) */ -int iptc_delete_entry(const ipt_chainlabel chain, +int iptc_delete_entry(const xt_chainlabel chain, const struct ipt_entry *origfw, unsigned char *matchmask, struct iptc_handle *handle); /* Delete the rule in position `rulenum' in `chain'. */ -int iptc_delete_num_entry(const ipt_chainlabel chain, +int iptc_delete_num_entry(const xt_chainlabel chain, unsigned int rulenum, struct iptc_handle *handle); /* Check the packet `e' on chain `chain'. Returns the verdict, or NULL and sets errno. */ -const char *iptc_check_packet(const ipt_chainlabel chain, +const char *iptc_check_packet(const xt_chainlabel chain, struct ipt_entry *entry, struct iptc_handle *handle); /* Flushes the entries in the given chain (ie. empties chain). */ -int iptc_flush_entries(const ipt_chainlabel chain, +int iptc_flush_entries(const xt_chainlabel chain, struct iptc_handle *handle); /* Zeroes the counters in a chain. */ -int iptc_zero_entries(const ipt_chainlabel chain, +int iptc_zero_entries(const xt_chainlabel chain, struct iptc_handle *handle); /* Creates a new chain. */ -int iptc_create_chain(const ipt_chainlabel chain, +int iptc_create_chain(const xt_chainlabel chain, struct iptc_handle *handle); /* Deletes a chain. */ -int iptc_delete_chain(const ipt_chainlabel chain, +int iptc_delete_chain(const xt_chainlabel chain, struct iptc_handle *handle); /* Renames a chain. */ -int iptc_rename_chain(const ipt_chainlabel oldname, - const ipt_chainlabel newname, +int iptc_rename_chain(const xt_chainlabel oldname, + const xt_chainlabel newname, struct iptc_handle *handle); /* Sets the policy on a built-in chain. */ -int iptc_set_policy(const ipt_chainlabel chain, - const ipt_chainlabel policy, +int iptc_set_policy(const xt_chainlabel chain, + const xt_chainlabel policy, struct ipt_counters *counters, struct iptc_handle *handle); /* Get the number of references to this chain */ int iptc_get_references(unsigned int *ref, - const ipt_chainlabel chain, + const xt_chainlabel chain, struct iptc_handle *handle); /* read packet and byte counters for a specific rule */ -struct ipt_counters *iptc_read_counter(const ipt_chainlabel chain, +struct ipt_counters *iptc_read_counter(const xt_chainlabel chain, unsigned int rulenum, struct iptc_handle *handle); /* zero packet and byte counters for a specific rule */ -int iptc_zero_counter(const ipt_chainlabel chain, +int iptc_zero_counter(const xt_chainlabel chain, unsigned int rulenum, struct iptc_handle *handle); /* set packet and byte counters for a specific rule */ -int iptc_set_counter(const ipt_chainlabel chain, +int iptc_set_counter(const xt_chainlabel chain, unsigned int rulenum, struct ipt_counters *counters, struct iptc_handle *handle); diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 04e5224f..c5d2a0bf 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -676,7 +676,7 @@ print_firewall_line(const struct ip6t_entry *fw, } static int -append_entry(const ip6t_chainlabel chain, +append_entry(const xt_chainlabel chain, struct ip6t_entry *fw, unsigned int nsaddrs, const struct in6_addr saddrs[], @@ -706,7 +706,7 @@ append_entry(const ip6t_chainlabel chain, } static int -replace_entry(const ip6t_chainlabel chain, +replace_entry(const xt_chainlabel chain, struct ip6t_entry *fw, unsigned int rulenum, const struct in6_addr *saddr, const struct in6_addr *smask, @@ -725,7 +725,7 @@ replace_entry(const ip6t_chainlabel chain, } static int -insert_entry(const ip6t_chainlabel chain, +insert_entry(const xt_chainlabel chain, struct ip6t_entry *fw, unsigned int rulenum, unsigned int nsaddrs, @@ -790,7 +790,7 @@ make_delete_mask(const struct xtables_rule_match *matches, } static int -delete_entry(const ip6t_chainlabel chain, +delete_entry(const xt_chainlabel chain, struct ip6t_entry *fw, unsigned int nsaddrs, const struct in6_addr saddrs[], @@ -825,7 +825,7 @@ delete_entry(const ip6t_chainlabel chain, } static int -check_entry(const ip6t_chainlabel chain, struct ip6t_entry *fw, +check_entry(const xt_chainlabel chain, struct ip6t_entry *fw, unsigned int nsaddrs, const struct in6_addr *saddrs, const struct in6_addr *smasks, unsigned int ndaddrs, const struct in6_addr *daddrs, const struct in6_addr *dmasks, @@ -855,7 +855,7 @@ check_entry(const ip6t_chainlabel chain, struct ip6t_entry *fw, } int -for_each_chain6(int (*fn)(const ip6t_chainlabel, int, struct ip6tc_handle *), +for_each_chain6(int (*fn)(const xt_chainlabel, int, struct ip6tc_handle *), int verbose, int builtinstoo, struct ip6tc_handle *handle) { int ret = 1; @@ -869,21 +869,21 @@ for_each_chain6(int (*fn)(const ip6t_chainlabel, int, struct ip6tc_handle *), chain = ip6tc_next_chain(handle); } - chains = xtables_malloc(sizeof(ip6t_chainlabel) * chaincount); + chains = xtables_malloc(sizeof(xt_chainlabel) * chaincount); i = 0; chain = ip6tc_first_chain(handle); while (chain) { - strcpy(chains + i*sizeof(ip6t_chainlabel), chain); + strcpy(chains + i*sizeof(xt_chainlabel), chain); i++; chain = ip6tc_next_chain(handle); } for (i = 0; i < chaincount; i++) { if (!builtinstoo - && ip6tc_builtin(chains + i*sizeof(ip6t_chainlabel), + && ip6tc_builtin(chains + i*sizeof(xt_chainlabel), handle) == 1) continue; - ret &= fn(chains + i*sizeof(ip6t_chainlabel), verbose, handle); + ret &= fn(chains + i*sizeof(xt_chainlabel), verbose, handle); } free(chains); @@ -891,7 +891,7 @@ for_each_chain6(int (*fn)(const ip6t_chainlabel, int, struct ip6tc_handle *), } int -flush_entries6(const ip6t_chainlabel chain, int verbose, +flush_entries6(const xt_chainlabel chain, int verbose, struct ip6tc_handle *handle) { if (!chain) @@ -903,7 +903,7 @@ flush_entries6(const ip6t_chainlabel chain, int verbose, } static int -zero_entries(const ip6t_chainlabel chain, int verbose, +zero_entries(const xt_chainlabel chain, int verbose, struct ip6tc_handle *handle) { if (!chain) @@ -915,7 +915,7 @@ zero_entries(const ip6t_chainlabel chain, int verbose, } int -delete_chain6(const ip6t_chainlabel chain, int verbose, +delete_chain6(const xt_chainlabel chain, int verbose, struct ip6tc_handle *handle) { if (!chain) @@ -927,7 +927,7 @@ delete_chain6(const ip6t_chainlabel chain, int verbose, } static int -list_entries(const ip6t_chainlabel chain, int rulenum, int verbose, int numeric, +list_entries(const xt_chainlabel chain, int rulenum, int verbose, int numeric, int expanded, int linenumbers, struct ip6tc_handle *handle) { int found = 0; @@ -1169,7 +1169,7 @@ void print_rule6(const struct ip6t_entry *e, } static int -list_rules(const ip6t_chainlabel chain, int rulenum, int counters, +list_rules(const xt_chainlabel chain, int rulenum, int counters, struct ip6tc_handle *handle) { const char *this = NULL; diff --git a/iptables/iptables.c b/iptables/iptables.c index 830ddbcb..f5f47fa1 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -678,7 +678,7 @@ print_firewall_line(const struct ipt_entry *fw, } static int -append_entry(const ipt_chainlabel chain, +append_entry(const xt_chainlabel chain, struct ipt_entry *fw, unsigned int nsaddrs, const struct in_addr saddrs[], @@ -708,7 +708,7 @@ append_entry(const ipt_chainlabel chain, } static int -replace_entry(const ipt_chainlabel chain, +replace_entry(const xt_chainlabel chain, struct ipt_entry *fw, unsigned int rulenum, const struct in_addr *saddr, const struct in_addr *smask, @@ -727,7 +727,7 @@ replace_entry(const ipt_chainlabel chain, } static int -insert_entry(const ipt_chainlabel chain, +insert_entry(const xt_chainlabel chain, struct ipt_entry *fw, unsigned int rulenum, unsigned int nsaddrs, @@ -792,7 +792,7 @@ make_delete_mask(const struct xtables_rule_match *matches, } static int -delete_entry(const ipt_chainlabel chain, +delete_entry(const xt_chainlabel chain, struct ipt_entry *fw, unsigned int nsaddrs, const struct in_addr saddrs[], @@ -827,7 +827,7 @@ delete_entry(const ipt_chainlabel chain, } static int -check_entry(const ipt_chainlabel chain, struct ipt_entry *fw, +check_entry(const xt_chainlabel chain, struct ipt_entry *fw, unsigned int nsaddrs, const struct in_addr *saddrs, const struct in_addr *smasks, unsigned int ndaddrs, const struct in_addr *daddrs, const struct in_addr *dmasks, @@ -857,7 +857,7 @@ check_entry(const ipt_chainlabel chain, struct ipt_entry *fw, } int -for_each_chain4(int (*fn)(const ipt_chainlabel, int, struct iptc_handle *), +for_each_chain4(int (*fn)(const xt_chainlabel, int, struct iptc_handle *), int verbose, int builtinstoo, struct iptc_handle *handle) { int ret = 1; @@ -871,21 +871,21 @@ for_each_chain4(int (*fn)(const ipt_chainlabel, int, struct iptc_handle *), chain = iptc_next_chain(handle); } - chains = xtables_malloc(sizeof(ipt_chainlabel) * chaincount); + chains = xtables_malloc(sizeof(xt_chainlabel) * chaincount); i = 0; chain = iptc_first_chain(handle); while (chain) { - strcpy(chains + i*sizeof(ipt_chainlabel), chain); + strcpy(chains + i*sizeof(xt_chainlabel), chain); i++; chain = iptc_next_chain(handle); } for (i = 0; i < chaincount; i++) { if (!builtinstoo - && iptc_builtin(chains + i*sizeof(ipt_chainlabel), + && iptc_builtin(chains + i*sizeof(xt_chainlabel), handle) == 1) continue; - ret &= fn(chains + i*sizeof(ipt_chainlabel), verbose, handle); + ret &= fn(chains + i*sizeof(xt_chainlabel), verbose, handle); } free(chains); @@ -893,7 +893,7 @@ for_each_chain4(int (*fn)(const ipt_chainlabel, int, struct iptc_handle *), } int -flush_entries4(const ipt_chainlabel chain, int verbose, +flush_entries4(const xt_chainlabel chain, int verbose, struct iptc_handle *handle) { if (!chain) @@ -905,7 +905,7 @@ flush_entries4(const ipt_chainlabel chain, int verbose, } static int -zero_entries(const ipt_chainlabel chain, int verbose, +zero_entries(const xt_chainlabel chain, int verbose, struct iptc_handle *handle) { if (!chain) @@ -917,7 +917,7 @@ zero_entries(const ipt_chainlabel chain, int verbose, } int -delete_chain4(const ipt_chainlabel chain, int verbose, +delete_chain4(const xt_chainlabel chain, int verbose, struct iptc_handle *handle) { if (!chain) @@ -929,7 +929,7 @@ delete_chain4(const ipt_chainlabel chain, int verbose, } static int -list_entries(const ipt_chainlabel chain, int rulenum, int verbose, int numeric, +list_entries(const xt_chainlabel chain, int rulenum, int verbose, int numeric, int expanded, int linenumbers, struct iptc_handle *handle) { int found = 0; @@ -1177,7 +1177,7 @@ void print_rule4(const struct ipt_entry *e, } static int -list_rules(const ipt_chainlabel chain, int rulenum, int counters, +list_rules(const xt_chainlabel chain, int rulenum, int counters, struct iptc_handle *handle) { const char *this = NULL; diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c index 3b0c15af..b9e50c5e 100644 --- a/libiptc/libip4tc.c +++ b/libiptc/libip4tc.c @@ -59,7 +59,7 @@ typedef unsigned int socklen_t; #define ERROR_TARGET IPT_ERROR_TARGET #define NUMHOOKS NF_IP_NUMHOOKS -#define IPT_CHAINLABEL ipt_chainlabel +#define IPT_CHAINLABEL xt_chainlabel #define TC_DUMP_ENTRIES dump_entries #define TC_IS_CHAIN iptc_is_chain diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index 0f8a889d..93366e2d 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -57,7 +57,7 @@ typedef unsigned int socklen_t; #define ERROR_TARGET IP6T_ERROR_TARGET #define NUMHOOKS NF_IP6_NUMHOOKS -#define IPT_CHAINLABEL ip6t_chainlabel +#define IPT_CHAINLABEL xt_chainlabel #define TC_DUMP_ENTRIES dump_entries6 #define TC_IS_CHAIN ip6tc_is_chain -- cgit v1.2.3 From 1639fe86579f86f5f6a954a9b0adde2e16ad1980 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 11:39:52 +0200 Subject: libiptc: combine common types: _handle No real API/ABI change incurred, since the definition of the structs' types is not visible anyhow. Signed-off-by: Jan Engelhardt --- include/ip6tables.h | 10 +++---- include/iptables.h | 12 ++++---- include/libiptc/libip6tc.h | 61 ++++++++++++++++++++--------------------- include/libiptc/libiptc.h | 61 ++++++++++++++++++++--------------------- include/libiptc/xtcshared.h | 1 + iptables/ip6tables-restore.c | 6 ++-- iptables/ip6tables-save.c | 2 +- iptables/ip6tables-standalone.c | 2 +- iptables/ip6tables.c | 34 +++++++++++------------ iptables/iptables-restore.c | 6 ++-- iptables/iptables-save.c | 2 +- iptables/iptables-standalone.c | 2 +- iptables/iptables.c | 34 +++++++++++------------ libiptc/libip4tc.c | 9 ++---- libiptc/libip6tc.c | 5 +--- libiptc/libiptc.c | 5 ++-- 16 files changed, 122 insertions(+), 130 deletions(-) diff --git a/include/ip6tables.h b/include/ip6tables.h index 1def3938..37d2e0a3 100644 --- a/include/ip6tables.h +++ b/include/ip6tables.h @@ -8,12 +8,12 @@ /* Your shared library should call one of these. */ extern int do_command6(int argc, char *argv[], char **table, - struct ip6tc_handle **handle); + struct xtc_handle **handle); -extern int for_each_chain6(int (*fn)(const xt_chainlabel, int, struct ip6tc_handle *), int verbose, int builtinstoo, struct ip6tc_handle *handle); -extern int flush_entries6(const xt_chainlabel chain, int verbose, struct ip6tc_handle *handle); -extern int delete_chain6(const xt_chainlabel chain, int verbose, struct ip6tc_handle *handle); -void print_rule6(const struct ip6t_entry *e, struct ip6tc_handle *h, const char *chain, int counters); +extern int for_each_chain6(int (*fn)(const xt_chainlabel, int, struct xtc_handle *), int verbose, int builtinstoo, struct xtc_handle *handle); +extern int flush_entries6(const xt_chainlabel chain, int verbose, struct xtc_handle *handle); +extern int delete_chain6(const xt_chainlabel chain, int verbose, struct xtc_handle *handle); +void print_rule6(const struct ip6t_entry *e, struct xtc_handle *h, const char *chain, int counters); extern struct xtables_globals ip6tables_globals; diff --git a/include/iptables.h b/include/iptables.h index 6edd369c..c42613c9 100644 --- a/include/iptables.h +++ b/include/iptables.h @@ -8,15 +8,15 @@ /* Your shared library should call one of these. */ extern int do_command4(int argc, char *argv[], char **table, - struct iptc_handle **handle); + struct xtc_handle **handle); extern int delete_chain4(const xt_chainlabel chain, int verbose, - struct iptc_handle *handle); + struct xtc_handle *handle); extern int flush_entries4(const xt_chainlabel chain, int verbose, - struct iptc_handle *handle); -extern int for_each_chain4(int (*fn)(const xt_chainlabel, int, struct iptc_handle *), - int verbose, int builtinstoo, struct iptc_handle *handle); + struct xtc_handle *handle); +extern int for_each_chain4(int (*fn)(const xt_chainlabel, int, struct xtc_handle *), + int verbose, int builtinstoo, struct xtc_handle *handle); extern void print_rule4(const struct ipt_entry *e, - struct iptc_handle *handle, const char *chain, int counters); + struct xtc_handle *handle, const char *chain, int counters); extern struct xtables_globals iptables_globals; diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index 6332073f..f85dda71 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -12,8 +12,7 @@ #include #include -struct ip6tc_handle; - +#define ip6tc_handle xtc_handle #define ip6t_chainlabel xt_chainlabel #define IP6TC_LABEL_ACCEPT "ACCEPT" @@ -22,37 +21,37 @@ struct ip6tc_handle; #define IP6TC_LABEL_RETURN "RETURN" /* Does this chain exist? */ -int ip6tc_is_chain(const char *chain, struct ip6tc_handle *const handle); +int ip6tc_is_chain(const char *chain, struct xtc_handle *const handle); /* Take a snapshot of the rules. Returns NULL on error. */ -struct ip6tc_handle *ip6tc_init(const char *tablename); +struct xtc_handle *ip6tc_init(const char *tablename); /* Cleanup after ip6tc_init(). */ -void ip6tc_free(struct ip6tc_handle *h); +void ip6tc_free(struct xtc_handle *h); /* Iterator functions to run through the chains. Returns NULL at end. */ -const char *ip6tc_first_chain(struct ip6tc_handle *handle); -const char *ip6tc_next_chain(struct ip6tc_handle *handle); +const char *ip6tc_first_chain(struct xtc_handle *handle); +const char *ip6tc_next_chain(struct xtc_handle *handle); /* Get first rule in the given chain: NULL for empty chain. */ const struct ip6t_entry *ip6tc_first_rule(const char *chain, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Returns NULL when rules run out. */ const struct ip6t_entry *ip6tc_next_rule(const struct ip6t_entry *prev, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Returns a pointer to the target name of this position. */ const char *ip6tc_get_target(const struct ip6t_entry *e, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Is this a built-in chain? */ -int ip6tc_builtin(const char *chain, struct ip6tc_handle *const handle); +int ip6tc_builtin(const char *chain, struct xtc_handle *const handle); /* Get the policy of a given built-in chain */ const char *ip6tc_get_policy(const char *chain, struct ip6t_counters *counters, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* These functions return TRUE for OK or 0 and set errno. If errno == 0, it means there was a version error (ie. upgrade libiptc). */ @@ -62,92 +61,92 @@ const char *ip6tc_get_policy(const char *chain, int ip6tc_insert_entry(const xt_chainlabel chain, const struct ip6t_entry *e, unsigned int rulenum, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Atomically replace rule `rulenum' in `chain' with `fw'. */ int ip6tc_replace_entry(const xt_chainlabel chain, const struct ip6t_entry *e, unsigned int rulenum, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Append entry `fw' to chain `chain'. Equivalent to insert with rulenum = length of chain. */ int ip6tc_append_entry(const xt_chainlabel chain, const struct ip6t_entry *e, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Check whether a matching rule exists */ int ip6tc_check_entry(const xt_chainlabel chain, const struct ip6t_entry *origfw, unsigned char *matchmask, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Delete the first rule in `chain' which matches `fw'. */ int ip6tc_delete_entry(const xt_chainlabel chain, const struct ip6t_entry *origfw, unsigned char *matchmask, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Delete the rule in position `rulenum' in `chain'. */ int ip6tc_delete_num_entry(const xt_chainlabel chain, unsigned int rulenum, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Check the packet `fw' on chain `chain'. Returns the verdict, or NULL and sets errno. */ const char *ip6tc_check_packet(const xt_chainlabel chain, struct ip6t_entry *, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Flushes the entries in the given chain (ie. empties chain). */ int ip6tc_flush_entries(const xt_chainlabel chain, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Zeroes the counters in a chain. */ int ip6tc_zero_entries(const xt_chainlabel chain, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Creates a new chain. */ int ip6tc_create_chain(const xt_chainlabel chain, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Deletes a chain. */ int ip6tc_delete_chain(const xt_chainlabel chain, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Renames a chain. */ int ip6tc_rename_chain(const xt_chainlabel oldname, const xt_chainlabel newname, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Sets the policy on a built-in chain. */ int ip6tc_set_policy(const xt_chainlabel chain, const xt_chainlabel policy, struct ip6t_counters *counters, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Get the number of references to this chain */ int ip6tc_get_references(unsigned int *ref, const xt_chainlabel chain, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* read packet and byte counters for a specific rule */ struct ip6t_counters *ip6tc_read_counter(const xt_chainlabel chain, unsigned int rulenum, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* zero packet and byte counters for a specific rule */ int ip6tc_zero_counter(const xt_chainlabel chain, unsigned int rulenum, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* set packet and byte counters for a specific rule */ int ip6tc_set_counter(const xt_chainlabel chain, unsigned int rulenum, struct ip6t_counters *counters, - struct ip6tc_handle *handle); + struct xtc_handle *handle); /* Makes the actual changes. */ -int ip6tc_commit(struct ip6tc_handle *handle); +int ip6tc_commit(struct xtc_handle *handle); /* Get raw socket. */ int ip6tc_get_raw_socket(void); @@ -158,6 +157,6 @@ const char *ip6tc_strerror(int err); /* Return prefix length, or -1 if not contiguous */ int ipv6_prefix_length(const struct in6_addr *a); -extern void dump_entries6(struct ip6tc_handle *const); +extern void dump_entries6(struct xtc_handle *const); #endif /* _LIBIP6TC_H */ diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index ded4d974..cf91725b 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -16,8 +16,7 @@ extern "C" { #endif -struct iptc_handle; - +#define iptc_handle xtc_handle #define ipt_chainlabel xt_chainlabel #define IPTC_LABEL_ACCEPT "ACCEPT" @@ -26,37 +25,37 @@ struct iptc_handle; #define IPTC_LABEL_RETURN "RETURN" /* Does this chain exist? */ -int iptc_is_chain(const char *chain, struct iptc_handle *const handle); +int iptc_is_chain(const char *chain, struct xtc_handle *const handle); /* Take a snapshot of the rules. Returns NULL on error. */ -struct iptc_handle *iptc_init(const char *tablename); +struct xtc_handle *iptc_init(const char *tablename); /* Cleanup after iptc_init(). */ -void iptc_free(struct iptc_handle *h); +void iptc_free(struct xtc_handle *h); /* Iterator functions to run through the chains. Returns NULL at end. */ -const char *iptc_first_chain(struct iptc_handle *handle); -const char *iptc_next_chain(struct iptc_handle *handle); +const char *iptc_first_chain(struct xtc_handle *handle); +const char *iptc_next_chain(struct xtc_handle *handle); /* Get first rule in the given chain: NULL for empty chain. */ const struct ipt_entry *iptc_first_rule(const char *chain, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Returns NULL when rules run out. */ const struct ipt_entry *iptc_next_rule(const struct ipt_entry *prev, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Returns a pointer to the target name of this entry. */ const char *iptc_get_target(const struct ipt_entry *e, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Is this a built-in chain? */ -int iptc_builtin(const char *chain, struct iptc_handle *const handle); +int iptc_builtin(const char *chain, struct xtc_handle *const handle); /* Get the policy of a given built-in chain */ const char *iptc_get_policy(const char *chain, struct ipt_counters *counter, - struct iptc_handle *handle); + struct xtc_handle *handle); /* These functions return TRUE for OK or 0 and set errno. If errno == 0, it means there was a version error (ie. upgrade libiptc). */ @@ -66,94 +65,94 @@ const char *iptc_get_policy(const char *chain, int iptc_insert_entry(const xt_chainlabel chain, const struct ipt_entry *e, unsigned int rulenum, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Atomically replace rule `rulenum' in `chain' with `e'. */ int iptc_replace_entry(const xt_chainlabel chain, const struct ipt_entry *e, unsigned int rulenum, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Append entry `e' to chain `chain'. Equivalent to insert with rulenum = length of chain. */ int iptc_append_entry(const xt_chainlabel chain, const struct ipt_entry *e, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Check whether a mathching rule exists */ int iptc_check_entry(const xt_chainlabel chain, const struct ipt_entry *origfw, unsigned char *matchmask, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Delete the first rule in `chain' which matches `e', subject to matchmask (array of length == origfw) */ int iptc_delete_entry(const xt_chainlabel chain, const struct ipt_entry *origfw, unsigned char *matchmask, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Delete the rule in position `rulenum' in `chain'. */ int iptc_delete_num_entry(const xt_chainlabel chain, unsigned int rulenum, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Check the packet `e' on chain `chain'. Returns the verdict, or NULL and sets errno. */ const char *iptc_check_packet(const xt_chainlabel chain, struct ipt_entry *entry, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Flushes the entries in the given chain (ie. empties chain). */ int iptc_flush_entries(const xt_chainlabel chain, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Zeroes the counters in a chain. */ int iptc_zero_entries(const xt_chainlabel chain, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Creates a new chain. */ int iptc_create_chain(const xt_chainlabel chain, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Deletes a chain. */ int iptc_delete_chain(const xt_chainlabel chain, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Renames a chain. */ int iptc_rename_chain(const xt_chainlabel oldname, const xt_chainlabel newname, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Sets the policy on a built-in chain. */ int iptc_set_policy(const xt_chainlabel chain, const xt_chainlabel policy, struct ipt_counters *counters, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Get the number of references to this chain */ int iptc_get_references(unsigned int *ref, const xt_chainlabel chain, - struct iptc_handle *handle); + struct xtc_handle *handle); /* read packet and byte counters for a specific rule */ struct ipt_counters *iptc_read_counter(const xt_chainlabel chain, unsigned int rulenum, - struct iptc_handle *handle); + struct xtc_handle *handle); /* zero packet and byte counters for a specific rule */ int iptc_zero_counter(const xt_chainlabel chain, unsigned int rulenum, - struct iptc_handle *handle); + struct xtc_handle *handle); /* set packet and byte counters for a specific rule */ int iptc_set_counter(const xt_chainlabel chain, unsigned int rulenum, struct ipt_counters *counters, - struct iptc_handle *handle); + struct xtc_handle *handle); /* Makes the actual changes. */ -int iptc_commit(struct iptc_handle *handle); +int iptc_commit(struct xtc_handle *handle); /* Get raw socket. */ int iptc_get_raw_socket(void); @@ -161,7 +160,7 @@ int iptc_get_raw_socket(void); /* Translates errno numbers into more human-readable form than strerror. */ const char *iptc_strerror(int err); -extern void dump_entries(struct iptc_handle *const); +extern void dump_entries(struct xtc_handle *const); #ifdef __cplusplus } diff --git a/include/libiptc/xtcshared.h b/include/libiptc/xtcshared.h index aaf87a4b..89a51511 100644 --- a/include/libiptc/xtcshared.h +++ b/include/libiptc/xtcshared.h @@ -2,5 +2,6 @@ #define _LIBXTC_SHARED_H 1 typedef char xt_chainlabel[32]; +struct xtc_handle; #endif /* _LIBXTC_SHARED_H */ diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 1487504b..c5afe315 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -56,9 +56,9 @@ static void print_usage(const char *name, const char *version) exit(1); } -static struct ip6tc_handle *create_handle(const char *tablename) +static struct xtc_handle *create_handle(const char *tablename) { - struct ip6tc_handle *handle; + struct xtc_handle *handle; handle = ip6tc_init(tablename); @@ -116,7 +116,7 @@ static void free_argv(void) { int ip6tables_restore_main(int argc, char *argv[]) { - struct ip6tc_handle *handle = NULL; + struct xtc_handle *handle = NULL; char buffer[10240]; int c; char curtable[IP6T_TABLE_MAXNAMELEN + 1]; diff --git a/iptables/ip6tables-save.c b/iptables/ip6tables-save.c index 38b0c2f2..fbfce788 100644 --- a/iptables/ip6tables-save.c +++ b/iptables/ip6tables-save.c @@ -60,7 +60,7 @@ static int for_each_table(int (*func)(const char *tablename)) static int do_output(const char *tablename) { - struct ip6tc_handle *h; + struct xtc_handle *h; const char *chain = NULL; if (!tablename) diff --git a/iptables/ip6tables-standalone.c b/iptables/ip6tables-standalone.c index 6b829353..21b58116 100644 --- a/iptables/ip6tables-standalone.c +++ b/iptables/ip6tables-standalone.c @@ -42,7 +42,7 @@ ip6tables_main(int argc, char *argv[]) { int ret; char *table = "filter"; - struct ip6tc_handle *handle = NULL; + struct xtc_handle *handle = NULL; ip6tables_globals.program_name = "ip6tables"; ret = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6); diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index c5d2a0bf..7b12205b 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -469,7 +469,7 @@ print_num(uint64_t number, unsigned int format) static void -print_header(unsigned int format, const char *chain, struct ip6tc_handle *handle) +print_header(unsigned int format, const char *chain, struct xtc_handle *handle) { struct ip6t_counters counters; const char *pol = ip6tc_get_policy(chain, &counters, handle); @@ -545,7 +545,7 @@ print_firewall(const struct ip6t_entry *fw, const char *targname, unsigned int num, unsigned int format, - struct ip6tc_handle *const handle) + struct xtc_handle *const handle) { const struct xtables_target *target = NULL; const struct ip6t_entry_target *t; @@ -667,7 +667,7 @@ print_firewall(const struct ip6t_entry *fw, static void print_firewall_line(const struct ip6t_entry *fw, - struct ip6tc_handle *const h) + struct xtc_handle *const h) { struct ip6t_entry_target *t; @@ -685,7 +685,7 @@ append_entry(const xt_chainlabel chain, const struct in6_addr daddrs[], const struct in6_addr dmasks[], int verbose, - struct ip6tc_handle *handle) + struct xtc_handle *handle) { unsigned int i, j; int ret = 1; @@ -712,7 +712,7 @@ replace_entry(const xt_chainlabel chain, const struct in6_addr *saddr, const struct in6_addr *smask, const struct in6_addr *daddr, const struct in6_addr *dmask, int verbose, - struct ip6tc_handle *handle) + struct xtc_handle *handle) { fw->ipv6.src = *saddr; fw->ipv6.dst = *daddr; @@ -735,7 +735,7 @@ insert_entry(const xt_chainlabel chain, const struct in6_addr daddrs[], const struct in6_addr dmasks[], int verbose, - struct ip6tc_handle *handle) + struct xtc_handle *handle) { unsigned int i, j; int ret = 1; @@ -799,7 +799,7 @@ delete_entry(const xt_chainlabel chain, const struct in6_addr daddrs[], const struct in6_addr dmasks[], int verbose, - struct ip6tc_handle *handle, + struct xtc_handle *handle, struct xtables_rule_match *matches, const struct xtables_target *target) { @@ -829,7 +829,7 @@ check_entry(const xt_chainlabel chain, struct ip6t_entry *fw, unsigned int nsaddrs, const struct in6_addr *saddrs, const struct in6_addr *smasks, unsigned int ndaddrs, const struct in6_addr *daddrs, const struct in6_addr *dmasks, - bool verbose, struct ip6tc_handle *handle, + bool verbose, struct xtc_handle *handle, struct xtables_rule_match *matches, const struct xtables_target *target) { @@ -855,8 +855,8 @@ check_entry(const xt_chainlabel chain, struct ip6t_entry *fw, } int -for_each_chain6(int (*fn)(const xt_chainlabel, int, struct ip6tc_handle *), - int verbose, int builtinstoo, struct ip6tc_handle *handle) +for_each_chain6(int (*fn)(const xt_chainlabel, int, struct xtc_handle *), + int verbose, int builtinstoo, struct xtc_handle *handle) { int ret = 1; const char *chain; @@ -892,7 +892,7 @@ for_each_chain6(int (*fn)(const xt_chainlabel, int, struct ip6tc_handle *), int flush_entries6(const xt_chainlabel chain, int verbose, - struct ip6tc_handle *handle) + struct xtc_handle *handle) { if (!chain) return for_each_chain6(flush_entries6, verbose, 1, handle); @@ -904,7 +904,7 @@ flush_entries6(const xt_chainlabel chain, int verbose, static int zero_entries(const xt_chainlabel chain, int verbose, - struct ip6tc_handle *handle) + struct xtc_handle *handle) { if (!chain) return for_each_chain6(zero_entries, verbose, 1, handle); @@ -916,7 +916,7 @@ zero_entries(const xt_chainlabel chain, int verbose, int delete_chain6(const xt_chainlabel chain, int verbose, - struct ip6tc_handle *handle) + struct xtc_handle *handle) { if (!chain) return for_each_chain6(delete_chain6, verbose, 0, handle); @@ -928,7 +928,7 @@ delete_chain6(const xt_chainlabel chain, int verbose, static int list_entries(const xt_chainlabel chain, int rulenum, int verbose, int numeric, - int expanded, int linenumbers, struct ip6tc_handle *handle) + int expanded, int linenumbers, struct xtc_handle *handle) { int found = 0; unsigned int format; @@ -1080,7 +1080,7 @@ static void print_ip(const char *prefix, const struct in6_addr *ip, /* We want this to be readable, so only print out neccessary fields. * Because that's the kind of world I want to live in. */ void print_rule6(const struct ip6t_entry *e, - struct ip6tc_handle *h, const char *chain, int counters) + struct xtc_handle *h, const char *chain, int counters) { const struct ip6t_entry_target *t; const char *target_name; @@ -1170,7 +1170,7 @@ void print_rule6(const struct ip6t_entry *e, static int list_rules(const xt_chainlabel chain, int rulenum, int counters, - struct ip6tc_handle *handle) + struct xtc_handle *handle) { const char *this = NULL; int found = 0; @@ -1328,7 +1328,7 @@ static void command_match(struct iptables_command_state *cs) m->extra_opts, &m->option_offset); } -int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **handle) +int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle) { struct iptables_command_state cs; struct ip6t_entry *e = NULL; diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index d0bd79a9..7152d750 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -56,9 +56,9 @@ static void print_usage(const char *name, const char *version) exit(1); } -static struct iptc_handle *create_handle(const char *tablename) +static struct xtc_handle *create_handle(const char *tablename) { - struct iptc_handle *handle; + struct xtc_handle *handle; handle = iptc_init(tablename); @@ -116,7 +116,7 @@ static void free_argv(void) { int iptables_restore_main(int argc, char *argv[]) { - struct iptc_handle *handle = NULL; + struct xtc_handle *handle = NULL; char buffer[10240]; int c; char curtable[IPT_TABLE_MAXNAMELEN + 1]; diff --git a/iptables/iptables-save.c b/iptables/iptables-save.c index a25a186e..ff42f884 100644 --- a/iptables/iptables-save.c +++ b/iptables/iptables-save.c @@ -58,7 +58,7 @@ static int for_each_table(int (*func)(const char *tablename)) static int do_output(const char *tablename) { - struct iptc_handle *h; + struct xtc_handle *h; const char *chain = NULL; if (!tablename) diff --git a/iptables/iptables-standalone.c b/iptables/iptables-standalone.c index 1ebec33d..683a44a5 100644 --- a/iptables/iptables-standalone.c +++ b/iptables/iptables-standalone.c @@ -43,7 +43,7 @@ iptables_main(int argc, char *argv[]) { int ret; char *table = "filter"; - struct iptc_handle *handle = NULL; + struct xtc_handle *handle = NULL; iptables_globals.program_name = "iptables"; ret = xtables_init_all(&iptables_globals, NFPROTO_IPV4); diff --git a/iptables/iptables.c b/iptables/iptables.c index f5f47fa1..d4a7ca11 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -471,7 +471,7 @@ print_num(uint64_t number, unsigned int format) static void -print_header(unsigned int format, const char *chain, struct iptc_handle *handle) +print_header(unsigned int format, const char *chain, struct xtc_handle *handle) { struct ipt_counters counters; const char *pol = iptc_get_policy(chain, &counters, handle); @@ -547,7 +547,7 @@ print_firewall(const struct ipt_entry *fw, const char *targname, unsigned int num, unsigned int format, - struct iptc_handle *const handle) + struct xtc_handle *const handle) { const struct xtables_target *target = NULL; const struct ipt_entry_target *t; @@ -669,7 +669,7 @@ print_firewall(const struct ipt_entry *fw, static void print_firewall_line(const struct ipt_entry *fw, - struct iptc_handle *const h) + struct xtc_handle *const h) { struct ipt_entry_target *t; @@ -687,7 +687,7 @@ append_entry(const xt_chainlabel chain, const struct in_addr daddrs[], const struct in_addr dmasks[], int verbose, - struct iptc_handle *handle) + struct xtc_handle *handle) { unsigned int i, j; int ret = 1; @@ -714,7 +714,7 @@ replace_entry(const xt_chainlabel chain, const struct in_addr *saddr, const struct in_addr *smask, const struct in_addr *daddr, const struct in_addr *dmask, int verbose, - struct iptc_handle *handle) + struct xtc_handle *handle) { fw->ip.src.s_addr = saddr->s_addr; fw->ip.dst.s_addr = daddr->s_addr; @@ -737,7 +737,7 @@ insert_entry(const xt_chainlabel chain, const struct in_addr daddrs[], const struct in_addr dmasks[], int verbose, - struct iptc_handle *handle) + struct xtc_handle *handle) { unsigned int i, j; int ret = 1; @@ -801,7 +801,7 @@ delete_entry(const xt_chainlabel chain, const struct in_addr daddrs[], const struct in_addr dmasks[], int verbose, - struct iptc_handle *handle, + struct xtc_handle *handle, struct xtables_rule_match *matches, const struct xtables_target *target) { @@ -831,7 +831,7 @@ check_entry(const xt_chainlabel chain, struct ipt_entry *fw, unsigned int nsaddrs, const struct in_addr *saddrs, const struct in_addr *smasks, unsigned int ndaddrs, const struct in_addr *daddrs, const struct in_addr *dmasks, - bool verbose, struct iptc_handle *handle, + bool verbose, struct xtc_handle *handle, struct xtables_rule_match *matches, const struct xtables_target *target) { @@ -857,8 +857,8 @@ check_entry(const xt_chainlabel chain, struct ipt_entry *fw, } int -for_each_chain4(int (*fn)(const xt_chainlabel, int, struct iptc_handle *), - int verbose, int builtinstoo, struct iptc_handle *handle) +for_each_chain4(int (*fn)(const xt_chainlabel, int, struct xtc_handle *), + int verbose, int builtinstoo, struct xtc_handle *handle) { int ret = 1; const char *chain; @@ -894,7 +894,7 @@ for_each_chain4(int (*fn)(const xt_chainlabel, int, struct iptc_handle *), int flush_entries4(const xt_chainlabel chain, int verbose, - struct iptc_handle *handle) + struct xtc_handle *handle) { if (!chain) return for_each_chain4(flush_entries4, verbose, 1, handle); @@ -906,7 +906,7 @@ flush_entries4(const xt_chainlabel chain, int verbose, static int zero_entries(const xt_chainlabel chain, int verbose, - struct iptc_handle *handle) + struct xtc_handle *handle) { if (!chain) return for_each_chain4(zero_entries, verbose, 1, handle); @@ -918,7 +918,7 @@ zero_entries(const xt_chainlabel chain, int verbose, int delete_chain4(const xt_chainlabel chain, int verbose, - struct iptc_handle *handle) + struct xtc_handle *handle) { if (!chain) return for_each_chain4(delete_chain4, verbose, 0, handle); @@ -930,7 +930,7 @@ delete_chain4(const xt_chainlabel chain, int verbose, static int list_entries(const xt_chainlabel chain, int rulenum, int verbose, int numeric, - int expanded, int linenumbers, struct iptc_handle *handle) + int expanded, int linenumbers, struct xtc_handle *handle) { int found = 0; unsigned int format; @@ -1097,7 +1097,7 @@ static void print_ip(const char *prefix, uint32_t ip, /* We want this to be readable, so only print out neccessary fields. * Because that's the kind of world I want to live in. */ void print_rule4(const struct ipt_entry *e, - struct iptc_handle *h, const char *chain, int counters) + struct xtc_handle *h, const char *chain, int counters) { const struct ipt_entry_target *t; const char *target_name; @@ -1178,7 +1178,7 @@ void print_rule4(const struct ipt_entry *e, static int list_rules(const xt_chainlabel chain, int rulenum, int counters, - struct iptc_handle *handle) + struct xtc_handle *handle) { const char *this = NULL; int found = 0; @@ -1340,7 +1340,7 @@ static void command_match(struct iptables_command_state *cs) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); } -int do_command4(int argc, char *argv[], char **table, struct iptc_handle **handle) +int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle) { struct iptables_command_state cs; struct ipt_entry *e = NULL; diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c index b9e50c5e..cf292381 100644 --- a/libiptc/libip4tc.c +++ b/libiptc/libip4tc.c @@ -47,9 +47,6 @@ typedef unsigned int socklen_t; #define STRUCT_STANDARD_TARGET struct ipt_standard_target #define STRUCT_REPLACE struct ipt_replace -#define STRUCT_TC_HANDLE struct iptc_handle -#define xtc_handle iptc_handle - #define ENTRY_ITERATE IPT_ENTRY_ITERATE #define TABLE_MAXNAMELEN IPT_TABLE_MAXNAMELEN #define FUNCTION_MAXNAMELEN IPT_FUNCTION_MAXNAMELEN @@ -123,7 +120,7 @@ typedef unsigned int socklen_t; #define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n)) static int -dump_entry(struct ipt_entry *e, struct iptc_handle *const handle) +dump_entry(struct ipt_entry *e, struct xtc_handle *const handle) { size_t i; STRUCT_ENTRY_TARGET *t; @@ -238,7 +235,7 @@ check_match(const STRUCT_ENTRY_MATCH *m, unsigned int *off) static inline int check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off, unsigned int user_offset, int *was_return, - struct iptc_handle *h) + struct xtc_handle *h) { unsigned int toff; STRUCT_STANDARD_TARGET *t; @@ -314,7 +311,7 @@ check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off, #ifdef IPTC_DEBUG /* Do every conceivable sanity check on the handle */ static void -do_check(struct iptc_handle *h, unsigned int line) +do_check(struct xtc_handle *h, unsigned int line) { unsigned int i, n; unsigned int user_offset; /* Offset of first user chain */ diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index 93366e2d..636466f1 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -45,9 +45,6 @@ typedef unsigned int socklen_t; #define STRUCT_STANDARD_TARGET struct ip6t_standard_target #define STRUCT_REPLACE struct ip6t_replace -#define STRUCT_TC_HANDLE struct ip6tc_handle -#define xtc_handle ip6tc_handle - #define ENTRY_ITERATE IP6T_ENTRY_ITERATE #define TABLE_MAXNAMELEN IP6T_TABLE_MAXNAMELEN #define FUNCTION_MAXNAMELEN IP6T_FUNCTION_MAXNAMELEN @@ -131,7 +128,7 @@ ipv6_prefix_length(const struct in6_addr *a) } static int -dump_entry(struct ip6t_entry *e, struct ip6tc_handle *const handle) +dump_entry(struct ip6t_entry *e, struct xtc_handle *const handle) { size_t i; char buf[40]; diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 0a29a690..593c5de8 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -121,8 +121,7 @@ struct chain_head unsigned int foot_offset; /* offset in rule blob */ }; -STRUCT_TC_HANDLE -{ +struct xtc_handle { int sockfd; int changed; /* Have changes been made? */ @@ -1270,7 +1269,7 @@ alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) { struct xtc_handle *h; - h = malloc(sizeof(STRUCT_TC_HANDLE)); + h = malloc(sizeof(*h)); if (!h) { errno = ENOMEM; return NULL; -- cgit v1.2.3 From 14da56743c6cdf25da35b7b5ca7a5d201771990d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 09:56:16 +0200 Subject: src: resolve old macro names that are indirections Command used: git grep -f <(pcregrep -hior '(?<=#define\s)IP6?(T_\w+)(?=\s+X\1)' include/) and then fix all occurrences. Signed-off-by: Jan Engelhardt --- extensions/libipt_realm.c | 10 ++++----- include/libiptc/libip6tc.h | 8 +++---- include/libiptc/libiptc.h | 8 +++---- iptables/ip6tables-restore.c | 13 ++++++------ iptables/ip6tables-save.c | 4 ++-- iptables/ip6tables.c | 50 ++++++++++++++++++++++---------------------- iptables/iptables-restore.c | 13 ++++++------ iptables/iptables-save.c | 4 ++-- iptables/iptables-xml.c | 36 +++++++++++++++---------------- iptables/iptables.c | 48 +++++++++++++++++++++--------------------- iptables/xshared.c | 2 +- libiptc/libip4tc.c | 32 ++++++++++++++-------------- libiptc/libip6tc.c | 30 +++++++++++++------------- 13 files changed, 128 insertions(+), 130 deletions(-) diff --git a/extensions/libipt_realm.c b/extensions/libipt_realm.c index b60c57ee..a8d9dda0 100644 --- a/extensions/libipt_realm.c +++ b/extensions/libipt_realm.c @@ -41,7 +41,7 @@ static void realm_init(struct xt_entry_match *m) static void realm_parse(struct xt_option_call *cb) { - struct ipt_realm_info *realminfo = cb->data; + struct xt_realm_info *realminfo = cb->data; int id; char *end; @@ -87,7 +87,7 @@ print_realm(unsigned long id, unsigned long mask, int numeric) static void realm_print(const void *ip, const struct xt_entry_match *match, int numeric) { - const struct ipt_realm_info *ri = (const void *)match->data; + const struct xt_realm_info *ri = (const void *)match->data; if (ri->invert) printf(" !"); @@ -98,7 +98,7 @@ static void realm_print(const void *ip, const struct xt_entry_match *match, static void realm_save(const void *ip, const struct xt_entry_match *match) { - const struct ipt_realm_info *ri = (const void *)match->data; + const struct xt_realm_info *ri = (const void *)match->data; if (ri->invert) printf(" !"); @@ -111,8 +111,8 @@ static struct xtables_match realm_mt_reg = { .name = "realm", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_realm_info)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_realm_info)), + .size = XT_ALIGN(sizeof(struct xt_realm_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_realm_info)), .help = realm_help, .init = realm_init, .print = realm_print, diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index f85dda71..61c1e7f5 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -50,7 +50,7 @@ int ip6tc_builtin(const char *chain, struct xtc_handle *const handle); /* Get the policy of a given built-in chain */ const char *ip6tc_get_policy(const char *chain, - struct ip6t_counters *counters, + struct xt_counters *counters, struct xtc_handle *handle); /* These functions return TRUE for OK or 0 and set errno. If errno == @@ -122,7 +122,7 @@ int ip6tc_rename_chain(const xt_chainlabel oldname, /* Sets the policy on a built-in chain. */ int ip6tc_set_policy(const xt_chainlabel chain, const xt_chainlabel policy, - struct ip6t_counters *counters, + struct xt_counters *counters, struct xtc_handle *handle); /* Get the number of references to this chain */ @@ -130,7 +130,7 @@ int ip6tc_get_references(unsigned int *ref, const xt_chainlabel chain, struct xtc_handle *handle); /* read packet and byte counters for a specific rule */ -struct ip6t_counters *ip6tc_read_counter(const xt_chainlabel chain, +struct xt_counters *ip6tc_read_counter(const xt_chainlabel chain, unsigned int rulenum, struct xtc_handle *handle); @@ -142,7 +142,7 @@ int ip6tc_zero_counter(const xt_chainlabel chain, /* set packet and byte counters for a specific rule */ int ip6tc_set_counter(const xt_chainlabel chain, unsigned int rulenum, - struct ip6t_counters *counters, + struct xt_counters *counters, struct xtc_handle *handle); /* Makes the actual changes. */ diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index cf91725b..6f64f5a9 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -54,7 +54,7 @@ int iptc_builtin(const char *chain, struct xtc_handle *const handle); /* Get the policy of a given built-in chain */ const char *iptc_get_policy(const char *chain, - struct ipt_counters *counter, + struct xt_counters *counter, struct xtc_handle *handle); /* These functions return TRUE for OK or 0 and set errno. If errno == @@ -127,7 +127,7 @@ int iptc_rename_chain(const xt_chainlabel oldname, /* Sets the policy on a built-in chain. */ int iptc_set_policy(const xt_chainlabel chain, const xt_chainlabel policy, - struct ipt_counters *counters, + struct xt_counters *counters, struct xtc_handle *handle); /* Get the number of references to this chain */ @@ -136,7 +136,7 @@ int iptc_get_references(unsigned int *ref, struct xtc_handle *handle); /* read packet and byte counters for a specific rule */ -struct ipt_counters *iptc_read_counter(const xt_chainlabel chain, +struct xt_counters *iptc_read_counter(const xt_chainlabel chain, unsigned int rulenum, struct xtc_handle *handle); @@ -148,7 +148,7 @@ int iptc_zero_counter(const xt_chainlabel chain, /* set packet and byte counters for a specific rule */ int iptc_set_counter(const xt_chainlabel chain, unsigned int rulenum, - struct ipt_counters *counters, + struct xt_counters *counters, struct xtc_handle *handle); /* Makes the actual changes. */ diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index c5afe315..073e42b8 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -77,7 +77,7 @@ static struct xtc_handle *create_handle(const char *tablename) return handle; } -static int parse_counters(char *string, struct ip6t_counters *ctr) +static int parse_counters(char *string, struct xt_counters *ctr) { unsigned long long pcnt, bcnt; int ret; @@ -119,7 +119,7 @@ int ip6tables_restore_main(int argc, char *argv[]) struct xtc_handle *handle = NULL; char buffer[10240]; int c; - char curtable[IP6T_TABLE_MAXNAMELEN + 1]; + char curtable[XT_TABLE_MAXNAMELEN + 1]; FILE *in; int in_table = 0, testing = 0; const char *tablename = NULL; @@ -218,8 +218,8 @@ int ip6tables_restore_main(int argc, char *argv[]) line); exit(1); } - strncpy(curtable, table, IP6T_TABLE_MAXNAMELEN); - curtable[IP6T_TABLE_MAXNAMELEN] = '\0'; + strncpy(curtable, table, XT_TABLE_MAXNAMELEN); + curtable[XT_TABLE_MAXNAMELEN] = '\0'; if (tablename != NULL && strcmp(tablename, table) != 0) continue; @@ -291,7 +291,7 @@ int ip6tables_restore_main(int argc, char *argv[]) } if (strcmp(policy, "-") != 0) { - struct ip6t_counters count; + struct xt_counters count; if (counters) { char *ctrs; @@ -303,8 +303,7 @@ int ip6tables_restore_main(int argc, char *argv[]) "for chain '%s'\n", chain); } else { - memset(&count, 0, - sizeof(struct ip6t_counters)); + memset(&count, 0, sizeof(count)); } DEBUGP("Setting policy of chain %s to %s\n", diff --git a/iptables/ip6tables-save.c b/iptables/ip6tables-save.c index fbfce788..d819b30b 100644 --- a/iptables/ip6tables-save.c +++ b/iptables/ip6tables-save.c @@ -38,7 +38,7 @@ static int for_each_table(int (*func)(const char *tablename)) { int ret = 1; FILE *procfile = NULL; - char tablename[IP6T_TABLE_MAXNAMELEN+1]; + char tablename[XT_TABLE_MAXNAMELEN+1]; procfile = fopen("/proc/net/ip6_tables_names", "re"); if (!procfile) @@ -89,7 +89,7 @@ static int do_output(const char *tablename) printf(":%s ", chain); if (ip6tc_builtin(chain, h)) { - struct ip6t_counters count; + struct xt_counters count; printf("%s ", ip6tc_get_policy(chain, &count, h)); printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 7b12205b..b191d5df 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -172,7 +172,7 @@ static const unsigned int inverse_for_options[NUMBER_OF_OPT] = /* -n */ 0, /* -s */ IP6T_INV_SRCIP, /* -d */ IP6T_INV_DSTIP, -/* -p */ IP6T_INV_PROTO, +/* -p */ XT_INV_PROTO, /* -j */ 0, /* -v */ 0, /* -x */ 0, @@ -471,7 +471,7 @@ print_num(uint64_t number, unsigned int format) static void print_header(unsigned int format, const char *chain, struct xtc_handle *handle) { - struct ip6t_counters counters; + struct xt_counters counters; const char *pol = ip6tc_get_policy(chain, &counters, handle); printf("Chain %s", chain); if (pol) { @@ -519,7 +519,7 @@ print_header(unsigned int format, const char *chain, struct xtc_handle *handle) static int -print_match(const struct ip6t_entry_match *m, +print_match(const struct xt_entry_match *m, const struct ip6t_ip6 *ip, int numeric) { @@ -548,13 +548,13 @@ print_firewall(const struct ip6t_entry *fw, struct xtc_handle *const handle) { const struct xtables_target *target = NULL; - const struct ip6t_entry_target *t; + const struct xt_entry_target *t; char buf[BUFSIZ]; if (!ip6tc_is_chain(targname, handle)) target = xtables_find_target(targname, XTF_TRY_LOAD); else - target = xtables_find_target(IP6T_STANDARD_TARGET, + target = xtables_find_target(XT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); t = ip6t_get_target((struct ip6t_entry *)fw); @@ -570,7 +570,7 @@ print_firewall(const struct ip6t_entry *fw, if (!(format & FMT_NOTARGET)) printf(FMT("%-9s ", "%s "), targname); - fputc(fw->ipv6.invflags & IP6T_INV_PROTO ? '!' : ' ', stdout); + fputc(fw->ipv6.invflags & XT_INV_PROTO ? '!' : ' ', stdout); { const char *pname = proto_to_name(fw->ipv6.proto, format&FMT_NUMERIC); if (pname) @@ -669,7 +669,7 @@ static void print_firewall_line(const struct ip6t_entry *fw, struct xtc_handle *const h) { - struct ip6t_entry_target *t; + struct xt_entry_target *t; t = ip6t_get_target((struct ip6t_entry *)fw); print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h); @@ -766,10 +766,10 @@ make_delete_mask(const struct xtables_rule_match *matches, size = sizeof(struct ip6t_entry); for (matchp = matches; matchp; matchp = matchp->next) - size += XT_ALIGN(sizeof(struct ip6t_entry_match)) + matchp->match->size; + size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size; mask = xtables_calloc(1, size - + XT_ALIGN(sizeof(struct ip6t_entry_target)) + + XT_ALIGN(sizeof(struct xt_entry_target)) + target->size); memset(mask, 0xFF, sizeof(struct ip6t_entry)); @@ -777,13 +777,13 @@ make_delete_mask(const struct xtables_rule_match *matches, for (matchp = matches; matchp; matchp = matchp->next) { memset(mptr, 0xFF, - XT_ALIGN(sizeof(struct ip6t_entry_match)) + XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->userspacesize); - mptr += XT_ALIGN(sizeof(struct ip6t_entry_match)) + matchp->match->size; + mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size; } memset(mptr, 0xFF, - XT_ALIGN(sizeof(struct ip6t_entry_target)) + XT_ALIGN(sizeof(struct xt_entry_target)) + target->userspacesize); return mask; @@ -1033,7 +1033,7 @@ static void print_proto(uint16_t proto, int invert) } } -static int print_match_save(const struct ip6t_entry_match *e, +static int print_match_save(const struct xt_entry_match *e, const struct ip6t_ip6 *ip) { const struct xtables_match *match = @@ -1082,7 +1082,7 @@ static void print_ip(const char *prefix, const struct in6_addr *ip, void print_rule6(const struct ip6t_entry *e, struct xtc_handle *h, const char *chain, int counters) { - const struct ip6t_entry_target *t; + const struct xt_entry_target *t; const char *target_name; /* print counters for iptables-save */ @@ -1105,7 +1105,7 @@ void print_rule6(const struct ip6t_entry *e, print_iface('o', e->ipv6.outiface, e->ipv6.outiface_mask, e->ipv6.invflags & IP6T_INV_VIA_OUT); - print_proto(e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO); + print_proto(e->ipv6.proto, e->ipv6.invflags & XT_INV_PROTO); #if 0 /* not definied in ipv6 @@ -1153,11 +1153,11 @@ void print_rule6(const struct ip6t_entry *e, if (target->save) target->save(&e->ipv6, t); else { - /* If the target size is greater than ip6t_entry_target + /* If the target size is greater than xt_entry_target * there is something to be saved, we just don't know * how to print it */ if (t->u.target_size != - sizeof(struct ip6t_entry_target)) { + sizeof(struct xt_entry_target)) { fprintf(stderr, "Target `%s' is missing " "save function\n", t->u.user.name); @@ -1187,7 +1187,7 @@ list_rules(const xt_chainlabel chain, int rulenum, int counters, continue; if (ip6tc_builtin(this, handle)) { - struct ip6t_counters count; + struct xt_counters count; printf("-P %s %s", this, ip6tc_get_policy(this, &count, handle)); if (counters) printf(" -c %llu %llu", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); @@ -1224,7 +1224,7 @@ list_rules(const xt_chainlabel chain, int rulenum, int counters, static struct ip6t_entry * generate_entry(const struct ip6t_entry *fw, struct xtables_rule_match *matches, - struct ip6t_entry_target *target) + struct xt_entry_target *target) { unsigned int size; struct xtables_rule_match *matchp; @@ -1282,7 +1282,7 @@ static void command_jump(struct iptables_command_state *cs) if (cs->target == NULL) return; - size = XT_ALIGN(sizeof(struct ip6t_entry_target)) + cs->target->size; + size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size; cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; @@ -1311,7 +1311,7 @@ static void command_match(struct iptables_command_state *cs) "unexpected ! flag before --match"); m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches); - size = XT_ALIGN(sizeof(struct ip6t_entry_match)) + m->size; + size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); @@ -1548,12 +1548,12 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle cs.fw6.ipv6.flags |= IP6T_F_PROTO; if (cs.fw6.ipv6.proto == 0 - && (cs.fw6.ipv6.invflags & IP6T_INV_PROTO)) + && (cs.fw6.ipv6.invflags & XT_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "rule would never match protocol"); if (is_exthdr(cs.fw6.ipv6.proto) - && (cs.fw6.ipv6.invflags & IP6T_INV_PROTO) == 0) + && (cs.fw6.ipv6.invflags & XT_INV_PROTO) == 0) fprintf(stderr, "Warning: never matched protocol: %s. " "use extension match instead.\n", @@ -1824,10 +1824,10 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle || ip6tc_is_chain(cs.jumpto, *handle))) { size_t size; - cs.target = xtables_find_target(IP6T_STANDARD_TARGET, + cs.target = xtables_find_target(XT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); - size = sizeof(struct ip6t_entry_target) + size = sizeof(struct xt_entry_target) + cs.target->size; cs.target->t = xtables_calloc(1, size); cs.target->t->u.target_size = size; diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 7152d750..001da734 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -76,7 +76,7 @@ static struct xtc_handle *create_handle(const char *tablename) return handle; } -static int parse_counters(char *string, struct ipt_counters *ctr) +static int parse_counters(char *string, struct xt_counters *ctr) { unsigned long long pcnt, bcnt; int ret; @@ -119,7 +119,7 @@ iptables_restore_main(int argc, char *argv[]) struct xtc_handle *handle = NULL; char buffer[10240]; int c; - char curtable[IPT_TABLE_MAXNAMELEN + 1]; + char curtable[XT_TABLE_MAXNAMELEN + 1]; FILE *in; int in_table = 0, testing = 0; const char *tablename = NULL; @@ -217,8 +217,8 @@ iptables_restore_main(int argc, char *argv[]) prog_name, line); exit(1); } - strncpy(curtable, table, IPT_TABLE_MAXNAMELEN); - curtable[IPT_TABLE_MAXNAMELEN] = '\0'; + strncpy(curtable, table, XT_TABLE_MAXNAMELEN); + curtable[XT_TABLE_MAXNAMELEN] = '\0'; if (tablename && (strcmp(tablename, table) != 0)) continue; @@ -288,7 +288,7 @@ iptables_restore_main(int argc, char *argv[]) } if (strcmp(policy, "-") != 0) { - struct ipt_counters count; + struct xt_counters count; if (counters) { char *ctrs; @@ -300,8 +300,7 @@ iptables_restore_main(int argc, char *argv[]) "for chain '%s'\n", chain); } else { - memset(&count, 0, - sizeof(struct ipt_counters)); + memset(&count, 0, sizeof(count)); } DEBUGP("Setting policy of chain %s to %s\n", diff --git a/iptables/iptables-save.c b/iptables/iptables-save.c index ff42f884..e599fcec 100644 --- a/iptables/iptables-save.c +++ b/iptables/iptables-save.c @@ -36,7 +36,7 @@ static int for_each_table(int (*func)(const char *tablename)) { int ret = 1; FILE *procfile = NULL; - char tablename[IPT_TABLE_MAXNAMELEN+1]; + char tablename[XT_TABLE_MAXNAMELEN+1]; procfile = fopen("/proc/net/ip_tables_names", "re"); if (!procfile) @@ -87,7 +87,7 @@ static int do_output(const char *tablename) printf(":%s ", chain); if (iptc_builtin(chain, h)) { - struct ipt_counters count; + struct xt_counters count; printf("%s ", iptc_get_policy(chain, &count, h)); printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); diff --git a/iptables/iptables-xml.c b/iptables/iptables-xml.c index 4ecddcb7..4b12bd46 100644 --- a/iptables/iptables-xml.c +++ b/iptables/iptables-xml.c @@ -56,7 +56,7 @@ print_usage(const char *name, const char *version) } static int -parse_counters(char *string, struct ipt_counters *ctr) +parse_counters(char *string, struct xt_counters *ctr) { __u64 *pcnt, *bcnt; @@ -81,16 +81,16 @@ static unsigned int oldargc = 0; /* arg meta data, were they quoted, frinstance */ static int newargvattr[255]; -#define IPT_CHAIN_MAXNAMELEN IPT_TABLE_MAXNAMELEN -static char closeActionTag[IPT_TABLE_MAXNAMELEN + 1]; -static char closeRuleTag[IPT_TABLE_MAXNAMELEN + 1]; -static char curTable[IPT_TABLE_MAXNAMELEN + 1]; -static char curChain[IPT_CHAIN_MAXNAMELEN + 1]; +#define XT_CHAIN_MAXNAMELEN XT_TABLE_MAXNAMELEN +static char closeActionTag[XT_TABLE_MAXNAMELEN + 1]; +static char closeRuleTag[XT_TABLE_MAXNAMELEN + 1]; +static char curTable[XT_TABLE_MAXNAMELEN + 1]; +static char curChain[XT_CHAIN_MAXNAMELEN + 1]; struct chain { char *chain; char *policy; - struct ipt_counters count; + struct xt_counters count; int created; }; @@ -233,12 +233,12 @@ closeChain(void) } static void -openChain(char *chain, char *policy, struct ipt_counters *ctr, char close) +openChain(char *chain, char *policy, struct xt_counters *ctr, char close) { closeChain(); - strncpy(curChain, chain, IPT_CHAIN_MAXNAMELEN); - curChain[IPT_CHAIN_MAXNAMELEN] = '\0'; + strncpy(curChain, chain, XT_CHAIN_MAXNAMELEN); + curChain[XT_CHAIN_MAXNAMELEN] = '\0'; printf(" = maxChains) { xtables_error(PARAMETER_PROBLEM, @@ -332,8 +332,8 @@ openTable(char *table) { closeTable(); - strncpy(curTable, table, IPT_TABLE_MAXNAMELEN); - curTable[IPT_TABLE_MAXNAMELEN] = '\0'; + strncpy(curTable, table, XT_TABLE_MAXNAMELEN); + curTable[XT_TABLE_MAXNAMELEN] = '\0'; printf(" \n"); - strncpy(closeRuleTag, " \n", IPT_TABLE_MAXNAMELEN); - closeRuleTag[IPT_TABLE_MAXNAMELEN] = '\0'; + strncpy(closeRuleTag, " \n", XT_TABLE_MAXNAMELEN); + closeRuleTag[XT_TABLE_MAXNAMELEN] = '\0'; /* no point in writing out condition if there isn't one */ if (argc >= 3 && !isTarget(argv[2])) { @@ -607,8 +607,8 @@ do_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[]) if (!closeActionTag[0]) { printf(" \n"); strncpy(closeActionTag, " \n", - IPT_TABLE_MAXNAMELEN); - closeActionTag[IPT_TABLE_MAXNAMELEN] = '\0'; + XT_TABLE_MAXNAMELEN); + closeActionTag[XT_TABLE_MAXNAMELEN] = '\0'; } do_rule_part(NULL, NULL, 1, argc, argv, argvattr); } @@ -694,7 +694,7 @@ iptables_xml_main(int argc, char *argv[]) } else if ((buffer[0] == ':') && (curTable[0])) { /* New chain. */ char *policy, *chain; - struct ipt_counters count; + struct xt_counters count; char *ctrs; chain = strtok(buffer + 1, " \t\n"); diff --git a/iptables/iptables.c b/iptables/iptables.c index d4a7ca11..03ac63b8 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -171,7 +171,7 @@ static const int inverse_for_options[NUMBER_OF_OPT] = /* -n */ 0, /* -s */ IPT_INV_SRCIP, /* -d */ IPT_INV_DSTIP, -/* -p */ IPT_INV_PROTO, +/* -p */ XT_INV_PROTO, /* -j */ 0, /* -v */ 0, /* -x */ 0, @@ -473,7 +473,7 @@ print_num(uint64_t number, unsigned int format) static void print_header(unsigned int format, const char *chain, struct xtc_handle *handle) { - struct ipt_counters counters; + struct xt_counters counters; const char *pol = iptc_get_policy(chain, &counters, handle); printf("Chain %s", chain); if (pol) { @@ -521,7 +521,7 @@ print_header(unsigned int format, const char *chain, struct xtc_handle *handle) static int -print_match(const struct ipt_entry_match *m, +print_match(const struct xt_entry_match *m, const struct ipt_ip *ip, int numeric) { @@ -550,14 +550,14 @@ print_firewall(const struct ipt_entry *fw, struct xtc_handle *const handle) { const struct xtables_target *target = NULL; - const struct ipt_entry_target *t; + const struct xt_entry_target *t; uint8_t flags; char buf[BUFSIZ]; if (!iptc_is_chain(targname, handle)) target = xtables_find_target(targname, XTF_TRY_LOAD); else - target = xtables_find_target(IPT_STANDARD_TARGET, + target = xtables_find_target(XT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); t = ipt_get_target((struct ipt_entry *)fw); @@ -574,7 +574,7 @@ print_firewall(const struct ipt_entry *fw, if (!(format & FMT_NOTARGET)) printf(FMT("%-9s ", "%s "), targname); - fputc(fw->ip.invflags & IPT_INV_PROTO ? '!' : ' ', stdout); + fputc(fw->ip.invflags & XT_INV_PROTO ? '!' : ' ', stdout); { const char *pname = proto_to_name(fw->ip.proto, format&FMT_NUMERIC); if (pname) @@ -671,7 +671,7 @@ static void print_firewall_line(const struct ipt_entry *fw, struct xtc_handle *const h) { - struct ipt_entry_target *t; + struct xt_entry_target *t; t = ipt_get_target((struct ipt_entry *)fw); print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h); @@ -768,10 +768,10 @@ make_delete_mask(const struct xtables_rule_match *matches, size = sizeof(struct ipt_entry); for (matchp = matches; matchp; matchp = matchp->next) - size += XT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size; + size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size; mask = xtables_calloc(1, size - + XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct xt_entry_target)) + target->size); memset(mask, 0xFF, sizeof(struct ipt_entry)); @@ -779,13 +779,13 @@ make_delete_mask(const struct xtables_rule_match *matches, for (matchp = matches; matchp; matchp = matchp->next) { memset(mptr, 0xFF, - XT_ALIGN(sizeof(struct ipt_entry_match)) + XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->userspacesize); - mptr += XT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size; + mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size; } memset(mptr, 0xFF, - XT_ALIGN(sizeof(struct ipt_entry_target)) + XT_ALIGN(sizeof(struct xt_entry_target)) + target->userspacesize); return mask; @@ -1041,7 +1041,7 @@ print_iface(char letter, const char *iface, const unsigned char *mask, } } -static int print_match_save(const struct ipt_entry_match *e, +static int print_match_save(const struct xt_entry_match *e, const struct ipt_ip *ip) { const struct xtables_match *match = @@ -1099,7 +1099,7 @@ static void print_ip(const char *prefix, uint32_t ip, void print_rule4(const struct ipt_entry *e, struct xtc_handle *h, const char *chain, int counters) { - const struct ipt_entry_target *t; + const struct xt_entry_target *t; const char *target_name; /* print counters for iptables-save */ @@ -1122,7 +1122,7 @@ void print_rule4(const struct ipt_entry *e, print_iface('o', e->ip.outiface, e->ip.outiface_mask, e->ip.invflags & IPT_INV_VIA_OUT); - print_proto(e->ip.proto, e->ip.invflags & IPT_INV_PROTO); + print_proto(e->ip.proto, e->ip.invflags & XT_INV_PROTO); if (e->ip.flags & IPT_F_FRAG) printf("%s -f", @@ -1161,11 +1161,11 @@ void print_rule4(const struct ipt_entry *e, if (target->save) target->save(&e->ip, t); else { - /* If the target size is greater than ipt_entry_target + /* If the target size is greater than xt_entry_target * there is something to be saved, we just don't know * how to print it */ if (t->u.target_size != - sizeof(struct ipt_entry_target)) { + sizeof(struct xt_entry_target)) { fprintf(stderr, "Target `%s' is missing " "save function\n", t->u.user.name); @@ -1195,7 +1195,7 @@ list_rules(const xt_chainlabel chain, int rulenum, int counters, continue; if (iptc_builtin(this, handle)) { - struct ipt_counters count; + struct xt_counters count; printf("-P %s %s", this, iptc_get_policy(this, &count, handle)); if (counters) printf(" -c %llu %llu", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); @@ -1232,7 +1232,7 @@ list_rules(const xt_chainlabel chain, int rulenum, int counters, static struct ipt_entry * generate_entry(const struct ipt_entry *fw, struct xtables_rule_match *matches, - struct ipt_entry_target *target) + struct xt_entry_target *target) { unsigned int size; struct xtables_rule_match *matchp; @@ -1290,7 +1290,7 @@ static void command_jump(struct iptables_command_state *cs) if (cs->target == NULL) return; - size = XT_ALIGN(sizeof(struct ipt_entry_target)) + size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size; cs->target->t = xtables_calloc(1, size); @@ -1321,7 +1321,7 @@ static void command_match(struct iptables_command_state *cs) "unexpected ! flag before --match"); m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches); - size = XT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; + size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); @@ -1559,7 +1559,7 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle cs.fw.ip.proto = xtables_parse_protocol(cs.protocol); if (cs.fw.ip.proto == 0 - && (cs.fw.ip.invflags & IPT_INV_PROTO)) + && (cs.fw.ip.invflags & XT_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "rule would never match protocol"); break; @@ -1837,10 +1837,10 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle || iptc_is_chain(cs.jumpto, *handle))) { size_t size; - cs.target = xtables_find_target(IPT_STANDARD_TARGET, + cs.target = xtables_find_target(XT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); - size = sizeof(struct ipt_entry_target) + size = sizeof(struct xt_entry_target) + cs.target->size; cs.target->t = xtables_calloc(1, size); cs.target->t->u.target_size = size; diff --git a/iptables/xshared.c b/iptables/xshared.c index 79da507d..e61c28c8 100644 --- a/iptables/xshared.c +++ b/iptables/xshared.c @@ -139,7 +139,7 @@ int command_default(struct iptables_command_state *cs, cs->proto_used = 1; - size = XT_ALIGN(sizeof(struct ip6t_entry_match)) + m->size; + size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c index cf292381..c55cbc7d 100644 --- a/libiptc/libip4tc.c +++ b/libiptc/libip4tc.c @@ -37,23 +37,23 @@ typedef unsigned int socklen_t; #define HOOK_LOCAL_OUT NF_IP_LOCAL_OUT #define HOOK_POST_ROUTING NF_IP_POST_ROUTING -#define STRUCT_ENTRY_TARGET struct ipt_entry_target +#define STRUCT_ENTRY_TARGET struct xt_entry_target #define STRUCT_ENTRY struct ipt_entry -#define STRUCT_ENTRY_MATCH struct ipt_entry_match +#define STRUCT_ENTRY_MATCH struct xt_entry_match #define STRUCT_GETINFO struct ipt_getinfo #define STRUCT_GET_ENTRIES struct ipt_get_entries -#define STRUCT_COUNTERS struct ipt_counters -#define STRUCT_COUNTERS_INFO struct ipt_counters_info -#define STRUCT_STANDARD_TARGET struct ipt_standard_target +#define STRUCT_COUNTERS struct xt_counters +#define STRUCT_COUNTERS_INFO struct xt_counters_info +#define STRUCT_STANDARD_TARGET struct xt_standard_target #define STRUCT_REPLACE struct ipt_replace #define ENTRY_ITERATE IPT_ENTRY_ITERATE -#define TABLE_MAXNAMELEN IPT_TABLE_MAXNAMELEN -#define FUNCTION_MAXNAMELEN IPT_FUNCTION_MAXNAMELEN +#define TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN +#define FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN #define GET_TARGET ipt_get_target -#define ERROR_TARGET IPT_ERROR_TARGET +#define ERROR_TARGET XT_ERROR_TARGET #define NUMHOOKS NF_IP_NUMHOOKS #define IPT_CHAINLABEL xt_chainlabel @@ -100,14 +100,14 @@ typedef unsigned int socklen_t; #define SO_GET_ENTRIES IPT_SO_GET_ENTRIES #define SO_GET_VERSION IPT_SO_GET_VERSION -#define STANDARD_TARGET IPT_STANDARD_TARGET +#define STANDARD_TARGET XT_STANDARD_TARGET #define LABEL_RETURN IPTC_LABEL_RETURN #define LABEL_ACCEPT IPTC_LABEL_ACCEPT #define LABEL_DROP IPTC_LABEL_DROP #define LABEL_QUEUE IPTC_LABEL_QUEUE #define ALIGN XT_ALIGN -#define RETURN IPT_RETURN +#define RETURN XT_RETURN #include "libiptc.c" @@ -160,7 +160,7 @@ dump_entry(struct ipt_entry *e, struct xtc_handle *const handle) : "UNKNOWN"); else printf("verdict=%u\n", pos); - } else if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0) + } else if (strcmp(t->u.user.name, XT_ERROR_TARGET) == 0) printf("error=`%s'\n", t->data); printf("\n"); @@ -203,7 +203,7 @@ is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask) mptr = matchmask + sizeof(STRUCT_ENTRY); if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr)) return NULL; - mptr += XT_ALIGN(sizeof(struct ipt_entry_target)); + mptr += XT_ALIGN(sizeof(struct xt_entry_target)); return mptr; } @@ -271,14 +271,14 @@ check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off, idx = iptcb_entry2index(h, te); assert(strcmp(GET_TARGET(te)->u.user.name, - IPT_ERROR_TARGET) + XT_ERROR_TARGET) != 0); assert(te != e); /* Prior node must be error node, or this node. */ assert(t->verdict == iptcb_entry2offset(h, e)+e->next_offset || strcmp(GET_TARGET(index2entry(h, idx-1)) - ->u.user.name, IPT_ERROR_TARGET) + ->u.user.name, XT_ERROR_TARGET) == 0); } @@ -288,7 +288,7 @@ check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off, *was_return = 1; else *was_return = 0; - } else if (strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0) { + } else if (strcmp(t->target.u.user.name, XT_ERROR_TARGET) == 0) { assert(t->target.u.target_size == ALIGN(sizeof(struct ipt_error_target))); @@ -301,7 +301,7 @@ check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off, else *was_return = 0; if (*off == user_offset) - assert(strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0); + assert(strcmp(t->target.u.user.name, XT_ERROR_TARGET) == 0); (*off) += e->next_offset; (*i)++; diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index 636466f1..9febee30 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -35,23 +35,23 @@ typedef unsigned int socklen_t; #define HOOK_LOCAL_OUT NF_IP6_LOCAL_OUT #define HOOK_POST_ROUTING NF_IP6_POST_ROUTING -#define STRUCT_ENTRY_TARGET struct ip6t_entry_target +#define STRUCT_ENTRY_TARGET struct xt_entry_target #define STRUCT_ENTRY struct ip6t_entry -#define STRUCT_ENTRY_MATCH struct ip6t_entry_match +#define STRUCT_ENTRY_MATCH struct xt_entry_match #define STRUCT_GETINFO struct ip6t_getinfo #define STRUCT_GET_ENTRIES struct ip6t_get_entries -#define STRUCT_COUNTERS struct ip6t_counters -#define STRUCT_COUNTERS_INFO struct ip6t_counters_info -#define STRUCT_STANDARD_TARGET struct ip6t_standard_target +#define STRUCT_COUNTERS struct xt_counters +#define STRUCT_COUNTERS_INFO struct xt_counters_info +#define STRUCT_STANDARD_TARGET struct xt_standard_target #define STRUCT_REPLACE struct ip6t_replace #define ENTRY_ITERATE IP6T_ENTRY_ITERATE -#define TABLE_MAXNAMELEN IP6T_TABLE_MAXNAMELEN -#define FUNCTION_MAXNAMELEN IP6T_FUNCTION_MAXNAMELEN +#define TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN +#define FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN #define GET_TARGET ip6t_get_target -#define ERROR_TARGET IP6T_ERROR_TARGET +#define ERROR_TARGET XT_ERROR_TARGET #define NUMHOOKS NF_IP6_NUMHOOKS #define IPT_CHAINLABEL xt_chainlabel @@ -98,14 +98,14 @@ typedef unsigned int socklen_t; #define SO_GET_ENTRIES IP6T_SO_GET_ENTRIES #define SO_GET_VERSION IP6T_SO_GET_VERSION -#define STANDARD_TARGET IP6T_STANDARD_TARGET +#define STANDARD_TARGET XT_STANDARD_TARGET #define LABEL_RETURN IP6TC_LABEL_RETURN #define LABEL_ACCEPT IP6TC_LABEL_ACCEPT #define LABEL_DROP IP6TC_LABEL_DROP #define LABEL_QUEUE IP6TC_LABEL_QUEUE #define ALIGN XT_ALIGN -#define RETURN IP6T_RETURN +#define RETURN XT_RETURN #include "libiptc.c" @@ -133,7 +133,7 @@ dump_entry(struct ip6t_entry *e, struct xtc_handle *const handle) size_t i; char buf[40]; int len; - struct ip6t_entry_target *t; + struct xt_entry_target *t; printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e), iptcb_entry2offset(handle, e)); @@ -182,18 +182,18 @@ dump_entry(struct ip6t_entry *e, struct xtc_handle *const handle) t = ip6t_get_target(e); printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size); - if (strcmp(t->u.user.name, IP6T_STANDARD_TARGET) == 0) { + if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0) { const unsigned char *data = t->data; int pos = *(const int *)data; if (pos < 0) printf("verdict=%s\n", pos == -NF_ACCEPT-1 ? "NF_ACCEPT" : pos == -NF_DROP-1 ? "NF_DROP" - : pos == IP6T_RETURN ? "RETURN" + : pos == XT_RETURN ? "RETURN" : "UNKNOWN"); else printf("verdict=%u\n", pos); - } else if (strcmp(t->u.user.name, IP6T_ERROR_TARGET) == 0) + } else if (strcmp(t->u.user.name, XT_ERROR_TARGET) == 0) printf("error=`%s'\n", t->data); printf("\n"); @@ -238,7 +238,7 @@ is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, mptr = matchmask + sizeof(STRUCT_ENTRY); if (IP6T_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr)) return NULL; - mptr += XT_ALIGN(sizeof(struct ip6t_entry_target)); + mptr += XT_ALIGN(sizeof(struct xt_entry_target)); return mptr; } -- cgit v1.2.3 From de4d2d3b716d83a6d3831aaf902c5adb5d1d14c9 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 12:50:32 +0200 Subject: libiptc: use a family-invariant xtc_ops struct for code reduction Signed-off-by: Jan Engelhardt --- include/libiptc/libip6tc.h | 2 ++ include/libiptc/libiptc.h | 2 ++ include/libiptc/xtcshared.h | 13 +++++++++++++ libiptc/Makefile.am | 4 ++-- libiptc/libip4tc.c | 1 + libiptc/libip6tc.c | 1 + libiptc/libiptc.c | 12 ++++++++++++ 7 files changed, 33 insertions(+), 2 deletions(-) diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index 61c1e7f5..c656bc43 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -159,4 +159,6 @@ int ipv6_prefix_length(const struct in6_addr *a); extern void dump_entries6(struct xtc_handle *const); +extern const struct xtc_ops ip6tc_ops; + #endif /* _LIBIP6TC_H */ diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index 6f64f5a9..24cdbdb7 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -162,6 +162,8 @@ const char *iptc_strerror(int err); extern void dump_entries(struct xtc_handle *const); +extern const struct xtc_ops iptc_ops; + #ifdef __cplusplus } #endif diff --git a/include/libiptc/xtcshared.h b/include/libiptc/xtcshared.h index 89a51511..773ebc4c 100644 --- a/include/libiptc/xtcshared.h +++ b/include/libiptc/xtcshared.h @@ -3,5 +3,18 @@ typedef char xt_chainlabel[32]; struct xtc_handle; +struct xt_counters; + +struct xtc_ops { + int (*commit)(struct xtc_handle *); + void (*free)(struct xtc_handle *); + int (*builtin)(const char *, struct xtc_handle *const); + int (*is_chain)(const char *, struct xtc_handle *const); + int (*flush_entries)(const xt_chainlabel, struct xtc_handle *); + int (*create_chain)(const xt_chainlabel, struct xtc_handle *); + int (*set_policy)(const xt_chainlabel, const xt_chainlabel, + struct xt_counters *, struct xtc_handle *); + const char *(*strerror)(int); +}; #endif /* _LIBXTC_SHARED_H */ diff --git a/libiptc/Makefile.am b/libiptc/Makefile.am index 22c920f6..0b59007d 100644 --- a/libiptc/Makefile.am +++ b/libiptc/Makefile.am @@ -10,6 +10,6 @@ libiptc_la_SOURCES = libiptc_la_LIBADD = libip4tc.la libip6tc.la libiptc_la_LDFLAGS = -version-info 0:0:0 ${libiptc_LDFLAGS2} libip4tc_la_SOURCES = libip4tc.c -libip4tc_la_LDFLAGS = -version-info 0:0:0 +libip4tc_la_LDFLAGS = -version-info 1:0:1 libip6tc_la_SOURCES = libip6tc.c -libip6tc_la_LDFLAGS = -version-info 0:0:0 ${libiptc_LDFLAGS2} +libip6tc_la_LDFLAGS = -version-info 1:0:1 ${libiptc_LDFLAGS2} diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c index c55cbc7d..dd599516 100644 --- a/libiptc/libip4tc.c +++ b/libiptc/libip4tc.c @@ -90,6 +90,7 @@ typedef unsigned int socklen_t; #define TC_STRERROR iptc_strerror #define TC_NUM_RULES iptc_num_rules #define TC_GET_RULE iptc_get_rule +#define TC_OPS iptc_ops #define TC_AF AF_INET #define TC_IPPROTO IPPROTO_IP diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index 9febee30..7128e1cf 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -88,6 +88,7 @@ typedef unsigned int socklen_t; #define TC_STRERROR ip6tc_strerror #define TC_NUM_RULES ip6tc_num_rules #define TC_GET_RULE ip6tc_get_rule +#define TC_OPS ip6tc_ops #define TC_AF AF_INET6 #define TC_IPPROTO IPPROTO_IPV6 diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 593c5de8..63fcfc2a 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "linux_list.h" @@ -2731,3 +2732,14 @@ TC_STRERROR(int err) return strerror(err); } + +const struct xtc_ops TC_OPS = { + .commit = TC_COMMIT, + .free = TC_FREE, + .builtin = TC_BUILTIN, + .is_chain = TC_IS_CHAIN, + .flush_entries = TC_FLUSH_ENTRIES, + .create_chain = TC_CREATE_CHAIN, + .set_policy = TC_SET_POLICY, + .strerror = TC_STRERROR, +}; -- cgit v1.2.3 From 0ab10b11093ec250b404e3bead1d39177d1cbfa0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 27 Aug 2011 10:34:01 +0200 Subject: ip6tables-restore: make code look alike with iptables-restore Signed-off-by: Jan Engelhardt --- iptables/ip6tables-restore.c | 34 +++++++++++++++------------------- iptables/iptables-restore.c | 29 +++++++++++++++-------------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 073e42b8..92bdc302 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -123,6 +123,7 @@ int ip6tables_restore_main(int argc, char *argv[]) FILE *in; int in_table = 0, testing = 0; const char *tablename = NULL; + const struct xtc_ops *ops = &ip6tc_ops; line = 0; @@ -197,8 +198,8 @@ int ip6tables_restore_main(int argc, char *argv[]) } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) { if (!testing) { DEBUGP("Calling commit\n"); - ret = ip6tc_commit(handle); - ip6tc_free(handle); + ret = ops->commit(handle); + ops->free(handle); handle = NULL; } else { DEBUGP("Not calling commit, testing\n"); @@ -214,8 +215,7 @@ int ip6tables_restore_main(int argc, char *argv[]) if (!table) { xtables_error(PARAMETER_PROBLEM, "%s: line %u table name invalid\n", - ip6tables_globals.program_name, - line); + xt_params->program_name, line); exit(1); } strncpy(curtable, table, XT_TABLE_MAXNAMELEN); @@ -224,7 +224,7 @@ int ip6tables_restore_main(int argc, char *argv[]) if (tablename != NULL && strcmp(tablename, table) != 0) continue; if (handle) - ip6tc_free(handle); + ops->free(handle); handle = create_handle(table); if (noflush == 0) { @@ -251,8 +251,7 @@ int ip6tables_restore_main(int argc, char *argv[]) if (!chain) { xtables_error(PARAMETER_PROBLEM, "%s: line %u chain name invalid\n", - ip6tables_globals.program_name, - line); + xt_params->program_name, line); exit(1); } @@ -262,17 +261,17 @@ int ip6tables_restore_main(int argc, char *argv[]) "(%u chars max)", chain, XT_EXTENSION_MAXNAMELEN - 1); - if (ip6tc_builtin(chain, handle) <= 0) { - if (noflush && ip6tc_is_chain(chain, handle)) { + if (ops->builtin(chain, handle) <= 0) { + if (noflush && ops->is_chain(chain, handle)) { DEBUGP("Flushing existing user defined chain '%s'\n", chain); - if (!ip6tc_flush_entries(chain, handle)) + if (!ops->flush_entries(chain, handle)) xtables_error(PARAMETER_PROBLEM, "error flushing chain " "'%s':%s\n", chain, strerror(errno)); } else { DEBUGP("Creating new chain '%s'\n", chain); - if (!ip6tc_create_chain(chain, handle)) + if (!ops->create_chain(chain, handle)) xtables_error(PARAMETER_PROBLEM, "error creating chain " "'%s':%s\n", chain, @@ -285,8 +284,7 @@ int ip6tables_restore_main(int argc, char *argv[]) if (!policy) { xtables_error(PARAMETER_PROBLEM, "%s: line %u policy invalid\n", - ip6tables_globals.program_name, - line); + xt_params->program_name, line); exit(1); } @@ -309,13 +307,13 @@ int ip6tables_restore_main(int argc, char *argv[]) DEBUGP("Setting policy of chain %s to %s\n", chain, policy); - if (!ip6tc_set_policy(chain, policy, &count, + if (!ops->set_policy(chain, policy, &count, handle)) xtables_error(OTHER_PROBLEM, "Can't set policy `%s'" " on `%s' line %u: %s\n", policy, chain, line, - ip6tc_strerror(errno)); + ops->strerror(errno)); } ret = 1; @@ -452,15 +450,13 @@ int ip6tables_restore_main(int argc, char *argv[]) continue; if (!ret) { fprintf(stderr, "%s: line %u failed\n", - ip6tables_globals.program_name, - line); + xt_params->program_name, line); exit(1); } } if (in_table) { fprintf(stderr, "%s: COMMIT expected at line %u\n", - ip6tables_globals.program_name, - line + 1); + xt_params->program_name, line + 1); exit(1); } diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 001da734..6b1c7929 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -123,6 +123,7 @@ iptables_restore_main(int argc, char *argv[]) FILE *in; int in_table = 0, testing = 0; const char *tablename = NULL; + const struct xtc_ops *ops = &iptc_ops; line = 0; @@ -197,8 +198,8 @@ iptables_restore_main(int argc, char *argv[]) } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) { if (!testing) { DEBUGP("Calling commit\n"); - ret = iptc_commit(handle); - iptc_free(handle); + ret = ops->commit(handle); + ops->free(handle); handle = NULL; } else { DEBUGP("Not calling commit, testing\n"); @@ -214,7 +215,7 @@ iptables_restore_main(int argc, char *argv[]) if (!table) { xtables_error(PARAMETER_PROBLEM, "%s: line %u table name invalid\n", - prog_name, line); + xt_params->program_name, line); exit(1); } strncpy(curtable, table, XT_TABLE_MAXNAMELEN); @@ -223,7 +224,7 @@ iptables_restore_main(int argc, char *argv[]) if (tablename && (strcmp(tablename, table) != 0)) continue; if (handle) - iptc_free(handle); + ops->free(handle); handle = create_handle(table); if (noflush == 0) { @@ -250,7 +251,7 @@ iptables_restore_main(int argc, char *argv[]) if (!chain) { xtables_error(PARAMETER_PROBLEM, "%s: line %u chain name invalid\n", - prog_name, line); + xt_params->program_name, line); exit(1); } @@ -260,17 +261,17 @@ iptables_restore_main(int argc, char *argv[]) "(%u chars max)", chain, XT_EXTENSION_MAXNAMELEN - 1); - if (iptc_builtin(chain, handle) <= 0) { - if (noflush && iptc_is_chain(chain, handle)) { + if (ops->builtin(chain, handle) <= 0) { + if (noflush && ops->is_chain(chain, handle)) { DEBUGP("Flushing existing user defined chain '%s'\n", chain); - if (!iptc_flush_entries(chain, handle)) + if (!ops->flush_entries(chain, handle)) xtables_error(PARAMETER_PROBLEM, "error flushing chain " "'%s':%s\n", chain, strerror(errno)); } else { DEBUGP("Creating new chain '%s'\n", chain); - if (!iptc_create_chain(chain, handle)) + if (!ops->create_chain(chain, handle)) xtables_error(PARAMETER_PROBLEM, "error creating chain " "'%s':%s\n", chain, @@ -283,7 +284,7 @@ iptables_restore_main(int argc, char *argv[]) if (!policy) { xtables_error(PARAMETER_PROBLEM, "%s: line %u policy invalid\n", - prog_name, line); + xt_params->program_name, line); exit(1); } @@ -306,13 +307,13 @@ iptables_restore_main(int argc, char *argv[]) DEBUGP("Setting policy of chain %s to %s\n", chain, policy); - if (!iptc_set_policy(chain, policy, &count, + if (!ops->set_policy(chain, policy, &count, handle)) xtables_error(OTHER_PROBLEM, "Can't set policy `%s'" " on `%s' line %u: %s\n", policy, chain, line, - iptc_strerror(errno)); + ops->strerror(errno)); } ret = 1; @@ -449,13 +450,13 @@ iptables_restore_main(int argc, char *argv[]) continue; if (!ret) { fprintf(stderr, "%s: line %u failed\n", - prog_name, line); + xt_params->program_name, line); exit(1); } } if (in_table) { fprintf(stderr, "%s: COMMIT expected at line %u\n", - prog_name, line + 1); + xt_params->program_name, line + 1); exit(1); } -- cgit v1.2.3 From 8816e91cddef785c78b3598c7c41a1f88be08f5a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Sep 2011 15:06:05 +0200 Subject: build: restore build order of modules iptables(exe) requires libext.a, but extensions/ require libxtables.la (in iptables/). This circular dependency does not work out, so separate libxtables into its own directory and put it in front. Signed-off-by: Jan Engelhardt --- Makefile.am | 5 +- configure.ac | 2 +- extensions/GNUmakefile.in | 4 +- iptables/Makefile.am | 18 +- iptables/xtables.c | 1832 --------------------------------------------- iptables/xtoptions.c | 1171 ----------------------------- libxtables/Makefile.am | 20 + libxtables/xtables.c | 1832 +++++++++++++++++++++++++++++++++++++++++++++ libxtables/xtoptions.c | 1171 +++++++++++++++++++++++++++++ 9 files changed, 3031 insertions(+), 3024 deletions(-) delete mode 100644 iptables/xtables.c delete mode 100644 iptables/xtoptions.c create mode 100644 libxtables/Makefile.am create mode 100644 libxtables/xtables.c create mode 100644 libxtables/xtoptions.c diff --git a/Makefile.am b/Makefile.am index 9167e8e3..4eb63ebe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign subdir-objects -SUBDIRS = libiptc iptables +SUBDIRS = libiptc libxtables if ENABLE_DEVEL SUBDIRS += include endif @@ -13,7 +13,10 @@ endif if HAVE_LIBNFNETLINK SUBDIRS += utils endif +# Depends on libxtables: SUBDIRS += extensions +# Depends on extensions/libext.a: +SUBDIRS += iptables .PHONY: tarball tarball: diff --git a/configure.ac b/configure.ac index 22b7bf15..8afba8c1 100644 --- a/configure.ac +++ b/configure.ac @@ -112,6 +112,6 @@ AC_SUBST([libxtables_vmajor]) AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc libipq/Makefile libipq/libipq.pc - libiptc/Makefile libiptc/libiptc.pc utils/Makefile + libiptc/Makefile libiptc/libiptc.pc libxtables/Makefile utils/Makefile include/xtables.h include/iptables/internal.h]) AC_OUTPUT diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 60f28c0c..221c2c91 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -72,10 +72,10 @@ all: ${targets} check check: ${targets} @echo " CHECK unknown symbols in .so files"; \ - . ../iptables/libxtables.la; \ + . ../libxtables/libxtables.la; \ for i in "" lib*.so; do \ [ -z "$$i" ] && continue; \ - LD_PRELOAD="$$dlname" LD_LIBRARY_PATH=../iptables/.libs \ + LD_PRELOAD="$$dlname" LD_LIBRARY_PATH=../libxtables/.libs \ ldd -r $$i 2>&1 >/dev/null; \ done; diff --git a/iptables/Makefile.am b/iptables/Makefile.am index af620f76..bdd4da11 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -3,22 +3,6 @@ AM_CFLAGS = ${regular_CFLAGS} AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CPPFLAGS} -lib_LTLIBRARIES = libxtables.la -libxtables_la_SOURCES = xtables.c xtoptions.c -libxtables_la_LDFLAGS = -version-info ${libxtables_vcurrent}:0:${libxtables_vage} -libxtables_la_LIBADD = -if ENABLE_STATIC -# With --enable-static, shipped extensions are linked into the main executable, -# so we need all the LIBADDs here too -libxtables_la_LIBADD += -lm -endif -if ENABLE_SHARED -libxtables_la_CFLAGS = ${AM_CFLAGS} -libxtables_la_LIBADD += -ldl -else -libxtables_la_CFLAGS = ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -endif - xtables_multi_SOURCES = xtables-multi.c iptables-xml.c xtables_multi_CFLAGS = ${AM_CFLAGS} xtables_multi_LDADD = ../extensions/libext.a @@ -38,7 +22,7 @@ xtables_multi_CFLAGS += -DENABLE_IPV6 xtables_multi_LDADD += ../libiptc/libip6tc.la ../extensions/libext6.a endif xtables_multi_SOURCES += xshared.c -xtables_multi_LDADD += libxtables.la -lm +xtables_multi_LDADD += ../libxtables/libxtables.la -lm sbin_PROGRAMS = xtables-multi man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \ diff --git a/iptables/xtables.c b/iptables/xtables.c deleted file mode 100644 index 014e115b..00000000 --- a/iptables/xtables.c +++ /dev/null @@ -1,1832 +0,0 @@ -/* - * (C) 2000-2006 by the netfilter coreteam : - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(HAVE_LINUX_MAGIC_H) -# include /* for PROC_SUPER_MAGIC */ -#elif defined(HAVE_LINUX_PROC_FS_H) -# include /* Linux 2.4 */ -#else -# define PROC_SUPER_MAGIC 0x9fa0 -#endif - -#include -#include /* INT_MAX in ip_tables.h/ip6_tables.h */ -#include -#include -#include - -#ifndef NO_SHARED_LIBS -#include -#endif -#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */ -# define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) -# define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) -#endif -#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */ -# define IP6T_SO_GET_REVISION_MATCH 68 -# define IP6T_SO_GET_REVISION_TARGET 69 -#endif -#include -#include "iptables/internal.h" -#include "xshared.h" - -#define NPROTO 255 - -#ifndef PROC_SYS_MODPROBE -#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" -#endif - -/* we need this for ip6?tables-restore. ip6?tables-restore.c sets line to the - * current line of the input file, in order to give a more precise error - * message. ip6?tables itself doesn't need this, so it is initialized to the - * magic number of -1 */ -int line = -1; - -void basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); - -struct xtables_globals *xt_params = NULL; - -void basic_exit_err(enum xtables_exittype status, const char *msg, ...) -{ - va_list args; - - va_start(args, msg); - fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version); - vfprintf(stderr, msg, args); - va_end(args); - fprintf(stderr, "\n"); - exit(status); -} - -void xtables_free_opts(int unused) -{ - if (xt_params->opts != xt_params->orig_opts) { - free(xt_params->opts); - xt_params->opts = NULL; - } -} - -struct option *xtables_merge_options(struct option *orig_opts, - struct option *oldopts, - const struct option *newopts, - unsigned int *option_offset) -{ - unsigned int num_oold = 0, num_old = 0, num_new = 0, i; - struct option *merge, *mp; - - if (newopts == NULL) - return oldopts; - - for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ; - if (oldopts != NULL) - for (num_old = 0; oldopts[num_old].name; num_old++) ; - for (num_new = 0; newopts[num_new].name; num_new++) ; - - /* - * Since @oldopts also has @orig_opts already (and does so at the - * start), skip these entries. - */ - oldopts += num_oold; - num_old -= num_oold; - - merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1)); - if (merge == NULL) - return NULL; - - /* Let the base options -[ADI...] have precedence over everything */ - memcpy(merge, orig_opts, sizeof(*mp) * num_oold); - mp = merge + num_oold; - - /* Second, the new options */ - xt_params->option_offset += XT_OPTION_OFFSET_SCALE; - *option_offset = xt_params->option_offset; - memcpy(mp, newopts, sizeof(*mp) * num_new); - - for (i = 0; i < num_new; ++i, ++mp) - mp->val += *option_offset; - - /* Third, the old options */ - memcpy(mp, oldopts, sizeof(*mp) * num_old); - mp += num_old; - xtables_free_opts(0); - - /* Clear trailing entry */ - memset(mp, 0, sizeof(*mp)); - return merge; -} - -static const struct xtables_afinfo afinfo_ipv4 = { - .kmod = "ip_tables", - .proc_exists = "/proc/net/ip_tables_names", - .libprefix = "libipt_", - .family = NFPROTO_IPV4, - .ipproto = IPPROTO_IP, - .so_rev_match = IPT_SO_GET_REVISION_MATCH, - .so_rev_target = IPT_SO_GET_REVISION_TARGET, -}; - -static const struct xtables_afinfo afinfo_ipv6 = { - .kmod = "ip6_tables", - .proc_exists = "/proc/net/ip6_tables_names", - .libprefix = "libip6t_", - .family = NFPROTO_IPV6, - .ipproto = IPPROTO_IPV6, - .so_rev_match = IP6T_SO_GET_REVISION_MATCH, - .so_rev_target = IP6T_SO_GET_REVISION_TARGET, -}; - -const struct xtables_afinfo *afinfo; - -/* Search path for Xtables .so files */ -static const char *xtables_libdir; - -/* the path to command to load kernel module */ -const char *xtables_modprobe_program; - -/* Keep track of matches/targets pending full registration: linked lists. */ -struct xtables_match *xtables_pending_matches; -struct xtables_target *xtables_pending_targets; - -/* Keep track of fully registered external matches/targets: linked lists. */ -struct xtables_match *xtables_matches; -struct xtables_target *xtables_targets; - -/* Fully register a match/target which was previously partially registered. */ -static void xtables_fully_register_pending_match(struct xtables_match *me); -static void xtables_fully_register_pending_target(struct xtables_target *me); - -void xtables_init(void) -{ - xtables_libdir = getenv("XTABLES_LIBDIR"); - if (xtables_libdir != NULL) - return; - xtables_libdir = getenv("IPTABLES_LIB_DIR"); - if (xtables_libdir != NULL) { - fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " - "use XTABLES_LIBDIR.\n"); - return; - } - /* - * Well yes, IP6TABLES_LIB_DIR is of lower priority over - * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok - * for these env vars are deprecated anyhow, and in light of the - * (shared) libxt_*.so files, makes less sense to have - * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. - */ - xtables_libdir = getenv("IP6TABLES_LIB_DIR"); - if (xtables_libdir != NULL) { - fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " - "use XTABLES_LIBDIR.\n"); - return; - } - xtables_libdir = XTABLES_LIBDIR; -} - -void xtables_set_nfproto(uint8_t nfproto) -{ - switch (nfproto) { - case NFPROTO_IPV4: - afinfo = &afinfo_ipv4; - break; - case NFPROTO_IPV6: - afinfo = &afinfo_ipv6; - break; - default: - fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", - __func__); - } -} - -/** - * xtables_set_params - set the global parameters used by xtables - * @xtp: input xtables_globals structure - * - * The app is expected to pass a valid xtables_globals data-filled - * with proper values - * @xtp cannot be NULL - * - * Returns -1 on failure to set and 0 on success - */ -int xtables_set_params(struct xtables_globals *xtp) -{ - if (!xtp) { - fprintf(stderr, "%s: Illegal global params\n",__func__); - return -1; - } - - xt_params = xtp; - - if (!xt_params->exit_err) - xt_params->exit_err = basic_exit_err; - - return 0; -} - -int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) -{ - xtables_init(); - xtables_set_nfproto(nfproto); - return xtables_set_params(xtp); -} - -/** - * xtables_*alloc - wrappers that exit on failure - */ -void *xtables_calloc(size_t count, size_t size) -{ - void *p; - - if ((p = calloc(count, size)) == NULL) { - perror("ip[6]tables: calloc failed"); - exit(1); - } - - return p; -} - -void *xtables_malloc(size_t size) -{ - void *p; - - if ((p = malloc(size)) == NULL) { - perror("ip[6]tables: malloc failed"); - exit(1); - } - - return p; -} - -void *xtables_realloc(void *ptr, size_t size) -{ - void *p; - - if ((p = realloc(ptr, size)) == NULL) { - perror("ip[6]tables: realloc failed"); - exit(1); - } - - return p; -} - -static char *get_modprobe(void) -{ - int procfile; - char *ret; - -#define PROCFILE_BUFSIZ 1024 - procfile = open(PROC_SYS_MODPROBE, O_RDONLY); - if (procfile < 0) - return NULL; - if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) { - fprintf(stderr, "Could not set close on exec: %s\n", - strerror(errno)); - exit(1); - } - - ret = malloc(PROCFILE_BUFSIZ); - if (ret) { - memset(ret, 0, PROCFILE_BUFSIZ); - switch (read(procfile, ret, PROCFILE_BUFSIZ)) { - case -1: goto fail; - case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ - } - if (ret[strlen(ret)-1]=='\n') - ret[strlen(ret)-1]=0; - close(procfile); - return ret; - } - fail: - free(ret); - close(procfile); - return NULL; -} - -int xtables_insmod(const char *modname, const char *modprobe, bool quiet) -{ - char *buf = NULL; - char *argv[4]; - int status; - - /* If they don't explicitly set it, read out of kernel */ - if (!modprobe) { - buf = get_modprobe(); - if (!buf) - return -1; - modprobe = buf; - } - - /* - * Need to flush the buffer, or the child may output it again - * when switching the program thru execv. - */ - fflush(stdout); - - switch (vfork()) { - case 0: - argv[0] = (char *)modprobe; - argv[1] = (char *)modname; - if (quiet) { - argv[2] = "-q"; - argv[3] = NULL; - } else { - argv[2] = NULL; - argv[3] = NULL; - } - execv(argv[0], argv); - - /* not usually reached */ - exit(1); - case -1: - free(buf); - return -1; - - default: /* parent */ - wait(&status); - } - - free(buf); - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) - return 0; - return -1; -} - -/* return true if a given file exists within procfs */ -static bool proc_file_exists(const char *filename) -{ - struct stat s; - struct statfs f; - - if (lstat(filename, &s)) - return false; - if (!S_ISREG(s.st_mode)) - return false; - if (statfs(filename, &f)) - return false; - if (f.f_type != PROC_SUPER_MAGIC) - return false; - return true; -} - -int xtables_load_ko(const char *modprobe, bool quiet) -{ - static bool loaded = false; - int ret; - - if (loaded) - return 0; - - if (proc_file_exists(afinfo->proc_exists)) { - loaded = true; - return 0; - }; - - ret = xtables_insmod(afinfo->kmod, modprobe, quiet); - if (ret == 0) - loaded = true; - - return ret; -} - -/** - * xtables_strtou{i,l} - string to number conversion - * @s: input string - * @end: like strtoul's "end" pointer - * @value: pointer for result - * @min: minimum accepted value - * @max: maximum accepted value - * - * If @end is NULL, we assume the caller wants a "strict strtoul", and hence - * "15a" is rejected. - * In either case, the value obtained is compared for min-max compliance. - * Base is always 0, i.e. autodetect depending on @s. - * - * Returns true/false whether number was accepted. On failure, *value has - * undefined contents. - */ -bool xtables_strtoul(const char *s, char **end, uintmax_t *value, - uintmax_t min, uintmax_t max) -{ - uintmax_t v; - const char *p; - char *my_end; - - errno = 0; - /* Since strtoul allows leading minus, we have to check for ourself. */ - for (p = s; isspace(*p); ++p) - ; - if (*p == '-') - return false; - v = strtoumax(s, &my_end, 0); - if (my_end == s) - return false; - if (end != NULL) - *end = my_end; - - if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { - if (value != NULL) - *value = v; - if (end == NULL) - return *my_end == '\0'; - return true; - } - - return false; -} - -bool xtables_strtoui(const char *s, char **end, unsigned int *value, - unsigned int min, unsigned int max) -{ - uintmax_t v; - bool ret; - - ret = xtables_strtoul(s, end, &v, min, max); - if (value != NULL) - *value = v; - return ret; -} - -int xtables_service_to_port(const char *name, const char *proto) -{ - struct servent *service; - - if ((service = getservbyname(name, proto)) != NULL) - return ntohs((unsigned short) service->s_port); - - return -1; -} - -uint16_t xtables_parse_port(const char *port, const char *proto) -{ - unsigned int portnum; - - if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || - (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) - return portnum; - - xt_params->exit_err(PARAMETER_PROBLEM, - "invalid port/service `%s' specified", port); -} - -void xtables_parse_interface(const char *arg, char *vianame, - unsigned char *mask) -{ - unsigned int vialen = strlen(arg); - unsigned int i; - - memset(mask, 0, IFNAMSIZ); - memset(vianame, 0, IFNAMSIZ); - - if (vialen + 1 > IFNAMSIZ) - xt_params->exit_err(PARAMETER_PROBLEM, - "interface name `%s' must be shorter than IFNAMSIZ" - " (%i)", arg, IFNAMSIZ-1); - - strcpy(vianame, arg); - if (vialen == 0) - return; - else if (vianame[vialen - 1] == '+') { - memset(mask, 0xFF, vialen - 1); - /* Don't remove `+' here! -HW */ - } else { - /* Include nul-terminator in match */ - memset(mask, 0xFF, vialen + 1); - for (i = 0; vianame[i]; i++) { - if (vianame[i] == '/' || - vianame[i] == ' ') { - fprintf(stderr, - "Warning: weird character in interface" - " `%s' ('/' and ' ' are not allowed by the kernel).\n", - vianame); - break; - } - } - } -} - -#ifndef NO_SHARED_LIBS -static void *load_extension(const char *search_path, const char *af_prefix, - const char *name, bool is_target) -{ - const char *all_prefixes[] = {"libxt_", af_prefix, NULL}; - const char **prefix; - const char *dir = search_path, *next; - void *ptr = NULL; - struct stat sb; - char path[256]; - - do { - next = strchr(dir, ':'); - if (next == NULL) - next = dir + strlen(dir); - - for (prefix = all_prefixes; *prefix != NULL; ++prefix) { - snprintf(path, sizeof(path), "%.*s/%s%s.so", - (unsigned int)(next - dir), dir, - *prefix, name); - - if (stat(path, &sb) != 0) { - if (errno == ENOENT) - continue; - fprintf(stderr, "%s: %s\n", path, - strerror(errno)); - return NULL; - } - if (dlopen(path, RTLD_NOW) == NULL) { - fprintf(stderr, "%s: %s\n", path, dlerror()); - break; - } - - if (is_target) - ptr = xtables_find_target(name, XTF_DONT_LOAD); - else - ptr = xtables_find_match(name, - XTF_DONT_LOAD, NULL); - - if (ptr != NULL) - return ptr; - - fprintf(stderr, "%s: no \"%s\" extension found for " - "this protocol\n", path, name); - errno = ENOENT; - return NULL; - } - dir = next + 1; - } while (*next != '\0'); - - return NULL; -} -#endif - -struct xtables_match * -xtables_find_match(const char *name, enum xtables_tryload tryload, - struct xtables_rule_match **matches) -{ - struct xtables_match **dptr; - struct xtables_match *ptr; - const char *icmp6 = "icmp6"; - - if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) - xtables_error(PARAMETER_PROBLEM, - "Invalid match name \"%s\" (%u chars max)", - name, XT_EXTENSION_MAXNAMELEN - 1); - - /* This is ugly as hell. Nonetheless, there is no way of changing - * this without hurting backwards compatibility */ - if ( (strcmp(name,"icmpv6") == 0) || - (strcmp(name,"ipv6-icmp") == 0) || - (strcmp(name,"icmp6") == 0) ) - name = icmp6; - - /* Trigger delayed initialization */ - for (dptr = &xtables_pending_matches; *dptr; ) { - if (strcmp(name, (*dptr)->name) == 0) { - ptr = *dptr; - *dptr = (*dptr)->next; - ptr->next = NULL; - xtables_fully_register_pending_match(ptr); - } else { - dptr = &((*dptr)->next); - } - } - - for (ptr = xtables_matches; ptr; ptr = ptr->next) { - if (strcmp(name, ptr->name) == 0) { - struct xtables_match *clone; - - /* First match of this type: */ - if (ptr->m == NULL) - break; - - /* Second and subsequent clones */ - clone = xtables_malloc(sizeof(struct xtables_match)); - memcpy(clone, ptr, sizeof(struct xtables_match)); - clone->udata = NULL; - clone->mflags = 0; - /* This is a clone: */ - clone->next = clone; - - ptr = clone; - break; - } - } - -#ifndef NO_SHARED_LIBS - if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { - ptr = load_extension(xtables_libdir, afinfo->libprefix, - name, false); - - if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) - xt_params->exit_err(PARAMETER_PROBLEM, - "Couldn't load match `%s':%s\n", - name, strerror(errno)); - } -#else - if (ptr && !ptr->loaded) { - if (tryload != XTF_DONT_LOAD) - ptr->loaded = 1; - else - ptr = NULL; - } - if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { - xt_params->exit_err(PARAMETER_PROBLEM, - "Couldn't find match `%s'\n", name); - } -#endif - - if (ptr && matches) { - struct xtables_rule_match **i; - struct xtables_rule_match *newentry; - - newentry = xtables_malloc(sizeof(struct xtables_rule_match)); - - for (i = matches; *i; i = &(*i)->next) { - if (strcmp(name, (*i)->match->name) == 0) - (*i)->completed = true; - } - newentry->match = ptr; - newentry->completed = false; - newentry->next = NULL; - *i = newentry; - } - - return ptr; -} - -struct xtables_target * -xtables_find_target(const char *name, enum xtables_tryload tryload) -{ - struct xtables_target **dptr; - struct xtables_target *ptr; - - /* Standard target? */ - if (strcmp(name, "") == 0 - || strcmp(name, XTC_LABEL_ACCEPT) == 0 - || strcmp(name, XTC_LABEL_DROP) == 0 - || strcmp(name, XTC_LABEL_QUEUE) == 0 - || strcmp(name, XTC_LABEL_RETURN) == 0) - name = "standard"; - - /* Trigger delayed initialization */ - for (dptr = &xtables_pending_targets; *dptr; ) { - if (strcmp(name, (*dptr)->name) == 0) { - ptr = *dptr; - *dptr = (*dptr)->next; - ptr->next = NULL; - xtables_fully_register_pending_target(ptr); - } else { - dptr = &((*dptr)->next); - } - } - - for (ptr = xtables_targets; ptr; ptr = ptr->next) { - if (strcmp(name, ptr->name) == 0) - break; - } - -#ifndef NO_SHARED_LIBS - if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { - ptr = load_extension(xtables_libdir, afinfo->libprefix, - name, true); - - if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) - xt_params->exit_err(PARAMETER_PROBLEM, - "Couldn't load target `%s':%s\n", - name, strerror(errno)); - } -#else - if (ptr && !ptr->loaded) { - if (tryload != XTF_DONT_LOAD) - ptr->loaded = 1; - else - ptr = NULL; - } - if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) { - xt_params->exit_err(PARAMETER_PROBLEM, - "Couldn't find target `%s'\n", name); - } -#endif - - if (ptr) - ptr->used = 1; - - return ptr; -} - -static int compatible_revision(const char *name, uint8_t revision, int opt) -{ - struct xt_get_revision rev; - socklen_t s = sizeof(rev); - int max_rev, sockfd; - - sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); - if (sockfd < 0) { - if (errno == EPERM) { - /* revision 0 is always supported. */ - if (revision != 0) - fprintf(stderr, "%s: Could not determine whether " - "revision %u is supported, " - "assuming it is.\n", - name, revision); - return 1; - } - fprintf(stderr, "Could not open socket to kernel: %s\n", - strerror(errno)); - exit(1); - } - - if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { - fprintf(stderr, "Could not set close on exec: %s\n", - strerror(errno)); - exit(1); - } - - xtables_load_ko(xtables_modprobe_program, true); - - strcpy(rev.name, name); - rev.revision = revision; - - max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); - if (max_rev < 0) { - /* Definitely don't support this? */ - if (errno == ENOENT || errno == EPROTONOSUPPORT) { - close(sockfd); - return 0; - } else if (errno == ENOPROTOOPT) { - close(sockfd); - /* Assume only revision 0 support (old kernel) */ - return (revision == 0); - } else { - fprintf(stderr, "getsockopt failed strangely: %s\n", - strerror(errno)); - exit(1); - } - } - close(sockfd); - return 1; -} - - -static int compatible_match_revision(const char *name, uint8_t revision) -{ - return compatible_revision(name, revision, afinfo->so_rev_match); -} - -static int compatible_target_revision(const char *name, uint8_t revision) -{ - return compatible_revision(name, revision, afinfo->so_rev_target); -} - -static void xtables_check_options(const char *name, const struct option *opt) -{ - for (; opt->name != NULL; ++opt) - if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) { - fprintf(stderr, "%s: Extension %s uses invalid " - "option value %d\n",xt_params->program_name, - name, opt->val); - exit(1); - } -} - -void xtables_register_match(struct xtables_match *me) -{ - if (me->version == NULL) { - fprintf(stderr, "%s: match %s<%u> is missing a version\n", - xt_params->program_name, me->name, me->revision); - exit(1); - } - if (strcmp(me->version, XTABLES_VERSION) != 0) { - fprintf(stderr, "%s: match \"%s\" has version \"%s\", " - "but \"%s\" is required.\n", - xt_params->program_name, me->name, - me->version, XTABLES_VERSION); - exit(1); - } - - if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { - fprintf(stderr, "%s: match `%s' has invalid name\n", - xt_params->program_name, me->name); - exit(1); - } - - if (me->family >= NPROTO) { - fprintf(stderr, - "%s: BUG: match %s has invalid protocol family\n", - xt_params->program_name, me->name); - exit(1); - } - - if (me->x6_options != NULL) - xtables_option_metavalidate(me->name, me->x6_options); - if (me->extra_opts != NULL) - xtables_check_options(me->name, me->extra_opts); - - /* ignore not interested match */ - if (me->family != afinfo->family && me->family != AF_UNSPEC) - return; - - /* place on linked list of matches pending full registration */ - me->next = xtables_pending_matches; - xtables_pending_matches = me; -} - -static void xtables_fully_register_pending_match(struct xtables_match *me) -{ - struct xtables_match **i, *old; - - old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); - if (old) { - if (old->revision == me->revision && - old->family == me->family) { - fprintf(stderr, - "%s: match `%s' already registered.\n", - xt_params->program_name, me->name); - exit(1); - } - - /* Now we have two (or more) options, check compatibility. */ - if (compatible_match_revision(old->name, old->revision) - && old->revision > me->revision) - return; - - /* See if new match can be used. */ - if (!compatible_match_revision(me->name, me->revision)) - return; - - /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ - if (old->revision == me->revision && me->family == AF_UNSPEC) - return; - - /* Delete old one. */ - for (i = &xtables_matches; *i!=old; i = &(*i)->next); - *i = old->next; - } - - if (me->size != XT_ALIGN(me->size)) { - fprintf(stderr, "%s: match `%s' has invalid size %u.\n", - xt_params->program_name, me->name, - (unsigned int)me->size); - exit(1); - } - - /* Append to list. */ - for (i = &xtables_matches; *i; i = &(*i)->next); - me->next = NULL; - *i = me; - - me->m = NULL; - me->mflags = 0; -} - -void xtables_register_matches(struct xtables_match *match, unsigned int n) -{ - do { - xtables_register_match(&match[--n]); - } while (n > 0); -} - -void xtables_register_target(struct xtables_target *me) -{ - if (me->version == NULL) { - fprintf(stderr, "%s: target %s<%u> is missing a version\n", - xt_params->program_name, me->name, me->revision); - exit(1); - } - if (strcmp(me->version, XTABLES_VERSION) != 0) { - fprintf(stderr, "%s: target \"%s\" has version \"%s\", " - "but \"%s\" is required.\n", - xt_params->program_name, me->name, - me->version, XTABLES_VERSION); - exit(1); - } - - if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { - fprintf(stderr, "%s: target `%s' has invalid name\n", - xt_params->program_name, me->name); - exit(1); - } - - if (me->family >= NPROTO) { - fprintf(stderr, - "%s: BUG: target %s has invalid protocol family\n", - xt_params->program_name, me->name); - exit(1); - } - - if (me->x6_options != NULL) - xtables_option_metavalidate(me->name, me->x6_options); - if (me->extra_opts != NULL) - xtables_check_options(me->name, me->extra_opts); - - /* ignore not interested target */ - if (me->family != afinfo->family && me->family != AF_UNSPEC) - return; - - /* place on linked list of targets pending full registration */ - me->next = xtables_pending_targets; - xtables_pending_targets = me; -} - -static void xtables_fully_register_pending_target(struct xtables_target *me) -{ - struct xtables_target *old; - - old = xtables_find_target(me->name, XTF_DURING_LOAD); - if (old) { - struct xtables_target **i; - - if (old->revision == me->revision && - old->family == me->family) { - fprintf(stderr, - "%s: target `%s' already registered.\n", - xt_params->program_name, me->name); - exit(1); - } - - /* Now we have two (or more) options, check compatibility. */ - if (compatible_target_revision(old->name, old->revision) - && old->revision > me->revision) - return; - - /* See if new target can be used. */ - if (!compatible_target_revision(me->name, me->revision)) - return; - - /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ - if (old->revision == me->revision && me->family == AF_UNSPEC) - return; - - /* Delete old one. */ - for (i = &xtables_targets; *i!=old; i = &(*i)->next); - *i = old->next; - } - - if (me->size != XT_ALIGN(me->size)) { - fprintf(stderr, "%s: target `%s' has invalid size %u.\n", - xt_params->program_name, me->name, - (unsigned int)me->size); - exit(1); - } - - /* Prepend to list. */ - me->next = xtables_targets; - xtables_targets = me; - me->t = NULL; - me->tflags = 0; -} - -void xtables_register_targets(struct xtables_target *target, unsigned int n) -{ - do { - xtables_register_target(&target[--n]); - } while (n > 0); -} - -/** - * xtables_param_act - act on condition - * @status: a constant from enum xtables_exittype - * - * %XTF_ONLY_ONCE: print error message that option may only be used once. - * @p1: module name (e.g. "mark") - * @p2(...): option in conflict (e.g. "--mark") - * @p3(...): condition to match on (see extensions/ for examples) - * - * %XTF_NO_INVERT: option does not support inversion - * @p1: module name - * @p2: option in conflict - * @p3: condition to match on - * - * %XTF_BAD_VALUE: bad value for option - * @p1: module name - * @p2: option with which the problem occured (e.g. "--mark") - * @p3: string the user passed in (e.g. "99999999999999") - * - * %XTF_ONE_ACTION: two mutually exclusive actions have been specified - * @p1: module name - * - * Displays an error message and exits the program. - */ -void xtables_param_act(unsigned int status, const char *p1, ...) -{ - const char *p2, *p3; - va_list args; - bool b; - - va_start(args, p1); - - switch (status) { - case XTF_ONLY_ONCE: - p2 = va_arg(args, const char *); - b = va_arg(args, unsigned int); - if (!b) { - va_end(args); - return; - } - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: \"%s\" option may only be specified once", - p1, p2); - break; - case XTF_NO_INVERT: - p2 = va_arg(args, const char *); - b = va_arg(args, unsigned int); - if (!b) { - va_end(args); - return; - } - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: \"%s\" option cannot be inverted", p1, p2); - break; - case XTF_BAD_VALUE: - p2 = va_arg(args, const char *); - p3 = va_arg(args, const char *); - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: Bad value for \"%s\" option: \"%s\"", - p1, p2, p3); - break; - case XTF_ONE_ACTION: - b = va_arg(args, unsigned int); - if (!b) { - va_end(args); - return; - } - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: At most one action is possible", p1); - break; - default: - xt_params->exit_err(status, p1, args); - break; - } - - va_end(args); -} - -const char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) -{ - static char buf[20]; - const unsigned char *bytep = (const void *)&addrp->s_addr; - - sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); - return buf; -} - -static const char *ipaddr_to_host(const struct in_addr *addr) -{ - struct hostent *host; - - host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); - if (host == NULL) - return NULL; - - return host->h_name; -} - -static const char *ipaddr_to_network(const struct in_addr *addr) -{ - struct netent *net; - - if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) - return net->n_name; - - return NULL; -} - -const char *xtables_ipaddr_to_anyname(const struct in_addr *addr) -{ - const char *name; - - if ((name = ipaddr_to_host(addr)) != NULL || - (name = ipaddr_to_network(addr)) != NULL) - return name; - - return xtables_ipaddr_to_numeric(addr); -} - -const char *xtables_ipmask_to_numeric(const struct in_addr *mask) -{ - static char buf[20]; - uint32_t maskaddr, bits; - int i; - - maskaddr = ntohl(mask->s_addr); - - if (maskaddr == 0xFFFFFFFFL) - /* we don't want to see "/32" */ - return ""; - - i = 32; - bits = 0xFFFFFFFEL; - while (--i >= 0 && maskaddr != bits) - bits <<= 1; - if (i >= 0) - sprintf(buf, "/%d", i); - else - /* mask was not a decent combination of 1's and 0's */ - sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); - - return buf; -} - -static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) -{ - static struct in_addr addr; - unsigned char *addrp; - unsigned int onebyte; - char buf[20], *p, *q; - int i; - - /* copy dotted string, because we need to modify it */ - strncpy(buf, dotted, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; - addrp = (void *)&addr.s_addr; - - p = buf; - for (i = 0; i < 3; ++i) { - if ((q = strchr(p, '.')) == NULL) { - if (is_mask) - return NULL; - - /* autocomplete, this is a network address */ - if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) - return NULL; - - addrp[i] = onebyte; - while (i < 3) - addrp[++i] = 0; - - return &addr; - } - - *q = '\0'; - if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) - return NULL; - - addrp[i] = onebyte; - p = q + 1; - } - - /* we have checked 3 bytes, now we check the last one */ - if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) - return NULL; - - addrp[3] = onebyte; - return &addr; -} - -struct in_addr *xtables_numeric_to_ipaddr(const char *dotted) -{ - return __numeric_to_ipaddr(dotted, false); -} - -struct in_addr *xtables_numeric_to_ipmask(const char *dotted) -{ - return __numeric_to_ipaddr(dotted, true); -} - -static struct in_addr *network_to_ipaddr(const char *name) -{ - static struct in_addr addr; - struct netent *net; - - if ((net = getnetbyname(name)) != NULL) { - if (net->n_addrtype != AF_INET) - return NULL; - addr.s_addr = htonl(net->n_net); - return &addr; - } - - return NULL; -} - -static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) -{ - struct hostent *host; - struct in_addr *addr; - unsigned int i; - - *naddr = 0; - if ((host = gethostbyname(name)) != NULL) { - if (host->h_addrtype != AF_INET || - host->h_length != sizeof(struct in_addr)) - return NULL; - - while (host->h_addr_list[*naddr] != NULL) - ++*naddr; - addr = xtables_calloc(*naddr, sizeof(struct in_addr)); - for (i = 0; i < *naddr; i++) - memcpy(&addr[i], host->h_addr_list[i], - sizeof(struct in_addr)); - return addr; - } - - return NULL; -} - -static struct in_addr * -ipparse_hostnetwork(const char *name, unsigned int *naddrs) -{ - struct in_addr *addrptmp, *addrp; - - if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || - (addrptmp = network_to_ipaddr(name)) != NULL) { - addrp = xtables_malloc(sizeof(struct in_addr)); - memcpy(addrp, addrptmp, sizeof(*addrp)); - *naddrs = 1; - return addrp; - } - if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) - return addrptmp; - - xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); -} - -static struct in_addr *parse_ipmask(const char *mask) -{ - static struct in_addr maskaddr; - struct in_addr *addrp; - unsigned int bits; - - if (mask == NULL) { - /* no mask at all defaults to 32 bits */ - maskaddr.s_addr = 0xFFFFFFFF; - return &maskaddr; - } - if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) - /* dotted_to_addr already returns a network byte order addr */ - return addrp; - if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) - xt_params->exit_err(PARAMETER_PROBLEM, - "invalid mask `%s' specified", mask); - if (bits != 0) { - maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); - return &maskaddr; - } - - maskaddr.s_addr = 0U; - return &maskaddr; -} - -void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, - struct in_addr **maskpp, unsigned int *naddrs) -{ - struct in_addr *addrp; - char buf[256], *p, *next; - unsigned int len, i, j, n, count = 1; - const char *loop = name; - - while ((loop = strchr(loop, ',')) != NULL) { - ++count; - ++loop; /* skip ',' */ - } - - *addrpp = xtables_malloc(sizeof(struct in_addr) * count); - *maskpp = xtables_malloc(sizeof(struct in_addr) * count); - - loop = name; - - for (i = 0; i < count; ++i) { - while (isspace(*loop)) - ++loop; - next = strchr(loop, ','); - if (next != NULL) - len = next - loop; - else - len = strlen(loop); - if (len > sizeof(buf) - 1) - xt_params->exit_err(PARAMETER_PROBLEM, - "Hostname too long"); - - strncpy(buf, loop, len); - buf[len] = '\0'; - if ((p = strrchr(buf, '/')) != NULL) { - *p = '\0'; - addrp = parse_ipmask(p + 1); - } else { - addrp = parse_ipmask(NULL); - } - memcpy(*maskpp + i, addrp, sizeof(*addrp)); - - /* if a null mask is given, the name is ignored, like in "any/0" */ - if ((*maskpp + i)->s_addr == 0) - /* - * A bit pointless to process multiple addresses - * in this case... - */ - strcpy(buf, "0.0.0.0"); - - addrp = ipparse_hostnetwork(buf, &n); - if (n > 1) { - count += n - 1; - *addrpp = xtables_realloc(*addrpp, - sizeof(struct in_addr) * count); - *maskpp = xtables_realloc(*maskpp, - sizeof(struct in_addr) * count); - for (j = 0; j < n; ++j) - /* for each new addr */ - memcpy(*addrpp + i + j, addrp + j, - sizeof(*addrp)); - for (j = 1; j < n; ++j) - /* for each new mask */ - memcpy(*maskpp + i + j, *maskpp + i, - sizeof(*addrp)); - i += n - 1; - } else { - memcpy(*addrpp + i, addrp, sizeof(*addrp)); - } - /* free what ipparse_hostnetwork had allocated: */ - free(addrp); - if (next == NULL) - break; - loop = next + 1; - } - *naddrs = count; - for (i = 0; i < count; ++i) - (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr; -} - - -/** - * xtables_ipparse_any - transform arbitrary name to in_addr - * - * Possible inputs (pseudo regex): - * m{^($hostname|$networkname|$ipaddr)(/$mask)?} - * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" - */ -void xtables_ipparse_any(const char *name, struct in_addr **addrpp, - struct in_addr *maskp, unsigned int *naddrs) -{ - unsigned int i, j, k, n; - struct in_addr *addrp; - char buf[256], *p; - - strncpy(buf, name, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; - if ((p = strrchr(buf, '/')) != NULL) { - *p = '\0'; - addrp = parse_ipmask(p + 1); - } else { - addrp = parse_ipmask(NULL); - } - memcpy(maskp, addrp, sizeof(*maskp)); - - /* if a null mask is given, the name is ignored, like in "any/0" */ - if (maskp->s_addr == 0U) - strcpy(buf, "0.0.0.0"); - - addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); - n = *naddrs; - for (i = 0, j = 0; i < n; ++i) { - addrp[j++].s_addr &= maskp->s_addr; - for (k = 0; k < j - 1; ++k) - if (addrp[k].s_addr == addrp[j-1].s_addr) { - /* - * Nuke the dup by copying an address from the - * tail here, and check the current position - * again (--j). - */ - memcpy(&addrp[--j], &addrp[--*naddrs], - sizeof(struct in_addr)); - break; - } - } -} - -const char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) -{ - /* 0000:0000:0000:0000:0000:0000:000.000.000.000 - * 0000:0000:0000:0000:0000:0000:0000:0000 */ - static char buf[50+1]; - return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); -} - -static const char *ip6addr_to_host(const struct in6_addr *addr) -{ - static char hostname[NI_MAXHOST]; - struct sockaddr_in6 saddr; - int err; - - memset(&saddr, 0, sizeof(struct sockaddr_in6)); - memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); - saddr.sin6_family = AF_INET6; - - err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), - hostname, sizeof(hostname) - 1, NULL, 0, 0); - if (err != 0) { -#ifdef DEBUG - fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); -#endif - return NULL; - } - -#ifdef DEBUG - fprintf (stderr, "\naddr2host: %s\n", hostname); -#endif - return hostname; -} - -const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) -{ - const char *name; - - if ((name = ip6addr_to_host(addr)) != NULL) - return name; - - return xtables_ip6addr_to_numeric(addr); -} - -static int ip6addr_prefix_length(const struct in6_addr *k) -{ - unsigned int bits = 0; - uint32_t a, b, c, d; - - a = ntohl(k->s6_addr32[0]); - b = ntohl(k->s6_addr32[1]); - c = ntohl(k->s6_addr32[2]); - d = ntohl(k->s6_addr32[3]); - while (a & 0x80000000U) { - ++bits; - a <<= 1; - a |= (b >> 31) & 1; - b <<= 1; - b |= (c >> 31) & 1; - c <<= 1; - c |= (d >> 31) & 1; - d <<= 1; - } - if (a != 0 || b != 0 || c != 0 || d != 0) - return -1; - return bits; -} - -const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) -{ - static char buf[50+2]; - int l = ip6addr_prefix_length(addrp); - - if (l == -1) { - strcpy(buf, "/"); - strcat(buf, xtables_ip6addr_to_numeric(addrp)); - return buf; - } - sprintf(buf, "/%d", l); - return buf; -} - -struct in6_addr *xtables_numeric_to_ip6addr(const char *num) -{ - static struct in6_addr ap; - int err; - - if ((err = inet_pton(AF_INET6, num, &ap)) == 1) - return ≈ -#ifdef DEBUG - fprintf(stderr, "\nnumeric2addr: %d\n", err); -#endif - return NULL; -} - -static struct in6_addr * -host_to_ip6addr(const char *name, unsigned int *naddr) -{ - struct in6_addr *addr; - struct addrinfo hints; - struct addrinfo *res, *p; - int err; - unsigned int i; - - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_RAW; - - *naddr = 0; - if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { -#ifdef DEBUG - fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); -#endif - return NULL; - } else { - /* Find length of address chain */ - for (p = res; p != NULL; p = p->ai_next) - ++*naddr; -#ifdef DEBUG - fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, - xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); -#endif - /* Copy each element of the address chain */ - addr = xtables_calloc(*naddr, sizeof(struct in6_addr)); - for (i = 0, p = res; p != NULL; p = p->ai_next) - memcpy(&addr[i++], - &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr, - sizeof(struct in6_addr)); - freeaddrinfo(res); - return addr; - } - - return NULL; -} - -static struct in6_addr *network_to_ip6addr(const char *name) -{ - /* abort();*/ - /* TODO: not implemented yet, but the exception breaks the - * name resolvation */ - return NULL; -} - -static struct in6_addr * -ip6parse_hostnetwork(const char *name, unsigned int *naddrs) -{ - struct in6_addr *addrp, *addrptmp; - - if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || - (addrptmp = network_to_ip6addr(name)) != NULL) { - addrp = xtables_malloc(sizeof(struct in6_addr)); - memcpy(addrp, addrptmp, sizeof(*addrp)); - *naddrs = 1; - return addrp; - } - if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) - return addrp; - - xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); -} - -static struct in6_addr *parse_ip6mask(char *mask) -{ - static struct in6_addr maskaddr; - struct in6_addr *addrp; - unsigned int bits; - - if (mask == NULL) { - /* no mask at all defaults to 128 bits */ - memset(&maskaddr, 0xff, sizeof maskaddr); - return &maskaddr; - } - if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) - return addrp; - if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) - xt_params->exit_err(PARAMETER_PROBLEM, - "invalid mask `%s' specified", mask); - if (bits != 0) { - char *p = (void *)&maskaddr; - memset(p, 0xff, bits / 8); - memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); - p[bits/8] = 0xff << (8 - (bits & 7)); - return &maskaddr; - } - - memset(&maskaddr, 0, sizeof(maskaddr)); - return &maskaddr; -} - -void -xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, - struct in6_addr **maskpp, unsigned int *naddrs) -{ - static const struct in6_addr zero_addr; - struct in6_addr *addrp; - char buf[256], *p, *next; - unsigned int len, i, j, n, count = 1; - const char *loop = name; - - while ((loop = strchr(loop, ',')) != NULL) { - ++count; - ++loop; /* skip ',' */ - } - - *addrpp = xtables_malloc(sizeof(struct in6_addr) * count); - *maskpp = xtables_malloc(sizeof(struct in6_addr) * count); - - loop = name; - - for (i = 0; i < count /*NB: count can grow*/; ++i) { - while (isspace(*loop)) - ++loop; - next = strchr(loop, ','); - if (next != NULL) - len = next - loop; - else - len = strlen(loop); - if (len > sizeof(buf) - 1) - xt_params->exit_err(PARAMETER_PROBLEM, - "Hostname too long"); - - strncpy(buf, loop, len); - buf[len] = '\0'; - if ((p = strrchr(buf, '/')) != NULL) { - *p = '\0'; - addrp = parse_ip6mask(p + 1); - } else { - addrp = parse_ip6mask(NULL); - } - memcpy(*maskpp + i, addrp, sizeof(*addrp)); - - /* if a null mask is given, the name is ignored, like in "any/0" */ - if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0) - strcpy(buf, "::"); - - addrp = ip6parse_hostnetwork(buf, &n); - if (n > 1) { - count += n - 1; - *addrpp = xtables_realloc(*addrpp, - sizeof(struct in6_addr) * count); - *maskpp = xtables_realloc(*maskpp, - sizeof(struct in6_addr) * count); - for (j = 0; j < n; ++j) - /* for each new addr */ - memcpy(*addrpp + i + j, addrp + j, - sizeof(*addrp)); - for (j = 1; j < n; ++j) - /* for each new mask */ - memcpy(*maskpp + i + j, *maskpp + i, - sizeof(*addrp)); - i += n - 1; - } else { - memcpy(*addrpp + i, addrp, sizeof(*addrp)); - } - /* free what ip6parse_hostnetwork had allocated: */ - free(addrp); - if (next == NULL) - break; - loop = next + 1; - } - *naddrs = count; - for (i = 0; i < count; ++i) - for (j = 0; j < 4; ++j) - (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j]; -} - -void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, - struct in6_addr *maskp, unsigned int *naddrs) -{ - static const struct in6_addr zero_addr; - struct in6_addr *addrp; - unsigned int i, j, k, n; - char buf[256], *p; - - strncpy(buf, name, sizeof(buf) - 1); - buf[sizeof(buf)-1] = '\0'; - if ((p = strrchr(buf, '/')) != NULL) { - *p = '\0'; - addrp = parse_ip6mask(p + 1); - } else { - addrp = parse_ip6mask(NULL); - } - memcpy(maskp, addrp, sizeof(*maskp)); - - /* if a null mask is given, the name is ignored, like in "any/0" */ - if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0) - strcpy(buf, "::"); - - addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); - n = *naddrs; - for (i = 0, j = 0; i < n; ++i) { - for (k = 0; k < 4; ++k) - addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; - ++j; - for (k = 0; k < j - 1; ++k) - if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { - /* - * Nuke the dup by copying an address from the - * tail here, and check the current position - * again (--j). - */ - memcpy(&addrp[--j], &addrp[--*naddrs], - sizeof(struct in_addr)); - break; - } - } -} - -void xtables_save_string(const char *value) -{ - static const char no_quote_chars[] = "_-0123456789" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - static const char escape_chars[] = "\"\\'"; - size_t length; - const char *p; - - length = strspn(value, no_quote_chars); - if (length > 0 && value[length] == 0) { - /* no quoting required */ - putchar(' '); - fputs(value, stdout); - } else { - /* there is at least one dangerous character in the - value, which we have to quote. Write double quotes - around the value and escape special characters with - a backslash */ - printf(" \""); - - for (p = strpbrk(value, escape_chars); p != NULL; - p = strpbrk(value, escape_chars)) { - if (p > value) - fwrite(value, 1, p - value, stdout); - putchar('\\'); - putchar(*p); - value = p + 1; - } - - /* print the rest and finish the double quoted - string */ - fputs(value, stdout); - putchar('\"'); - } -} - -const struct xtables_pprot xtables_chain_protos[] = { - {"tcp", IPPROTO_TCP}, - {"sctp", IPPROTO_SCTP}, - {"udp", IPPROTO_UDP}, - {"udplite", IPPROTO_UDPLITE}, - {"icmp", IPPROTO_ICMP}, - {"icmpv6", IPPROTO_ICMPV6}, - {"ipv6-icmp", IPPROTO_ICMPV6}, - {"esp", IPPROTO_ESP}, - {"ah", IPPROTO_AH}, - {"ipv6-mh", IPPROTO_MH}, - {"mh", IPPROTO_MH}, - {"all", 0}, - {NULL}, -}; - -uint16_t -xtables_parse_protocol(const char *s) -{ - const struct protoent *pent; - unsigned int proto, i; - - if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) - return proto; - - /* first deal with the special case of 'all' to prevent - * people from being able to redefine 'all' in nsswitch - * and/or provoke expensive [not working] ldap/nis/... - * lookups */ - if (strcmp(s, "all") == 0) - return 0; - - pent = getprotobyname(s); - if (pent != NULL) - return pent->p_proto; - - for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { - if (xtables_chain_protos[i].name == NULL) - continue; - if (strcmp(s, xtables_chain_protos[i].name) == 0) - return xtables_chain_protos[i].num; - } - xt_params->exit_err(PARAMETER_PROBLEM, - "unknown protocol \"%s\" specified", s); - return -1; -} - -int kernel_version; - -void get_kernel_version(void) -{ - static struct utsname uts; - int x = 0, y = 0, z = 0; - - if (uname(&uts) == -1) { - fprintf(stderr, "Unable to retrieve kernel version.\n"); - xtables_free_opts(1); - exit(1); - } - - sscanf(uts.release, "%d.%d.%d", &x, &y, &z); - kernel_version = LINUX_VERSION(x, y, z); -} diff --git a/iptables/xtoptions.c b/iptables/xtoptions.c deleted file mode 100644 index 5f617a42..00000000 --- a/iptables/xtoptions.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* - * Argument parser - * Copyright © Jan Engelhardt, 2011 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "xtables.h" -#include "xshared.h" -#ifndef IPTOS_NORMALSVC -# define IPTOS_NORMALSVC 0 -#endif - -#define XTOPT_MKPTR(cb) \ - ((void *)((char *)(cb)->data + (cb)->entry->ptroff)) - -/** - * Simple key-value pairs for syslog levels - */ -struct syslog_level { - char name[8]; - uint8_t level; -}; - -struct tos_value_mask { - uint8_t value, mask; -}; - -static const size_t xtopt_psize[] = { - /* - * All types not listed here, and thus essentially being initialized to - * zero have zero on purpose. - */ - [XTTYPE_UINT8] = sizeof(uint8_t), - [XTTYPE_UINT16] = sizeof(uint16_t), - [XTTYPE_UINT32] = sizeof(uint32_t), - [XTTYPE_UINT64] = sizeof(uint64_t), - [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), - [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), - [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), - [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), - [XTTYPE_DOUBLE] = sizeof(double), - [XTTYPE_STRING] = -1, - [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), - [XTTYPE_HOST] = sizeof(union nf_inet_addr), - [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), - [XTTYPE_PROTOCOL] = sizeof(uint8_t), - [XTTYPE_PORT] = sizeof(uint16_t), - [XTTYPE_PORTRC] = sizeof(uint16_t[2]), - [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr), - [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]), -}; - -/** - * Creates getopt options from the x6-style option map, and assigns each a - * getopt id. - */ -struct option * -xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, - const struct xt_option_entry *entry, unsigned int *offset) -{ - unsigned int num_orig, num_old = 0, num_new, i; - struct option *merge, *mp; - - if (entry == NULL) - return oldopts; - for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig) - ; - if (oldopts != NULL) - for (num_old = 0; oldopts[num_old].name != NULL; ++num_old) - ; - for (num_new = 0; entry[num_new].name != NULL; ++num_new) - ; - - /* - * Since @oldopts also has @orig_opts already (and does so at the - * start), skip these entries. - */ - oldopts += num_orig; - num_old -= num_orig; - - merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1)); - if (merge == NULL) - return NULL; - - /* Let the base options -[ADI...] have precedence over everything */ - memcpy(merge, orig_opts, sizeof(*mp) * num_orig); - mp = merge + num_orig; - - /* Second, the new options */ - xt_params->option_offset += XT_OPTION_OFFSET_SCALE; - *offset = xt_params->option_offset; - - for (i = 0; i < num_new; ++i, ++mp, ++entry) { - mp->name = entry->name; - mp->has_arg = entry->type != XTTYPE_NONE; - mp->flag = NULL; - mp->val = entry->id + *offset; - } - - /* Third, the old options */ - memcpy(mp, oldopts, sizeof(*mp) * num_old); - mp += num_old; - xtables_free_opts(0); - - /* Clear trailing entry */ - memset(mp, 0, sizeof(*mp)); - return merge; -} - -/** - * Give the upper limit for a certain type. - */ -static uintmax_t xtopt_max_by_type(enum xt_option_type type) -{ - switch (type) { - case XTTYPE_UINT8: - case XTTYPE_UINT8RC: - return UINT8_MAX; - case XTTYPE_UINT16: - case XTTYPE_UINT16RC: - return UINT16_MAX; - case XTTYPE_UINT32: - case XTTYPE_UINT32RC: - return UINT32_MAX; - case XTTYPE_UINT64: - case XTTYPE_UINT64RC: - return UINT64_MAX; - default: - return 0; - } -} - -/** - * Return the size of a single entity based upon a type - predominantly an - * XTTYPE_UINT*RC type. - */ -static size_t xtopt_esize_by_type(enum xt_option_type type) -{ - switch (type) { - case XTTYPE_UINT8RC: - return xtopt_psize[XTTYPE_UINT8]; - case XTTYPE_UINT16RC: - return xtopt_psize[XTTYPE_UINT16]; - case XTTYPE_UINT32RC: - return xtopt_psize[XTTYPE_UINT32]; - case XTTYPE_UINT64RC: - return xtopt_psize[XTTYPE_UINT64]; - default: - return xtopt_psize[type]; - } -} - -/** - * Require a simple integer. - */ -static void xtopt_parse_int(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type); - uintmax_t value; - - if (cb->entry->min != 0) - lmin = cb->entry->min; - if (cb->entry->max != 0) - lmax = cb->entry->max; - - if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: bad value for option \"--%s\", " - "or out of range (%ju-%ju).\n", - cb->ext_name, entry->name, lmin, lmax); - - if (entry->type == XTTYPE_UINT8) { - cb->val.u8 = value; - if (entry->flags & XTOPT_PUT) - *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; - } else if (entry->type == XTTYPE_UINT16) { - cb->val.u16 = value; - if (entry->flags & XTOPT_PUT) - *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16; - } else if (entry->type == XTTYPE_UINT32) { - cb->val.u32 = value; - if (entry->flags & XTOPT_PUT) - *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; - } else if (entry->type == XTTYPE_UINT64) { - cb->val.u64 = value; - if (entry->flags & XTOPT_PUT) - *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; - } -} - -/** - * Require a simple floating point number. - */ -static void xtopt_parse_float(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - double value; - char *end; - - value = strtod(cb->arg, &end); - if (end == cb->arg || *end != '\0' || - (entry->min != entry->max && - (value < entry->min || value > entry->max))) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: bad value for option \"--%s\", " - "or out of range (%u-%u).\n", - cb->ext_name, entry->name, entry->min, entry->max); - - cb->val.dbl = value; - if (entry->flags & XTOPT_PUT) - *(double *)XTOPT_MKPTR(cb) = cb->val.dbl; -} - -/** - * Copy the parsed value to the appropriate entry in cb->val. - */ -static void xtopt_mint_value_to_cb(struct xt_option_call *cb, uintmax_t value) -{ - const struct xt_option_entry *entry = cb->entry; - - if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range)) - return; - if (entry->type == XTTYPE_UINT8RC) - cb->val.u8_range[cb->nvals] = value; - else if (entry->type == XTTYPE_UINT16RC) - cb->val.u16_range[cb->nvals] = value; - else if (entry->type == XTTYPE_UINT32RC) - cb->val.u32_range[cb->nvals] = value; - else if (entry->type == XTTYPE_UINT64RC) - cb->val.u64_range[cb->nvals] = value; -} - -/** - * Copy the parsed value to the data area, using appropriate type access. - */ -static void xtopt_mint_value_to_ptr(struct xt_option_call *cb, void **datap, - uintmax_t value) -{ - const struct xt_option_entry *entry = cb->entry; - void *data = *datap; - - if (!(entry->flags & XTOPT_PUT)) - return; - if (entry->type == XTTYPE_UINT8RC) - *(uint8_t *)data = value; - else if (entry->type == XTTYPE_UINT16RC) - *(uint16_t *)data = value; - else if (entry->type == XTTYPE_UINT32RC) - *(uint32_t *)data = value; - else if (entry->type == XTTYPE_UINT64RC) - *(uint64_t *)data = value; - data += xtopt_esize_by_type(entry->type); - *datap = data; -} - -/** - * Multiple integer parse routine. - * - * This function is capable of parsing any number of fields. Only the first - * two values from the string will be put into @cb however (and as such, - * @cb->val.uXX_range is just that large) to cater for the few extensions that - * do not have a range[2] field, but {min, max}, and which cannot use - * XTOPT_POINTER. - */ -static void xtopt_parse_mint(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - const char *arg = cb->arg; - size_t esize = xtopt_esize_by_type(entry->type); - const uintmax_t lmax = xtopt_max_by_type(entry->type); - void *put = XTOPT_MKPTR(cb); - unsigned int maxiter; - uintmax_t value; - char *end = ""; - char sep = ':'; - - maxiter = entry->size / esize; - if (maxiter == 0) - maxiter = ARRAY_SIZE(cb->val.u32_range); - if (entry->size % esize != 0) - xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " - "not have proper size\n", __func__); - - cb->nvals = 0; - for (arg = cb->arg, end = (char *)arg; ; arg = end + 1) { - if (cb->nvals == maxiter) - xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " - "components for option \"--%s\" (max: %u)\n", - cb->ext_name, entry->name, maxiter); - if (*arg == '\0' || *arg == sep) { - /* Default range components when field not spec'd. */ - end = (char *)arg; - value = (cb->nvals == 1) ? lmax : 0; - } else { - if (!xtables_strtoul(arg, &end, &value, 0, lmax)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: bad value for option \"--%s\" near " - "\"%s\", or out of range (0-%ju).\n", - cb->ext_name, entry->name, arg, lmax); - if (*end != '\0' && *end != sep) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: Argument to \"--%s\" has " - "unexpected characters near \"%s\".\n", - cb->ext_name, entry->name, end); - } - xtopt_mint_value_to_cb(cb, value); - ++cb->nvals; - xtopt_mint_value_to_ptr(cb, &put, value); - if (*end == '\0') - break; - } -} - -static void xtopt_parse_string(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - size_t z = strlen(cb->arg); - char *p; - - if (entry->min != 0 && z < entry->min) - xt_params->exit_err(PARAMETER_PROBLEM, - "Argument must have a minimum length of " - "%u characters\n", entry->min); - if (entry->max != 0 && z > entry->max) - xt_params->exit_err(PARAMETER_PROBLEM, - "Argument must have a maximum length of " - "%u characters\n", entry->max); - if (!(entry->flags & XTOPT_PUT)) - return; - if (z >= entry->size) - z = entry->size - 1; - p = XTOPT_MKPTR(cb); - strncpy(p, cb->arg, z); - p[z] = '\0'; -} - -static const struct tos_symbol_info { - unsigned char value; - const char *name; -} tos_symbol_names[] = { - {IPTOS_LOWDELAY, "Minimize-Delay"}, - {IPTOS_THROUGHPUT, "Maximize-Throughput"}, - {IPTOS_RELIABILITY, "Maximize-Reliability"}, - {IPTOS_MINCOST, "Minimize-Cost"}, - {IPTOS_NORMALSVC, "Normal-Service"}, - {}, -}; - -/* - * tos_parse_numeric - parse a string like "15/255" - * - * @str: input string - * @tvm: (value/mask) tuple - * @max: maximum allowed value (must be pow(2,some_int)-1) - */ -static bool tos_parse_numeric(const char *str, struct xt_option_call *cb, - unsigned int max) -{ - unsigned int value; - char *end; - - xtables_strtoui(str, &end, &value, 0, max); - cb->val.tos_value = value; - cb->val.tos_mask = max; - - if (*end == '/') { - const char *p = end + 1; - - if (!xtables_strtoui(p, &end, &value, 0, max)) - xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", - str); - cb->val.tos_mask = value; - } - - if (*end != '\0') - xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str); - return true; -} - -/** - * @str: input string - * @tvm: (value/mask) tuple - * @def_mask: mask to force when a symbolic name is used - */ -static void xtopt_parse_tosmask(struct xt_option_call *cb) -{ - const struct tos_symbol_info *symbol; - char *tmp; - - if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) { - tos_parse_numeric(cb->arg, cb, UINT8_MAX); - return; - } - /* - * This is our way we deal with different defaults - * for different revisions. - */ - cb->val.tos_mask = cb->entry->max; - for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) - if (strcasecmp(cb->arg, symbol->name) == 0) { - cb->val.tos_value = symbol->value; - return; - } - - xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", - cb->arg); -} - -/** - * Validate the input for being conformant to "mark[/mask]". - */ -static void xtopt_parse_markmask(struct xt_option_call *cb) -{ - unsigned int mark = 0, mask = ~0U; - char *end; - - if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: bad mark value for option \"--%s\", " - "or out of range.\n", - cb->ext_name, cb->entry->name); - if (*end == '/' && - !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: bad mask value for option \"--%s\", " - "or out of range.\n", - cb->ext_name, cb->entry->name); - if (*end != '\0') - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: trailing garbage after value " - "for option \"--%s\".\n", - cb->ext_name, cb->entry->name); - cb->val.mark = mark; - cb->val.mask = mask; -} - -static int xtopt_sysloglvl_compare(const void *a, const void *b) -{ - const char *name = a; - const struct syslog_level *entry = b; - - return strcmp(name, entry->name); -} - -static void xtopt_parse_sysloglevel(struct xt_option_call *cb) -{ - static const struct syslog_level log_names[] = { /* must be sorted */ - {"alert", LOG_ALERT}, - {"crit", LOG_CRIT}, - {"debug", LOG_DEBUG}, - {"emerg", LOG_EMERG}, - {"error", LOG_ERR}, /* deprecated */ - {"info", LOG_INFO}, - {"notice", LOG_NOTICE}, - {"panic", LOG_EMERG}, /* deprecated */ - {"warning", LOG_WARNING}, - }; - const struct syslog_level *e; - unsigned int num = 0; - - if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) { - e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names), - sizeof(*log_names), xtopt_sysloglvl_compare); - if (e == NULL) - xt_params->exit_err(PARAMETER_PROBLEM, - "log level \"%s\" unknown\n", cb->arg); - num = e->level; - } - cb->val.syslog_level = num; - if (cb->entry->flags & XTOPT_PUT) - *(uint8_t *)XTOPT_MKPTR(cb) = num; -} - -static void *xtables_sa_host(const void *sa, unsigned int afproto) -{ - if (afproto == AF_INET6) - return &((struct sockaddr_in6 *)sa)->sin6_addr; - else if (afproto == AF_INET) - return &((struct sockaddr_in *)sa)->sin_addr; - return (void *)sa; -} - -static socklen_t xtables_sa_hostlen(unsigned int afproto) -{ - if (afproto == AF_INET6) - return sizeof(struct in6_addr); - else if (afproto == AF_INET) - return sizeof(struct in_addr); - return 0; -} - -/** - * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The - * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and - * @cb->val.hlen are set for completeness to the appropriate values. - */ -static void xtopt_parse_host(struct xt_option_call *cb) -{ - struct addrinfo hints = {.ai_family = afinfo->family}; - unsigned int adcount = 0; - struct addrinfo *res, *p; - int ret; - - ret = getaddrinfo(cb->arg, NULL, &hints, &res); - if (ret < 0) - xt_params->exit_err(PARAMETER_PROBLEM, - "getaddrinfo: %s\n", gai_strerror(ret)); - - memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask)); - cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; - - for (p = res; p != NULL; p = p->ai_next) { - if (adcount == 0) { - memset(&cb->val.haddr, 0, sizeof(cb->val.haddr)); - memcpy(&cb->val.haddr, - xtables_sa_host(p->ai_addr, p->ai_family), - xtables_sa_hostlen(p->ai_family)); - ++adcount; - continue; - } - if (memcmp(&cb->val.haddr, - xtables_sa_host(p->ai_addr, p->ai_family), - xtables_sa_hostlen(p->ai_family)) != 0) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s resolves to more than one address\n", - cb->arg); - } - - freeaddrinfo(res); - if (cb->entry->flags & XTOPT_PUT) - /* Validation in xtables_option_metavalidate */ - memcpy(XTOPT_MKPTR(cb), &cb->val.haddr, - sizeof(cb->val.haddr)); -} - -/** - * @name: port name, or number as a string (e.g. "http" or "80") - * - * Resolve a port name to a number. Returns the port number in integral - * form on success, or <0 on error. (errno will not be set.) - */ -static int xtables_getportbyname(const char *name) -{ - struct addrinfo *res = NULL, *p; - int ret; - - ret = getaddrinfo(NULL, name, NULL, &res); - if (ret < 0) - return -1; - ret = -1; - for (p = res; p != NULL; p = p->ai_next) { - if (p->ai_family == AF_INET6) { - ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port; - break; - } else if (p->ai_family == AF_INET) { - ret = ((struct sockaddr_in *)p->ai_addr)->sin_port; - break; - } - } - freeaddrinfo(res); - if (ret < 0) - return ret; - return ntohs(ret); -} - -/** - * Validate and parse a protocol specification (number or name) by use of - * /etc/protocols and put the result into @cb->val.protocol. - */ -static void xtopt_parse_protocol(struct xt_option_call *cb) -{ - cb->val.protocol = xtables_parse_protocol(cb->arg); - if (cb->entry->flags & XTOPT_PUT) - *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol; -} - -/** - * Validate and parse a port specification and put the result into - * @cb->val.port. - */ -static void xtopt_parse_port(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - int ret; - - ret = xtables_getportbyname(cb->arg); - if (ret < 0) - xt_params->exit_err(PARAMETER_PROBLEM, - "Port \"%s\" does not resolve to anything.\n", - cb->arg); - if (entry->flags & XTOPT_NBO) - ret = htons(ret); - cb->val.port = ret; - if (entry->flags & XTOPT_PUT) - *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; -} - -static void xtopt_parse_mport(struct xt_option_call *cb) -{ - static const size_t esize = sizeof(uint16_t); - const struct xt_option_entry *entry = cb->entry; - char *lo_arg, *wp_arg, *arg; - unsigned int maxiter; - int value; - - wp_arg = lo_arg = strdup(cb->arg); - if (lo_arg == NULL) - xt_params->exit_err(RESOURCE_PROBLEM, "strdup"); - - maxiter = entry->size / esize; - if (maxiter == 0) - maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */ - if (entry->size % esize != 0) - xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " - "not have proper size\n", __func__); - - cb->val.port_range[0] = 0; - cb->val.port_range[1] = UINT16_MAX; - cb->nvals = 0; - - while ((arg = strsep(&wp_arg, ":")) != NULL) { - if (cb->nvals == maxiter) - xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " - "components for option \"--%s\" (max: %u)\n", - cb->ext_name, entry->name, maxiter); - if (*arg == '\0') { - ++cb->nvals; - continue; - } - - value = xtables_getportbyname(arg); - if (value < 0) - xt_params->exit_err(PARAMETER_PROBLEM, - "Port \"%s\" does not resolve to " - "anything.\n", arg); - if (entry->flags & XTOPT_NBO) - value = htons(value); - if (cb->nvals < ARRAY_SIZE(cb->val.port_range)) - cb->val.port_range[cb->nvals] = value; - ++cb->nvals; - } - - if (cb->nvals == 1) { - cb->val.port_range[1] = cb->val.port_range[0]; - ++cb->nvals; - } - if (entry->flags & XTOPT_PUT) - memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) * - (cb->nvals <= maxiter ? cb->nvals : maxiter)); - free(lo_arg); -} - -/** - * Parse an integer and ensure it is within the address family's prefix length - * limits. The result is stored in @cb->val.hlen. - */ -static void xtopt_parse_plen(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - unsigned int prefix_len = 128; /* happiness is a warm gcc */ - - cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; - if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: bad value for option \"--%s\", " - "or out of range (%u-%u).\n", - cb->ext_name, entry->name, 0, cb->val.hlen); - - cb->val.hlen = prefix_len; -} - -/** - * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to - * a bitmask, and make it available through @cb->val.hmask (hlen remains - * valid). If %XTOPT_PUT is used, hmask will be copied to the target area. - */ -static void xtopt_parse_plenmask(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - uint32_t *mask = cb->val.hmask.all; - - xtopt_parse_plen(cb); - - memset(mask, 0xFF, sizeof(union nf_inet_addr)); - /* This shifting is AF-independent. */ - if (cb->val.hlen == 0) { - mask[0] = mask[1] = mask[2] = mask[3] = 0; - } else if (cb->val.hlen <= 32) { - mask[0] <<= 32 - cb->val.hlen; - mask[1] = mask[2] = mask[3] = 0; - } else if (cb->val.hlen <= 64) { - mask[1] <<= 32 - (cb->val.hlen - 32); - mask[2] = mask[3] = 0; - } else if (cb->val.hlen <= 96) { - mask[2] <<= 32 - (cb->val.hlen - 64); - mask[3] = 0; - } else if (cb->val.hlen <= 128) { - mask[3] <<= 32 - (cb->val.hlen - 96); - } - mask[0] = htonl(mask[0]); - mask[1] = htonl(mask[1]); - mask[2] = htonl(mask[2]); - mask[3] = htonl(mask[3]); - if (entry->flags & XTOPT_PUT) - memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr)); -} - -static void xtopt_parse_hostmask(struct xt_option_call *cb) -{ - const char *orig_arg = cb->arg; - char *work, *p; - - if (strchr(cb->arg, '/') == NULL) { - xtopt_parse_host(cb); - return; - } - work = strdup(orig_arg); - if (work == NULL) - xt_params->exit_err(PARAMETER_PROBLEM, "strdup"); - p = strchr(work, '/'); /* by def this can't be NULL now */ - *p++ = '\0'; - /* - * Because xtopt_parse_host and xtopt_parse_plenmask would store - * different things in the same target area, XTTYPE_HOSTMASK must - * disallow XTOPT_PUT, which it does by forcing its absence, - * cf. not being listed in xtopt_psize. - */ - cb->arg = work; - xtopt_parse_host(cb); - cb->arg = p; - xtopt_parse_plenmask(cb); - cb->arg = orig_arg; -} - -static void xtopt_parse_ethermac(struct xt_option_call *cb) -{ - const char *arg = cb->arg; - unsigned int i; - char *end; - - for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) { - cb->val.ethermac[i] = strtoul(arg, &end, 16); - if (*end != ':' || end - arg > 2) - goto out; - arg = end + 1; - } - i = ARRAY_SIZE(cb->val.ethermac) - 1; - cb->val.ethermac[i] = strtoul(arg, &end, 16); - if (*end != '\0' || end - arg > 2) - goto out; - if (cb->entry->flags & XTOPT_PUT) - memcpy(XTOPT_MKPTR(cb), cb->val.ethermac, - sizeof(cb->val.ethermac)); - return; - out: - xt_params->exit_err(PARAMETER_PROBLEM, "ether"); -} - -static void (*const xtopt_subparse[])(struct xt_option_call *) = { - [XTTYPE_UINT8] = xtopt_parse_int, - [XTTYPE_UINT16] = xtopt_parse_int, - [XTTYPE_UINT32] = xtopt_parse_int, - [XTTYPE_UINT64] = xtopt_parse_int, - [XTTYPE_UINT8RC] = xtopt_parse_mint, - [XTTYPE_UINT16RC] = xtopt_parse_mint, - [XTTYPE_UINT32RC] = xtopt_parse_mint, - [XTTYPE_UINT64RC] = xtopt_parse_mint, - [XTTYPE_DOUBLE] = xtopt_parse_float, - [XTTYPE_STRING] = xtopt_parse_string, - [XTTYPE_TOSMASK] = xtopt_parse_tosmask, - [XTTYPE_MARKMASK32] = xtopt_parse_markmask, - [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, - [XTTYPE_HOST] = xtopt_parse_host, - [XTTYPE_HOSTMASK] = xtopt_parse_hostmask, - [XTTYPE_PROTOCOL] = xtopt_parse_protocol, - [XTTYPE_PORT] = xtopt_parse_port, - [XTTYPE_PORTRC] = xtopt_parse_mport, - [XTTYPE_PLEN] = xtopt_parse_plen, - [XTTYPE_PLENMASK] = xtopt_parse_plenmask, - [XTTYPE_ETHERMAC] = xtopt_parse_ethermac, -}; - -/** - * The master option parsing routine. May be used for the ".x6_parse" - * function pointer in extensions if fully automatic parsing is desired. - * It may be also called manually from a custom x6_parse function. - */ -void xtables_option_parse(struct xt_option_call *cb) -{ - const struct xt_option_entry *entry = cb->entry; - unsigned int eflag = 1 << cb->entry->id; - - /* - * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use - * prevention. Though it turned out that this is too much typing (most - * of the options are one-time use only), so now we also have - * %XTOPT_MULTI. - */ - if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && - cb->xflags & eflag) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: option \"--%s\" can only be used once.\n", - cb->ext_name, cb->entry->name); - if (cb->invert && !(entry->flags & XTOPT_INVERT)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: option \"--%s\" cannot be inverted.\n", - cb->ext_name, entry->name); - if (entry->type != XTTYPE_NONE && optarg == NULL) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: option \"--%s\" requires an argument.\n", - cb->ext_name, entry->name); - /* - * Fill in fallback value for "nvals", in case an extension (as it - * happened with libxt_conntrack.2) tries to read it, despite not using - * a *RC option type. - */ - cb->nvals = 1; - if (entry->type <= ARRAY_SIZE(xtopt_subparse) && - xtopt_subparse[entry->type] != NULL) - xtopt_subparse[entry->type](cb); - /* Exclusion with other flags tested later in finalize. */ - cb->xflags |= 1 << entry->id; -} - -/** - * Verifies that an extension's option map descriptor is valid, and ought to - * be called right after the extension has been loaded, and before option - * merging/xfrm. - */ -void xtables_option_metavalidate(const char *name, - const struct xt_option_entry *entry) -{ - for (; entry->name != NULL; ++entry) { - if (entry->id >= CHAR_BIT * sizeof(unsigned int) || - entry->id >= XT_OPTION_OFFSET_SCALE) - xt_params->exit_err(OTHER_PROBLEM, - "Extension %s uses invalid ID %u\n", - name, entry->id); - if (!(entry->flags & XTOPT_PUT)) { - if (entry->ptroff != 0) - xt_params->exit_err(OTHER_PROBLEM, - "%s: ptroff for \"--%s\" is non-" - "zero but no XTOPT_PUT is specified. " - "Oversight?", name, entry->name); - continue; - } - if (entry->type >= ARRAY_SIZE(xtopt_psize) || - xtopt_psize[entry->type] == 0) - xt_params->exit_err(OTHER_PROBLEM, - "%s: entry type of option \"--%s\" cannot be " - "combined with XTOPT_PUT\n", - name, entry->name); - if (xtopt_psize[entry->type] != -1 && - xtopt_psize[entry->type] != entry->size) - xt_params->exit_err(OTHER_PROBLEM, - "%s: option \"--%s\" points to a memory block " - "of wrong size (expected %zu, got %zu)\n", - name, entry->name, - xtopt_psize[entry->type], entry->size); - } -} - -/** - * Find an option entry by its id. - */ -static const struct xt_option_entry * -xtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) -{ - for (; entry->name != NULL; ++entry) - if (entry->id == id) - return entry; - return NULL; -} - -/** - * @c: getopt id (i.e. with offset) - * @fw: struct ipt_entry or ip6t_entry - * - * Dispatch arguments to the appropriate parse function, based upon the - * extension's choice of API. - */ -void xtables_option_tpcall(unsigned int c, char **argv, bool invert, - struct xtables_target *t, void *fw) -{ - struct xt_option_call cb; - - if (t->x6_parse == NULL) { - if (t->parse != NULL) - t->parse(c - t->option_offset, argv, invert, - &t->tflags, fw, &t->t); - return; - } - - c -= t->option_offset; - cb.entry = xtables_option_lookup(t->x6_options, c); - if (cb.entry == NULL) - xtables_error(OTHER_PROBLEM, - "Extension does not know id %u\n", c); - cb.arg = optarg; - cb.invert = invert; - cb.ext_name = t->name; - cb.data = t->t->data; - cb.xflags = t->tflags; - cb.target = &t->t; - cb.xt_entry = fw; - cb.udata = t->udata; - t->x6_parse(&cb); - t->tflags = cb.xflags; -} - -/** - * @c: getopt id (i.e. with offset) - * @fw: struct ipt_entry or ip6t_entry - * - * Dispatch arguments to the appropriate parse function, based upon the - * extension's choice of API. - */ -void xtables_option_mpcall(unsigned int c, char **argv, bool invert, - struct xtables_match *m, void *fw) -{ - struct xt_option_call cb; - - if (m->x6_parse == NULL) { - if (m->parse != NULL) - m->parse(c - m->option_offset, argv, invert, - &m->mflags, fw, &m->m); - return; - } - - c -= m->option_offset; - cb.entry = xtables_option_lookup(m->x6_options, c); - if (cb.entry == NULL) - xtables_error(OTHER_PROBLEM, - "Extension does not know id %u\n", c); - cb.arg = optarg; - cb.invert = invert; - cb.ext_name = m->name; - cb.data = m->m->data; - cb.xflags = m->mflags; - cb.match = &m->m; - cb.xt_entry = fw; - cb.udata = m->udata; - m->x6_parse(&cb); - m->mflags = cb.xflags; -} - -/** - * @name: name of extension - * @entry: current option (from all ext's entries) being validated - * @xflags: flags the extension has collected - * @i: conflicting option (id) to test for - */ -static void -xtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, - const struct xt_option_entry *other, - unsigned int xflags) -{ - unsigned int ef = 1 << entry->id, of = 1 << other->id; - - if (entry->also & of && !(xflags & of)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: option \"--%s\" also requires \"--%s\".\n", - name, entry->name, other->name); - - if (!(entry->excl & of)) - /* Use of entry does not collide with other option, good. */ - return; - if ((xflags & (ef | of)) != (ef | of)) - /* Conflicting options were not used. */ - return; - - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: option \"--%s\" cannot be used together with \"--%s\".\n", - name, entry->name, other->name); -} - -/** - * @name: name of extension - * @xflags: accumulated flags - * @entry: extension's option table - * - * Check that all option constraints have been met. This effectively replaces - * ->final_check of the older API. - */ -void xtables_options_fcheck(const char *name, unsigned int xflags, - const struct xt_option_entry *table) -{ - const struct xt_option_entry *entry, *other; - unsigned int i; - - for (entry = table; entry->name != NULL; ++entry) { - if (entry->flags & XTOPT_MAND && - !(xflags & (1 << entry->id))) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: option \"--%s\" must be specified\n", - name, entry->name); - if (!(xflags & (1 << entry->id))) - /* Not required, not specified, thus skip. */ - continue; - - for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { - if (entry->id == i) - /* - * Avoid conflict with self. Multi-use check - * was done earlier in xtables_option_parse. - */ - continue; - other = xtables_option_lookup(table, i); - if (other == NULL) - continue; - xtables_option_fcheck2(name, entry, other, xflags); - } - } -} - -/** - * Dispatch arguments to the appropriate final_check function, based upon the - * extension's choice of API. - */ -void xtables_option_tfcall(struct xtables_target *t) -{ - if (t->x6_fcheck != NULL) { - struct xt_fcheck_call cb; - - cb.ext_name = t->name; - cb.data = t->t->data; - cb.xflags = t->tflags; - cb.udata = t->udata; - t->x6_fcheck(&cb); - } else if (t->final_check != NULL) { - t->final_check(t->tflags); - } - if (t->x6_options != NULL) - xtables_options_fcheck(t->name, t->tflags, t->x6_options); -} - -/** - * Dispatch arguments to the appropriate final_check function, based upon the - * extension's choice of API. - */ -void xtables_option_mfcall(struct xtables_match *m) -{ - if (m->x6_fcheck != NULL) { - struct xt_fcheck_call cb; - - cb.ext_name = m->name; - cb.data = m->m->data; - cb.xflags = m->mflags; - cb.udata = m->udata; - m->x6_fcheck(&cb); - } else if (m->final_check != NULL) { - m->final_check(m->mflags); - } - if (m->x6_options != NULL) - xtables_options_fcheck(m->name, m->mflags, m->x6_options); -} - -struct xtables_lmap *xtables_lmap_init(const char *file) -{ - struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; - char buf[512]; - FILE *fp; - char *cur, *nxt; - int id; - - fp = fopen(file, "re"); - if (fp == NULL) - return NULL; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - cur = buf; - while (isspace(*cur)) - ++cur; - if (*cur == '#' || *cur == '\n' || *cur == '\0') - continue; - - /* iproute2 allows hex and dec format */ - errno = 0; - id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); - if (nxt == cur || errno != 0) - continue; - - /* same boundaries as in iproute2 */ - if (id < 0 || id > 255) - continue; - cur = nxt; - - if (!isspace(*cur)) - continue; - while (isspace(*cur)) - ++cur; - if (*cur == '#' || *cur == '\n' || *cur == '\0') - continue; - nxt = cur; - while (*nxt != '\0' && !isspace(*nxt)) - ++nxt; - if (nxt == cur) - continue; - *nxt = '\0'; - - /* found valid data */ - lmap_this = malloc(sizeof(*lmap_this)); - if (lmap_this == NULL) { - perror("malloc"); - goto out; - } - lmap_this->id = id; - lmap_this->name = strdup(cur); - if (lmap_this->name == NULL) { - free(lmap_this); - goto out; - } - lmap_this->next = NULL; - - if (lmap_prev != NULL) - lmap_prev->next = lmap_this; - else - lmap_head = lmap_this; - lmap_prev = lmap_this; - } - - fclose(fp); - return lmap_head; - out: - xtables_lmap_free(lmap_head); - return NULL; -} - -void xtables_lmap_free(struct xtables_lmap *head) -{ - struct xtables_lmap *next; - - for (; head != NULL; head = next) { - next = head->next; - free(head->name); - free(head); - } -} - -int xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) -{ - for (; head != NULL; head = head->next) - if (strcmp(head->name, name) == 0) - return head->id; - return -1; -} - -const char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) -{ - for (; head != NULL; head = head->next) - if (head->id == id) - return head->name; - return NULL; -} diff --git a/libxtables/Makefile.am b/libxtables/Makefile.am new file mode 100644 index 00000000..c5795fef --- /dev/null +++ b/libxtables/Makefile.am @@ -0,0 +1,20 @@ +# -*- Makefile -*- + +AM_CFLAGS = ${regular_CFLAGS} +AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include -I${top_srcdir}/iptables ${kinclude_CPPFLAGS} + +lib_LTLIBRARIES = libxtables.la +libxtables_la_SOURCES = xtables.c xtoptions.c +libxtables_la_LDFLAGS = -version-info ${libxtables_vcurrent}:0:${libxtables_vage} +libxtables_la_LIBADD = +if ENABLE_STATIC +# With --enable-static, shipped extensions are linked into the main executable, +# so we need all the LIBADDs here too +libxtables_la_LIBADD += -lm +endif +if ENABLE_SHARED +libxtables_la_CFLAGS = ${AM_CFLAGS} +libxtables_la_LIBADD += -ldl +else +libxtables_la_CFLAGS = ${AM_CFLAGS} -DNO_SHARED_LIBS=1 +endif diff --git a/libxtables/xtables.c b/libxtables/xtables.c new file mode 100644 index 00000000..014e115b --- /dev/null +++ b/libxtables/xtables.c @@ -0,0 +1,1832 @@ +/* + * (C) 2000-2006 by the netfilter coreteam : + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(HAVE_LINUX_MAGIC_H) +# include /* for PROC_SUPER_MAGIC */ +#elif defined(HAVE_LINUX_PROC_FS_H) +# include /* Linux 2.4 */ +#else +# define PROC_SUPER_MAGIC 0x9fa0 +#endif + +#include +#include /* INT_MAX in ip_tables.h/ip6_tables.h */ +#include +#include +#include + +#ifndef NO_SHARED_LIBS +#include +#endif +#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */ +# define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) +# define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) +#endif +#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */ +# define IP6T_SO_GET_REVISION_MATCH 68 +# define IP6T_SO_GET_REVISION_TARGET 69 +#endif +#include +#include "iptables/internal.h" +#include "xshared.h" + +#define NPROTO 255 + +#ifndef PROC_SYS_MODPROBE +#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" +#endif + +/* we need this for ip6?tables-restore. ip6?tables-restore.c sets line to the + * current line of the input file, in order to give a more precise error + * message. ip6?tables itself doesn't need this, so it is initialized to the + * magic number of -1 */ +int line = -1; + +void basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); + +struct xtables_globals *xt_params = NULL; + +void basic_exit_err(enum xtables_exittype status, const char *msg, ...) +{ + va_list args; + + va_start(args, msg); + fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + exit(status); +} + +void xtables_free_opts(int unused) +{ + if (xt_params->opts != xt_params->orig_opts) { + free(xt_params->opts); + xt_params->opts = NULL; + } +} + +struct option *xtables_merge_options(struct option *orig_opts, + struct option *oldopts, + const struct option *newopts, + unsigned int *option_offset) +{ + unsigned int num_oold = 0, num_old = 0, num_new = 0, i; + struct option *merge, *mp; + + if (newopts == NULL) + return oldopts; + + for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ; + if (oldopts != NULL) + for (num_old = 0; oldopts[num_old].name; num_old++) ; + for (num_new = 0; newopts[num_new].name; num_new++) ; + + /* + * Since @oldopts also has @orig_opts already (and does so at the + * start), skip these entries. + */ + oldopts += num_oold; + num_old -= num_oold; + + merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1)); + if (merge == NULL) + return NULL; + + /* Let the base options -[ADI...] have precedence over everything */ + memcpy(merge, orig_opts, sizeof(*mp) * num_oold); + mp = merge + num_oold; + + /* Second, the new options */ + xt_params->option_offset += XT_OPTION_OFFSET_SCALE; + *option_offset = xt_params->option_offset; + memcpy(mp, newopts, sizeof(*mp) * num_new); + + for (i = 0; i < num_new; ++i, ++mp) + mp->val += *option_offset; + + /* Third, the old options */ + memcpy(mp, oldopts, sizeof(*mp) * num_old); + mp += num_old; + xtables_free_opts(0); + + /* Clear trailing entry */ + memset(mp, 0, sizeof(*mp)); + return merge; +} + +static const struct xtables_afinfo afinfo_ipv4 = { + .kmod = "ip_tables", + .proc_exists = "/proc/net/ip_tables_names", + .libprefix = "libipt_", + .family = NFPROTO_IPV4, + .ipproto = IPPROTO_IP, + .so_rev_match = IPT_SO_GET_REVISION_MATCH, + .so_rev_target = IPT_SO_GET_REVISION_TARGET, +}; + +static const struct xtables_afinfo afinfo_ipv6 = { + .kmod = "ip6_tables", + .proc_exists = "/proc/net/ip6_tables_names", + .libprefix = "libip6t_", + .family = NFPROTO_IPV6, + .ipproto = IPPROTO_IPV6, + .so_rev_match = IP6T_SO_GET_REVISION_MATCH, + .so_rev_target = IP6T_SO_GET_REVISION_TARGET, +}; + +const struct xtables_afinfo *afinfo; + +/* Search path for Xtables .so files */ +static const char *xtables_libdir; + +/* the path to command to load kernel module */ +const char *xtables_modprobe_program; + +/* Keep track of matches/targets pending full registration: linked lists. */ +struct xtables_match *xtables_pending_matches; +struct xtables_target *xtables_pending_targets; + +/* Keep track of fully registered external matches/targets: linked lists. */ +struct xtables_match *xtables_matches; +struct xtables_target *xtables_targets; + +/* Fully register a match/target which was previously partially registered. */ +static void xtables_fully_register_pending_match(struct xtables_match *me); +static void xtables_fully_register_pending_target(struct xtables_target *me); + +void xtables_init(void) +{ + xtables_libdir = getenv("XTABLES_LIBDIR"); + if (xtables_libdir != NULL) + return; + xtables_libdir = getenv("IPTABLES_LIB_DIR"); + if (xtables_libdir != NULL) { + fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " + "use XTABLES_LIBDIR.\n"); + return; + } + /* + * Well yes, IP6TABLES_LIB_DIR is of lower priority over + * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok + * for these env vars are deprecated anyhow, and in light of the + * (shared) libxt_*.so files, makes less sense to have + * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. + */ + xtables_libdir = getenv("IP6TABLES_LIB_DIR"); + if (xtables_libdir != NULL) { + fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " + "use XTABLES_LIBDIR.\n"); + return; + } + xtables_libdir = XTABLES_LIBDIR; +} + +void xtables_set_nfproto(uint8_t nfproto) +{ + switch (nfproto) { + case NFPROTO_IPV4: + afinfo = &afinfo_ipv4; + break; + case NFPROTO_IPV6: + afinfo = &afinfo_ipv6; + break; + default: + fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", + __func__); + } +} + +/** + * xtables_set_params - set the global parameters used by xtables + * @xtp: input xtables_globals structure + * + * The app is expected to pass a valid xtables_globals data-filled + * with proper values + * @xtp cannot be NULL + * + * Returns -1 on failure to set and 0 on success + */ +int xtables_set_params(struct xtables_globals *xtp) +{ + if (!xtp) { + fprintf(stderr, "%s: Illegal global params\n",__func__); + return -1; + } + + xt_params = xtp; + + if (!xt_params->exit_err) + xt_params->exit_err = basic_exit_err; + + return 0; +} + +int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) +{ + xtables_init(); + xtables_set_nfproto(nfproto); + return xtables_set_params(xtp); +} + +/** + * xtables_*alloc - wrappers that exit on failure + */ +void *xtables_calloc(size_t count, size_t size) +{ + void *p; + + if ((p = calloc(count, size)) == NULL) { + perror("ip[6]tables: calloc failed"); + exit(1); + } + + return p; +} + +void *xtables_malloc(size_t size) +{ + void *p; + + if ((p = malloc(size)) == NULL) { + perror("ip[6]tables: malloc failed"); + exit(1); + } + + return p; +} + +void *xtables_realloc(void *ptr, size_t size) +{ + void *p; + + if ((p = realloc(ptr, size)) == NULL) { + perror("ip[6]tables: realloc failed"); + exit(1); + } + + return p; +} + +static char *get_modprobe(void) +{ + int procfile; + char *ret; + +#define PROCFILE_BUFSIZ 1024 + procfile = open(PROC_SYS_MODPROBE, O_RDONLY); + if (procfile < 0) + return NULL; + if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) { + fprintf(stderr, "Could not set close on exec: %s\n", + strerror(errno)); + exit(1); + } + + ret = malloc(PROCFILE_BUFSIZ); + if (ret) { + memset(ret, 0, PROCFILE_BUFSIZ); + switch (read(procfile, ret, PROCFILE_BUFSIZ)) { + case -1: goto fail; + case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ + } + if (ret[strlen(ret)-1]=='\n') + ret[strlen(ret)-1]=0; + close(procfile); + return ret; + } + fail: + free(ret); + close(procfile); + return NULL; +} + +int xtables_insmod(const char *modname, const char *modprobe, bool quiet) +{ + char *buf = NULL; + char *argv[4]; + int status; + + /* If they don't explicitly set it, read out of kernel */ + if (!modprobe) { + buf = get_modprobe(); + if (!buf) + return -1; + modprobe = buf; + } + + /* + * Need to flush the buffer, or the child may output it again + * when switching the program thru execv. + */ + fflush(stdout); + + switch (vfork()) { + case 0: + argv[0] = (char *)modprobe; + argv[1] = (char *)modname; + if (quiet) { + argv[2] = "-q"; + argv[3] = NULL; + } else { + argv[2] = NULL; + argv[3] = NULL; + } + execv(argv[0], argv); + + /* not usually reached */ + exit(1); + case -1: + free(buf); + return -1; + + default: /* parent */ + wait(&status); + } + + free(buf); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + return 0; + return -1; +} + +/* return true if a given file exists within procfs */ +static bool proc_file_exists(const char *filename) +{ + struct stat s; + struct statfs f; + + if (lstat(filename, &s)) + return false; + if (!S_ISREG(s.st_mode)) + return false; + if (statfs(filename, &f)) + return false; + if (f.f_type != PROC_SUPER_MAGIC) + return false; + return true; +} + +int xtables_load_ko(const char *modprobe, bool quiet) +{ + static bool loaded = false; + int ret; + + if (loaded) + return 0; + + if (proc_file_exists(afinfo->proc_exists)) { + loaded = true; + return 0; + }; + + ret = xtables_insmod(afinfo->kmod, modprobe, quiet); + if (ret == 0) + loaded = true; + + return ret; +} + +/** + * xtables_strtou{i,l} - string to number conversion + * @s: input string + * @end: like strtoul's "end" pointer + * @value: pointer for result + * @min: minimum accepted value + * @max: maximum accepted value + * + * If @end is NULL, we assume the caller wants a "strict strtoul", and hence + * "15a" is rejected. + * In either case, the value obtained is compared for min-max compliance. + * Base is always 0, i.e. autodetect depending on @s. + * + * Returns true/false whether number was accepted. On failure, *value has + * undefined contents. + */ +bool xtables_strtoul(const char *s, char **end, uintmax_t *value, + uintmax_t min, uintmax_t max) +{ + uintmax_t v; + const char *p; + char *my_end; + + errno = 0; + /* Since strtoul allows leading minus, we have to check for ourself. */ + for (p = s; isspace(*p); ++p) + ; + if (*p == '-') + return false; + v = strtoumax(s, &my_end, 0); + if (my_end == s) + return false; + if (end != NULL) + *end = my_end; + + if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { + if (value != NULL) + *value = v; + if (end == NULL) + return *my_end == '\0'; + return true; + } + + return false; +} + +bool xtables_strtoui(const char *s, char **end, unsigned int *value, + unsigned int min, unsigned int max) +{ + uintmax_t v; + bool ret; + + ret = xtables_strtoul(s, end, &v, min, max); + if (value != NULL) + *value = v; + return ret; +} + +int xtables_service_to_port(const char *name, const char *proto) +{ + struct servent *service; + + if ((service = getservbyname(name, proto)) != NULL) + return ntohs((unsigned short) service->s_port); + + return -1; +} + +uint16_t xtables_parse_port(const char *port, const char *proto) +{ + unsigned int portnum; + + if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || + (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) + return portnum; + + xt_params->exit_err(PARAMETER_PROBLEM, + "invalid port/service `%s' specified", port); +} + +void xtables_parse_interface(const char *arg, char *vianame, + unsigned char *mask) +{ + unsigned int vialen = strlen(arg); + unsigned int i; + + memset(mask, 0, IFNAMSIZ); + memset(vianame, 0, IFNAMSIZ); + + if (vialen + 1 > IFNAMSIZ) + xt_params->exit_err(PARAMETER_PROBLEM, + "interface name `%s' must be shorter than IFNAMSIZ" + " (%i)", arg, IFNAMSIZ-1); + + strcpy(vianame, arg); + if (vialen == 0) + return; + else if (vianame[vialen - 1] == '+') { + memset(mask, 0xFF, vialen - 1); + /* Don't remove `+' here! -HW */ + } else { + /* Include nul-terminator in match */ + memset(mask, 0xFF, vialen + 1); + for (i = 0; vianame[i]; i++) { + if (vianame[i] == '/' || + vianame[i] == ' ') { + fprintf(stderr, + "Warning: weird character in interface" + " `%s' ('/' and ' ' are not allowed by the kernel).\n", + vianame); + break; + } + } + } +} + +#ifndef NO_SHARED_LIBS +static void *load_extension(const char *search_path, const char *af_prefix, + const char *name, bool is_target) +{ + const char *all_prefixes[] = {"libxt_", af_prefix, NULL}; + const char **prefix; + const char *dir = search_path, *next; + void *ptr = NULL; + struct stat sb; + char path[256]; + + do { + next = strchr(dir, ':'); + if (next == NULL) + next = dir + strlen(dir); + + for (prefix = all_prefixes; *prefix != NULL; ++prefix) { + snprintf(path, sizeof(path), "%.*s/%s%s.so", + (unsigned int)(next - dir), dir, + *prefix, name); + + if (stat(path, &sb) != 0) { + if (errno == ENOENT) + continue; + fprintf(stderr, "%s: %s\n", path, + strerror(errno)); + return NULL; + } + if (dlopen(path, RTLD_NOW) == NULL) { + fprintf(stderr, "%s: %s\n", path, dlerror()); + break; + } + + if (is_target) + ptr = xtables_find_target(name, XTF_DONT_LOAD); + else + ptr = xtables_find_match(name, + XTF_DONT_LOAD, NULL); + + if (ptr != NULL) + return ptr; + + fprintf(stderr, "%s: no \"%s\" extension found for " + "this protocol\n", path, name); + errno = ENOENT; + return NULL; + } + dir = next + 1; + } while (*next != '\0'); + + return NULL; +} +#endif + +struct xtables_match * +xtables_find_match(const char *name, enum xtables_tryload tryload, + struct xtables_rule_match **matches) +{ + struct xtables_match **dptr; + struct xtables_match *ptr; + const char *icmp6 = "icmp6"; + + if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) + xtables_error(PARAMETER_PROBLEM, + "Invalid match name \"%s\" (%u chars max)", + name, XT_EXTENSION_MAXNAMELEN - 1); + + /* This is ugly as hell. Nonetheless, there is no way of changing + * this without hurting backwards compatibility */ + if ( (strcmp(name,"icmpv6") == 0) || + (strcmp(name,"ipv6-icmp") == 0) || + (strcmp(name,"icmp6") == 0) ) + name = icmp6; + + /* Trigger delayed initialization */ + for (dptr = &xtables_pending_matches; *dptr; ) { + if (strcmp(name, (*dptr)->name) == 0) { + ptr = *dptr; + *dptr = (*dptr)->next; + ptr->next = NULL; + xtables_fully_register_pending_match(ptr); + } else { + dptr = &((*dptr)->next); + } + } + + for (ptr = xtables_matches; ptr; ptr = ptr->next) { + if (strcmp(name, ptr->name) == 0) { + struct xtables_match *clone; + + /* First match of this type: */ + if (ptr->m == NULL) + break; + + /* Second and subsequent clones */ + clone = xtables_malloc(sizeof(struct xtables_match)); + memcpy(clone, ptr, sizeof(struct xtables_match)); + clone->udata = NULL; + clone->mflags = 0; + /* This is a clone: */ + clone->next = clone; + + ptr = clone; + break; + } + } + +#ifndef NO_SHARED_LIBS + if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { + ptr = load_extension(xtables_libdir, afinfo->libprefix, + name, false); + + if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) + xt_params->exit_err(PARAMETER_PROBLEM, + "Couldn't load match `%s':%s\n", + name, strerror(errno)); + } +#else + if (ptr && !ptr->loaded) { + if (tryload != XTF_DONT_LOAD) + ptr->loaded = 1; + else + ptr = NULL; + } + if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { + xt_params->exit_err(PARAMETER_PROBLEM, + "Couldn't find match `%s'\n", name); + } +#endif + + if (ptr && matches) { + struct xtables_rule_match **i; + struct xtables_rule_match *newentry; + + newentry = xtables_malloc(sizeof(struct xtables_rule_match)); + + for (i = matches; *i; i = &(*i)->next) { + if (strcmp(name, (*i)->match->name) == 0) + (*i)->completed = true; + } + newentry->match = ptr; + newentry->completed = false; + newentry->next = NULL; + *i = newentry; + } + + return ptr; +} + +struct xtables_target * +xtables_find_target(const char *name, enum xtables_tryload tryload) +{ + struct xtables_target **dptr; + struct xtables_target *ptr; + + /* Standard target? */ + if (strcmp(name, "") == 0 + || strcmp(name, XTC_LABEL_ACCEPT) == 0 + || strcmp(name, XTC_LABEL_DROP) == 0 + || strcmp(name, XTC_LABEL_QUEUE) == 0 + || strcmp(name, XTC_LABEL_RETURN) == 0) + name = "standard"; + + /* Trigger delayed initialization */ + for (dptr = &xtables_pending_targets; *dptr; ) { + if (strcmp(name, (*dptr)->name) == 0) { + ptr = *dptr; + *dptr = (*dptr)->next; + ptr->next = NULL; + xtables_fully_register_pending_target(ptr); + } else { + dptr = &((*dptr)->next); + } + } + + for (ptr = xtables_targets; ptr; ptr = ptr->next) { + if (strcmp(name, ptr->name) == 0) + break; + } + +#ifndef NO_SHARED_LIBS + if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { + ptr = load_extension(xtables_libdir, afinfo->libprefix, + name, true); + + if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) + xt_params->exit_err(PARAMETER_PROBLEM, + "Couldn't load target `%s':%s\n", + name, strerror(errno)); + } +#else + if (ptr && !ptr->loaded) { + if (tryload != XTF_DONT_LOAD) + ptr->loaded = 1; + else + ptr = NULL; + } + if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) { + xt_params->exit_err(PARAMETER_PROBLEM, + "Couldn't find target `%s'\n", name); + } +#endif + + if (ptr) + ptr->used = 1; + + return ptr; +} + +static int compatible_revision(const char *name, uint8_t revision, int opt) +{ + struct xt_get_revision rev; + socklen_t s = sizeof(rev); + int max_rev, sockfd; + + sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); + if (sockfd < 0) { + if (errno == EPERM) { + /* revision 0 is always supported. */ + if (revision != 0) + fprintf(stderr, "%s: Could not determine whether " + "revision %u is supported, " + "assuming it is.\n", + name, revision); + return 1; + } + fprintf(stderr, "Could not open socket to kernel: %s\n", + strerror(errno)); + exit(1); + } + + if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { + fprintf(stderr, "Could not set close on exec: %s\n", + strerror(errno)); + exit(1); + } + + xtables_load_ko(xtables_modprobe_program, true); + + strcpy(rev.name, name); + rev.revision = revision; + + max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); + if (max_rev < 0) { + /* Definitely don't support this? */ + if (errno == ENOENT || errno == EPROTONOSUPPORT) { + close(sockfd); + return 0; + } else if (errno == ENOPROTOOPT) { + close(sockfd); + /* Assume only revision 0 support (old kernel) */ + return (revision == 0); + } else { + fprintf(stderr, "getsockopt failed strangely: %s\n", + strerror(errno)); + exit(1); + } + } + close(sockfd); + return 1; +} + + +static int compatible_match_revision(const char *name, uint8_t revision) +{ + return compatible_revision(name, revision, afinfo->so_rev_match); +} + +static int compatible_target_revision(const char *name, uint8_t revision) +{ + return compatible_revision(name, revision, afinfo->so_rev_target); +} + +static void xtables_check_options(const char *name, const struct option *opt) +{ + for (; opt->name != NULL; ++opt) + if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) { + fprintf(stderr, "%s: Extension %s uses invalid " + "option value %d\n",xt_params->program_name, + name, opt->val); + exit(1); + } +} + +void xtables_register_match(struct xtables_match *me) +{ + if (me->version == NULL) { + fprintf(stderr, "%s: match %s<%u> is missing a version\n", + xt_params->program_name, me->name, me->revision); + exit(1); + } + if (strcmp(me->version, XTABLES_VERSION) != 0) { + fprintf(stderr, "%s: match \"%s\" has version \"%s\", " + "but \"%s\" is required.\n", + xt_params->program_name, me->name, + me->version, XTABLES_VERSION); + exit(1); + } + + if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { + fprintf(stderr, "%s: match `%s' has invalid name\n", + xt_params->program_name, me->name); + exit(1); + } + + if (me->family >= NPROTO) { + fprintf(stderr, + "%s: BUG: match %s has invalid protocol family\n", + xt_params->program_name, me->name); + exit(1); + } + + if (me->x6_options != NULL) + xtables_option_metavalidate(me->name, me->x6_options); + if (me->extra_opts != NULL) + xtables_check_options(me->name, me->extra_opts); + + /* ignore not interested match */ + if (me->family != afinfo->family && me->family != AF_UNSPEC) + return; + + /* place on linked list of matches pending full registration */ + me->next = xtables_pending_matches; + xtables_pending_matches = me; +} + +static void xtables_fully_register_pending_match(struct xtables_match *me) +{ + struct xtables_match **i, *old; + + old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); + if (old) { + if (old->revision == me->revision && + old->family == me->family) { + fprintf(stderr, + "%s: match `%s' already registered.\n", + xt_params->program_name, me->name); + exit(1); + } + + /* Now we have two (or more) options, check compatibility. */ + if (compatible_match_revision(old->name, old->revision) + && old->revision > me->revision) + return; + + /* See if new match can be used. */ + if (!compatible_match_revision(me->name, me->revision)) + return; + + /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ + if (old->revision == me->revision && me->family == AF_UNSPEC) + return; + + /* Delete old one. */ + for (i = &xtables_matches; *i!=old; i = &(*i)->next); + *i = old->next; + } + + if (me->size != XT_ALIGN(me->size)) { + fprintf(stderr, "%s: match `%s' has invalid size %u.\n", + xt_params->program_name, me->name, + (unsigned int)me->size); + exit(1); + } + + /* Append to list. */ + for (i = &xtables_matches; *i; i = &(*i)->next); + me->next = NULL; + *i = me; + + me->m = NULL; + me->mflags = 0; +} + +void xtables_register_matches(struct xtables_match *match, unsigned int n) +{ + do { + xtables_register_match(&match[--n]); + } while (n > 0); +} + +void xtables_register_target(struct xtables_target *me) +{ + if (me->version == NULL) { + fprintf(stderr, "%s: target %s<%u> is missing a version\n", + xt_params->program_name, me->name, me->revision); + exit(1); + } + if (strcmp(me->version, XTABLES_VERSION) != 0) { + fprintf(stderr, "%s: target \"%s\" has version \"%s\", " + "but \"%s\" is required.\n", + xt_params->program_name, me->name, + me->version, XTABLES_VERSION); + exit(1); + } + + if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { + fprintf(stderr, "%s: target `%s' has invalid name\n", + xt_params->program_name, me->name); + exit(1); + } + + if (me->family >= NPROTO) { + fprintf(stderr, + "%s: BUG: target %s has invalid protocol family\n", + xt_params->program_name, me->name); + exit(1); + } + + if (me->x6_options != NULL) + xtables_option_metavalidate(me->name, me->x6_options); + if (me->extra_opts != NULL) + xtables_check_options(me->name, me->extra_opts); + + /* ignore not interested target */ + if (me->family != afinfo->family && me->family != AF_UNSPEC) + return; + + /* place on linked list of targets pending full registration */ + me->next = xtables_pending_targets; + xtables_pending_targets = me; +} + +static void xtables_fully_register_pending_target(struct xtables_target *me) +{ + struct xtables_target *old; + + old = xtables_find_target(me->name, XTF_DURING_LOAD); + if (old) { + struct xtables_target **i; + + if (old->revision == me->revision && + old->family == me->family) { + fprintf(stderr, + "%s: target `%s' already registered.\n", + xt_params->program_name, me->name); + exit(1); + } + + /* Now we have two (or more) options, check compatibility. */ + if (compatible_target_revision(old->name, old->revision) + && old->revision > me->revision) + return; + + /* See if new target can be used. */ + if (!compatible_target_revision(me->name, me->revision)) + return; + + /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ + if (old->revision == me->revision && me->family == AF_UNSPEC) + return; + + /* Delete old one. */ + for (i = &xtables_targets; *i!=old; i = &(*i)->next); + *i = old->next; + } + + if (me->size != XT_ALIGN(me->size)) { + fprintf(stderr, "%s: target `%s' has invalid size %u.\n", + xt_params->program_name, me->name, + (unsigned int)me->size); + exit(1); + } + + /* Prepend to list. */ + me->next = xtables_targets; + xtables_targets = me; + me->t = NULL; + me->tflags = 0; +} + +void xtables_register_targets(struct xtables_target *target, unsigned int n) +{ + do { + xtables_register_target(&target[--n]); + } while (n > 0); +} + +/** + * xtables_param_act - act on condition + * @status: a constant from enum xtables_exittype + * + * %XTF_ONLY_ONCE: print error message that option may only be used once. + * @p1: module name (e.g. "mark") + * @p2(...): option in conflict (e.g. "--mark") + * @p3(...): condition to match on (see extensions/ for examples) + * + * %XTF_NO_INVERT: option does not support inversion + * @p1: module name + * @p2: option in conflict + * @p3: condition to match on + * + * %XTF_BAD_VALUE: bad value for option + * @p1: module name + * @p2: option with which the problem occured (e.g. "--mark") + * @p3: string the user passed in (e.g. "99999999999999") + * + * %XTF_ONE_ACTION: two mutually exclusive actions have been specified + * @p1: module name + * + * Displays an error message and exits the program. + */ +void xtables_param_act(unsigned int status, const char *p1, ...) +{ + const char *p2, *p3; + va_list args; + bool b; + + va_start(args, p1); + + switch (status) { + case XTF_ONLY_ONCE: + p2 = va_arg(args, const char *); + b = va_arg(args, unsigned int); + if (!b) { + va_end(args); + return; + } + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: \"%s\" option may only be specified once", + p1, p2); + break; + case XTF_NO_INVERT: + p2 = va_arg(args, const char *); + b = va_arg(args, unsigned int); + if (!b) { + va_end(args); + return; + } + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: \"%s\" option cannot be inverted", p1, p2); + break; + case XTF_BAD_VALUE: + p2 = va_arg(args, const char *); + p3 = va_arg(args, const char *); + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: Bad value for \"%s\" option: \"%s\"", + p1, p2, p3); + break; + case XTF_ONE_ACTION: + b = va_arg(args, unsigned int); + if (!b) { + va_end(args); + return; + } + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: At most one action is possible", p1); + break; + default: + xt_params->exit_err(status, p1, args); + break; + } + + va_end(args); +} + +const char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) +{ + static char buf[20]; + const unsigned char *bytep = (const void *)&addrp->s_addr; + + sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); + return buf; +} + +static const char *ipaddr_to_host(const struct in_addr *addr) +{ + struct hostent *host; + + host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); + if (host == NULL) + return NULL; + + return host->h_name; +} + +static const char *ipaddr_to_network(const struct in_addr *addr) +{ + struct netent *net; + + if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) + return net->n_name; + + return NULL; +} + +const char *xtables_ipaddr_to_anyname(const struct in_addr *addr) +{ + const char *name; + + if ((name = ipaddr_to_host(addr)) != NULL || + (name = ipaddr_to_network(addr)) != NULL) + return name; + + return xtables_ipaddr_to_numeric(addr); +} + +const char *xtables_ipmask_to_numeric(const struct in_addr *mask) +{ + static char buf[20]; + uint32_t maskaddr, bits; + int i; + + maskaddr = ntohl(mask->s_addr); + + if (maskaddr == 0xFFFFFFFFL) + /* we don't want to see "/32" */ + return ""; + + i = 32; + bits = 0xFFFFFFFEL; + while (--i >= 0 && maskaddr != bits) + bits <<= 1; + if (i >= 0) + sprintf(buf, "/%d", i); + else + /* mask was not a decent combination of 1's and 0's */ + sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); + + return buf; +} + +static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) +{ + static struct in_addr addr; + unsigned char *addrp; + unsigned int onebyte; + char buf[20], *p, *q; + int i; + + /* copy dotted string, because we need to modify it */ + strncpy(buf, dotted, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + addrp = (void *)&addr.s_addr; + + p = buf; + for (i = 0; i < 3; ++i) { + if ((q = strchr(p, '.')) == NULL) { + if (is_mask) + return NULL; + + /* autocomplete, this is a network address */ + if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) + return NULL; + + addrp[i] = onebyte; + while (i < 3) + addrp[++i] = 0; + + return &addr; + } + + *q = '\0'; + if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) + return NULL; + + addrp[i] = onebyte; + p = q + 1; + } + + /* we have checked 3 bytes, now we check the last one */ + if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) + return NULL; + + addrp[3] = onebyte; + return &addr; +} + +struct in_addr *xtables_numeric_to_ipaddr(const char *dotted) +{ + return __numeric_to_ipaddr(dotted, false); +} + +struct in_addr *xtables_numeric_to_ipmask(const char *dotted) +{ + return __numeric_to_ipaddr(dotted, true); +} + +static struct in_addr *network_to_ipaddr(const char *name) +{ + static struct in_addr addr; + struct netent *net; + + if ((net = getnetbyname(name)) != NULL) { + if (net->n_addrtype != AF_INET) + return NULL; + addr.s_addr = htonl(net->n_net); + return &addr; + } + + return NULL; +} + +static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) +{ + struct hostent *host; + struct in_addr *addr; + unsigned int i; + + *naddr = 0; + if ((host = gethostbyname(name)) != NULL) { + if (host->h_addrtype != AF_INET || + host->h_length != sizeof(struct in_addr)) + return NULL; + + while (host->h_addr_list[*naddr] != NULL) + ++*naddr; + addr = xtables_calloc(*naddr, sizeof(struct in_addr)); + for (i = 0; i < *naddr; i++) + memcpy(&addr[i], host->h_addr_list[i], + sizeof(struct in_addr)); + return addr; + } + + return NULL; +} + +static struct in_addr * +ipparse_hostnetwork(const char *name, unsigned int *naddrs) +{ + struct in_addr *addrptmp, *addrp; + + if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || + (addrptmp = network_to_ipaddr(name)) != NULL) { + addrp = xtables_malloc(sizeof(struct in_addr)); + memcpy(addrp, addrptmp, sizeof(*addrp)); + *naddrs = 1; + return addrp; + } + if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) + return addrptmp; + + xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); +} + +static struct in_addr *parse_ipmask(const char *mask) +{ + static struct in_addr maskaddr; + struct in_addr *addrp; + unsigned int bits; + + if (mask == NULL) { + /* no mask at all defaults to 32 bits */ + maskaddr.s_addr = 0xFFFFFFFF; + return &maskaddr; + } + if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) + /* dotted_to_addr already returns a network byte order addr */ + return addrp; + if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) + xt_params->exit_err(PARAMETER_PROBLEM, + "invalid mask `%s' specified", mask); + if (bits != 0) { + maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); + return &maskaddr; + } + + maskaddr.s_addr = 0U; + return &maskaddr; +} + +void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, + struct in_addr **maskpp, unsigned int *naddrs) +{ + struct in_addr *addrp; + char buf[256], *p, *next; + unsigned int len, i, j, n, count = 1; + const char *loop = name; + + while ((loop = strchr(loop, ',')) != NULL) { + ++count; + ++loop; /* skip ',' */ + } + + *addrpp = xtables_malloc(sizeof(struct in_addr) * count); + *maskpp = xtables_malloc(sizeof(struct in_addr) * count); + + loop = name; + + for (i = 0; i < count; ++i) { + while (isspace(*loop)) + ++loop; + next = strchr(loop, ','); + if (next != NULL) + len = next - loop; + else + len = strlen(loop); + if (len > sizeof(buf) - 1) + xt_params->exit_err(PARAMETER_PROBLEM, + "Hostname too long"); + + strncpy(buf, loop, len); + buf[len] = '\0'; + if ((p = strrchr(buf, '/')) != NULL) { + *p = '\0'; + addrp = parse_ipmask(p + 1); + } else { + addrp = parse_ipmask(NULL); + } + memcpy(*maskpp + i, addrp, sizeof(*addrp)); + + /* if a null mask is given, the name is ignored, like in "any/0" */ + if ((*maskpp + i)->s_addr == 0) + /* + * A bit pointless to process multiple addresses + * in this case... + */ + strcpy(buf, "0.0.0.0"); + + addrp = ipparse_hostnetwork(buf, &n); + if (n > 1) { + count += n - 1; + *addrpp = xtables_realloc(*addrpp, + sizeof(struct in_addr) * count); + *maskpp = xtables_realloc(*maskpp, + sizeof(struct in_addr) * count); + for (j = 0; j < n; ++j) + /* for each new addr */ + memcpy(*addrpp + i + j, addrp + j, + sizeof(*addrp)); + for (j = 1; j < n; ++j) + /* for each new mask */ + memcpy(*maskpp + i + j, *maskpp + i, + sizeof(*addrp)); + i += n - 1; + } else { + memcpy(*addrpp + i, addrp, sizeof(*addrp)); + } + /* free what ipparse_hostnetwork had allocated: */ + free(addrp); + if (next == NULL) + break; + loop = next + 1; + } + *naddrs = count; + for (i = 0; i < count; ++i) + (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr; +} + + +/** + * xtables_ipparse_any - transform arbitrary name to in_addr + * + * Possible inputs (pseudo regex): + * m{^($hostname|$networkname|$ipaddr)(/$mask)?} + * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" + */ +void xtables_ipparse_any(const char *name, struct in_addr **addrpp, + struct in_addr *maskp, unsigned int *naddrs) +{ + unsigned int i, j, k, n; + struct in_addr *addrp; + char buf[256], *p; + + strncpy(buf, name, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + if ((p = strrchr(buf, '/')) != NULL) { + *p = '\0'; + addrp = parse_ipmask(p + 1); + } else { + addrp = parse_ipmask(NULL); + } + memcpy(maskp, addrp, sizeof(*maskp)); + + /* if a null mask is given, the name is ignored, like in "any/0" */ + if (maskp->s_addr == 0U) + strcpy(buf, "0.0.0.0"); + + addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); + n = *naddrs; + for (i = 0, j = 0; i < n; ++i) { + addrp[j++].s_addr &= maskp->s_addr; + for (k = 0; k < j - 1; ++k) + if (addrp[k].s_addr == addrp[j-1].s_addr) { + /* + * Nuke the dup by copying an address from the + * tail here, and check the current position + * again (--j). + */ + memcpy(&addrp[--j], &addrp[--*naddrs], + sizeof(struct in_addr)); + break; + } + } +} + +const char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) +{ + /* 0000:0000:0000:0000:0000:0000:000.000.000.000 + * 0000:0000:0000:0000:0000:0000:0000:0000 */ + static char buf[50+1]; + return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); +} + +static const char *ip6addr_to_host(const struct in6_addr *addr) +{ + static char hostname[NI_MAXHOST]; + struct sockaddr_in6 saddr; + int err; + + memset(&saddr, 0, sizeof(struct sockaddr_in6)); + memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); + saddr.sin6_family = AF_INET6; + + err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), + hostname, sizeof(hostname) - 1, NULL, 0, 0); + if (err != 0) { +#ifdef DEBUG + fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); +#endif + return NULL; + } + +#ifdef DEBUG + fprintf (stderr, "\naddr2host: %s\n", hostname); +#endif + return hostname; +} + +const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) +{ + const char *name; + + if ((name = ip6addr_to_host(addr)) != NULL) + return name; + + return xtables_ip6addr_to_numeric(addr); +} + +static int ip6addr_prefix_length(const struct in6_addr *k) +{ + unsigned int bits = 0; + uint32_t a, b, c, d; + + a = ntohl(k->s6_addr32[0]); + b = ntohl(k->s6_addr32[1]); + c = ntohl(k->s6_addr32[2]); + d = ntohl(k->s6_addr32[3]); + while (a & 0x80000000U) { + ++bits; + a <<= 1; + a |= (b >> 31) & 1; + b <<= 1; + b |= (c >> 31) & 1; + c <<= 1; + c |= (d >> 31) & 1; + d <<= 1; + } + if (a != 0 || b != 0 || c != 0 || d != 0) + return -1; + return bits; +} + +const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) +{ + static char buf[50+2]; + int l = ip6addr_prefix_length(addrp); + + if (l == -1) { + strcpy(buf, "/"); + strcat(buf, xtables_ip6addr_to_numeric(addrp)); + return buf; + } + sprintf(buf, "/%d", l); + return buf; +} + +struct in6_addr *xtables_numeric_to_ip6addr(const char *num) +{ + static struct in6_addr ap; + int err; + + if ((err = inet_pton(AF_INET6, num, &ap)) == 1) + return ≈ +#ifdef DEBUG + fprintf(stderr, "\nnumeric2addr: %d\n", err); +#endif + return NULL; +} + +static struct in6_addr * +host_to_ip6addr(const char *name, unsigned int *naddr) +{ + struct in6_addr *addr; + struct addrinfo hints; + struct addrinfo *res, *p; + int err; + unsigned int i; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_RAW; + + *naddr = 0; + if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { +#ifdef DEBUG + fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); +#endif + return NULL; + } else { + /* Find length of address chain */ + for (p = res; p != NULL; p = p->ai_next) + ++*naddr; +#ifdef DEBUG + fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, + xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); +#endif + /* Copy each element of the address chain */ + addr = xtables_calloc(*naddr, sizeof(struct in6_addr)); + for (i = 0, p = res; p != NULL; p = p->ai_next) + memcpy(&addr[i++], + &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr, + sizeof(struct in6_addr)); + freeaddrinfo(res); + return addr; + } + + return NULL; +} + +static struct in6_addr *network_to_ip6addr(const char *name) +{ + /* abort();*/ + /* TODO: not implemented yet, but the exception breaks the + * name resolvation */ + return NULL; +} + +static struct in6_addr * +ip6parse_hostnetwork(const char *name, unsigned int *naddrs) +{ + struct in6_addr *addrp, *addrptmp; + + if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || + (addrptmp = network_to_ip6addr(name)) != NULL) { + addrp = xtables_malloc(sizeof(struct in6_addr)); + memcpy(addrp, addrptmp, sizeof(*addrp)); + *naddrs = 1; + return addrp; + } + if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) + return addrp; + + xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); +} + +static struct in6_addr *parse_ip6mask(char *mask) +{ + static struct in6_addr maskaddr; + struct in6_addr *addrp; + unsigned int bits; + + if (mask == NULL) { + /* no mask at all defaults to 128 bits */ + memset(&maskaddr, 0xff, sizeof maskaddr); + return &maskaddr; + } + if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) + return addrp; + if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) + xt_params->exit_err(PARAMETER_PROBLEM, + "invalid mask `%s' specified", mask); + if (bits != 0) { + char *p = (void *)&maskaddr; + memset(p, 0xff, bits / 8); + memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); + p[bits/8] = 0xff << (8 - (bits & 7)); + return &maskaddr; + } + + memset(&maskaddr, 0, sizeof(maskaddr)); + return &maskaddr; +} + +void +xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, + struct in6_addr **maskpp, unsigned int *naddrs) +{ + static const struct in6_addr zero_addr; + struct in6_addr *addrp; + char buf[256], *p, *next; + unsigned int len, i, j, n, count = 1; + const char *loop = name; + + while ((loop = strchr(loop, ',')) != NULL) { + ++count; + ++loop; /* skip ',' */ + } + + *addrpp = xtables_malloc(sizeof(struct in6_addr) * count); + *maskpp = xtables_malloc(sizeof(struct in6_addr) * count); + + loop = name; + + for (i = 0; i < count /*NB: count can grow*/; ++i) { + while (isspace(*loop)) + ++loop; + next = strchr(loop, ','); + if (next != NULL) + len = next - loop; + else + len = strlen(loop); + if (len > sizeof(buf) - 1) + xt_params->exit_err(PARAMETER_PROBLEM, + "Hostname too long"); + + strncpy(buf, loop, len); + buf[len] = '\0'; + if ((p = strrchr(buf, '/')) != NULL) { + *p = '\0'; + addrp = parse_ip6mask(p + 1); + } else { + addrp = parse_ip6mask(NULL); + } + memcpy(*maskpp + i, addrp, sizeof(*addrp)); + + /* if a null mask is given, the name is ignored, like in "any/0" */ + if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0) + strcpy(buf, "::"); + + addrp = ip6parse_hostnetwork(buf, &n); + if (n > 1) { + count += n - 1; + *addrpp = xtables_realloc(*addrpp, + sizeof(struct in6_addr) * count); + *maskpp = xtables_realloc(*maskpp, + sizeof(struct in6_addr) * count); + for (j = 0; j < n; ++j) + /* for each new addr */ + memcpy(*addrpp + i + j, addrp + j, + sizeof(*addrp)); + for (j = 1; j < n; ++j) + /* for each new mask */ + memcpy(*maskpp + i + j, *maskpp + i, + sizeof(*addrp)); + i += n - 1; + } else { + memcpy(*addrpp + i, addrp, sizeof(*addrp)); + } + /* free what ip6parse_hostnetwork had allocated: */ + free(addrp); + if (next == NULL) + break; + loop = next + 1; + } + *naddrs = count; + for (i = 0; i < count; ++i) + for (j = 0; j < 4; ++j) + (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j]; +} + +void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, + struct in6_addr *maskp, unsigned int *naddrs) +{ + static const struct in6_addr zero_addr; + struct in6_addr *addrp; + unsigned int i, j, k, n; + char buf[256], *p; + + strncpy(buf, name, sizeof(buf) - 1); + buf[sizeof(buf)-1] = '\0'; + if ((p = strrchr(buf, '/')) != NULL) { + *p = '\0'; + addrp = parse_ip6mask(p + 1); + } else { + addrp = parse_ip6mask(NULL); + } + memcpy(maskp, addrp, sizeof(*maskp)); + + /* if a null mask is given, the name is ignored, like in "any/0" */ + if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0) + strcpy(buf, "::"); + + addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); + n = *naddrs; + for (i = 0, j = 0; i < n; ++i) { + for (k = 0; k < 4; ++k) + addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; + ++j; + for (k = 0; k < j - 1; ++k) + if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { + /* + * Nuke the dup by copying an address from the + * tail here, and check the current position + * again (--j). + */ + memcpy(&addrp[--j], &addrp[--*naddrs], + sizeof(struct in_addr)); + break; + } + } +} + +void xtables_save_string(const char *value) +{ + static const char no_quote_chars[] = "_-0123456789" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + static const char escape_chars[] = "\"\\'"; + size_t length; + const char *p; + + length = strspn(value, no_quote_chars); + if (length > 0 && value[length] == 0) { + /* no quoting required */ + putchar(' '); + fputs(value, stdout); + } else { + /* there is at least one dangerous character in the + value, which we have to quote. Write double quotes + around the value and escape special characters with + a backslash */ + printf(" \""); + + for (p = strpbrk(value, escape_chars); p != NULL; + p = strpbrk(value, escape_chars)) { + if (p > value) + fwrite(value, 1, p - value, stdout); + putchar('\\'); + putchar(*p); + value = p + 1; + } + + /* print the rest and finish the double quoted + string */ + fputs(value, stdout); + putchar('\"'); + } +} + +const struct xtables_pprot xtables_chain_protos[] = { + {"tcp", IPPROTO_TCP}, + {"sctp", IPPROTO_SCTP}, + {"udp", IPPROTO_UDP}, + {"udplite", IPPROTO_UDPLITE}, + {"icmp", IPPROTO_ICMP}, + {"icmpv6", IPPROTO_ICMPV6}, + {"ipv6-icmp", IPPROTO_ICMPV6}, + {"esp", IPPROTO_ESP}, + {"ah", IPPROTO_AH}, + {"ipv6-mh", IPPROTO_MH}, + {"mh", IPPROTO_MH}, + {"all", 0}, + {NULL}, +}; + +uint16_t +xtables_parse_protocol(const char *s) +{ + const struct protoent *pent; + unsigned int proto, i; + + if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) + return proto; + + /* first deal with the special case of 'all' to prevent + * people from being able to redefine 'all' in nsswitch + * and/or provoke expensive [not working] ldap/nis/... + * lookups */ + if (strcmp(s, "all") == 0) + return 0; + + pent = getprotobyname(s); + if (pent != NULL) + return pent->p_proto; + + for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { + if (xtables_chain_protos[i].name == NULL) + continue; + if (strcmp(s, xtables_chain_protos[i].name) == 0) + return xtables_chain_protos[i].num; + } + xt_params->exit_err(PARAMETER_PROBLEM, + "unknown protocol \"%s\" specified", s); + return -1; +} + +int kernel_version; + +void get_kernel_version(void) +{ + static struct utsname uts; + int x = 0, y = 0, z = 0; + + if (uname(&uts) == -1) { + fprintf(stderr, "Unable to retrieve kernel version.\n"); + xtables_free_opts(1); + exit(1); + } + + sscanf(uts.release, "%d.%d.%d", &x, &y, &z); + kernel_version = LINUX_VERSION(x, y, z); +} diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c new file mode 100644 index 00000000..5f617a42 --- /dev/null +++ b/libxtables/xtoptions.c @@ -0,0 +1,1171 @@ +/* + * Argument parser + * Copyright © Jan Engelhardt, 2011 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xtables.h" +#include "xshared.h" +#ifndef IPTOS_NORMALSVC +# define IPTOS_NORMALSVC 0 +#endif + +#define XTOPT_MKPTR(cb) \ + ((void *)((char *)(cb)->data + (cb)->entry->ptroff)) + +/** + * Simple key-value pairs for syslog levels + */ +struct syslog_level { + char name[8]; + uint8_t level; +}; + +struct tos_value_mask { + uint8_t value, mask; +}; + +static const size_t xtopt_psize[] = { + /* + * All types not listed here, and thus essentially being initialized to + * zero have zero on purpose. + */ + [XTTYPE_UINT8] = sizeof(uint8_t), + [XTTYPE_UINT16] = sizeof(uint16_t), + [XTTYPE_UINT32] = sizeof(uint32_t), + [XTTYPE_UINT64] = sizeof(uint64_t), + [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), + [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), + [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), + [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), + [XTTYPE_DOUBLE] = sizeof(double), + [XTTYPE_STRING] = -1, + [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), + [XTTYPE_HOST] = sizeof(union nf_inet_addr), + [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), + [XTTYPE_PROTOCOL] = sizeof(uint8_t), + [XTTYPE_PORT] = sizeof(uint16_t), + [XTTYPE_PORTRC] = sizeof(uint16_t[2]), + [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr), + [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]), +}; + +/** + * Creates getopt options from the x6-style option map, and assigns each a + * getopt id. + */ +struct option * +xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, + const struct xt_option_entry *entry, unsigned int *offset) +{ + unsigned int num_orig, num_old = 0, num_new, i; + struct option *merge, *mp; + + if (entry == NULL) + return oldopts; + for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig) + ; + if (oldopts != NULL) + for (num_old = 0; oldopts[num_old].name != NULL; ++num_old) + ; + for (num_new = 0; entry[num_new].name != NULL; ++num_new) + ; + + /* + * Since @oldopts also has @orig_opts already (and does so at the + * start), skip these entries. + */ + oldopts += num_orig; + num_old -= num_orig; + + merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1)); + if (merge == NULL) + return NULL; + + /* Let the base options -[ADI...] have precedence over everything */ + memcpy(merge, orig_opts, sizeof(*mp) * num_orig); + mp = merge + num_orig; + + /* Second, the new options */ + xt_params->option_offset += XT_OPTION_OFFSET_SCALE; + *offset = xt_params->option_offset; + + for (i = 0; i < num_new; ++i, ++mp, ++entry) { + mp->name = entry->name; + mp->has_arg = entry->type != XTTYPE_NONE; + mp->flag = NULL; + mp->val = entry->id + *offset; + } + + /* Third, the old options */ + memcpy(mp, oldopts, sizeof(*mp) * num_old); + mp += num_old; + xtables_free_opts(0); + + /* Clear trailing entry */ + memset(mp, 0, sizeof(*mp)); + return merge; +} + +/** + * Give the upper limit for a certain type. + */ +static uintmax_t xtopt_max_by_type(enum xt_option_type type) +{ + switch (type) { + case XTTYPE_UINT8: + case XTTYPE_UINT8RC: + return UINT8_MAX; + case XTTYPE_UINT16: + case XTTYPE_UINT16RC: + return UINT16_MAX; + case XTTYPE_UINT32: + case XTTYPE_UINT32RC: + return UINT32_MAX; + case XTTYPE_UINT64: + case XTTYPE_UINT64RC: + return UINT64_MAX; + default: + return 0; + } +} + +/** + * Return the size of a single entity based upon a type - predominantly an + * XTTYPE_UINT*RC type. + */ +static size_t xtopt_esize_by_type(enum xt_option_type type) +{ + switch (type) { + case XTTYPE_UINT8RC: + return xtopt_psize[XTTYPE_UINT8]; + case XTTYPE_UINT16RC: + return xtopt_psize[XTTYPE_UINT16]; + case XTTYPE_UINT32RC: + return xtopt_psize[XTTYPE_UINT32]; + case XTTYPE_UINT64RC: + return xtopt_psize[XTTYPE_UINT64]; + default: + return xtopt_psize[type]; + } +} + +/** + * Require a simple integer. + */ +static void xtopt_parse_int(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type); + uintmax_t value; + + if (cb->entry->min != 0) + lmin = cb->entry->min; + if (cb->entry->max != 0) + lmax = cb->entry->max; + + if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad value for option \"--%s\", " + "or out of range (%ju-%ju).\n", + cb->ext_name, entry->name, lmin, lmax); + + if (entry->type == XTTYPE_UINT8) { + cb->val.u8 = value; + if (entry->flags & XTOPT_PUT) + *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; + } else if (entry->type == XTTYPE_UINT16) { + cb->val.u16 = value; + if (entry->flags & XTOPT_PUT) + *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16; + } else if (entry->type == XTTYPE_UINT32) { + cb->val.u32 = value; + if (entry->flags & XTOPT_PUT) + *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; + } else if (entry->type == XTTYPE_UINT64) { + cb->val.u64 = value; + if (entry->flags & XTOPT_PUT) + *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; + } +} + +/** + * Require a simple floating point number. + */ +static void xtopt_parse_float(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + double value; + char *end; + + value = strtod(cb->arg, &end); + if (end == cb->arg || *end != '\0' || + (entry->min != entry->max && + (value < entry->min || value > entry->max))) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad value for option \"--%s\", " + "or out of range (%u-%u).\n", + cb->ext_name, entry->name, entry->min, entry->max); + + cb->val.dbl = value; + if (entry->flags & XTOPT_PUT) + *(double *)XTOPT_MKPTR(cb) = cb->val.dbl; +} + +/** + * Copy the parsed value to the appropriate entry in cb->val. + */ +static void xtopt_mint_value_to_cb(struct xt_option_call *cb, uintmax_t value) +{ + const struct xt_option_entry *entry = cb->entry; + + if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range)) + return; + if (entry->type == XTTYPE_UINT8RC) + cb->val.u8_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT16RC) + cb->val.u16_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT32RC) + cb->val.u32_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT64RC) + cb->val.u64_range[cb->nvals] = value; +} + +/** + * Copy the parsed value to the data area, using appropriate type access. + */ +static void xtopt_mint_value_to_ptr(struct xt_option_call *cb, void **datap, + uintmax_t value) +{ + const struct xt_option_entry *entry = cb->entry; + void *data = *datap; + + if (!(entry->flags & XTOPT_PUT)) + return; + if (entry->type == XTTYPE_UINT8RC) + *(uint8_t *)data = value; + else if (entry->type == XTTYPE_UINT16RC) + *(uint16_t *)data = value; + else if (entry->type == XTTYPE_UINT32RC) + *(uint32_t *)data = value; + else if (entry->type == XTTYPE_UINT64RC) + *(uint64_t *)data = value; + data += xtopt_esize_by_type(entry->type); + *datap = data; +} + +/** + * Multiple integer parse routine. + * + * This function is capable of parsing any number of fields. Only the first + * two values from the string will be put into @cb however (and as such, + * @cb->val.uXX_range is just that large) to cater for the few extensions that + * do not have a range[2] field, but {min, max}, and which cannot use + * XTOPT_POINTER. + */ +static void xtopt_parse_mint(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + const char *arg = cb->arg; + size_t esize = xtopt_esize_by_type(entry->type); + const uintmax_t lmax = xtopt_max_by_type(entry->type); + void *put = XTOPT_MKPTR(cb); + unsigned int maxiter; + uintmax_t value; + char *end = ""; + char sep = ':'; + + maxiter = entry->size / esize; + if (maxiter == 0) + maxiter = ARRAY_SIZE(cb->val.u32_range); + if (entry->size % esize != 0) + xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " + "not have proper size\n", __func__); + + cb->nvals = 0; + for (arg = cb->arg, end = (char *)arg; ; arg = end + 1) { + if (cb->nvals == maxiter) + xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " + "components for option \"--%s\" (max: %u)\n", + cb->ext_name, entry->name, maxiter); + if (*arg == '\0' || *arg == sep) { + /* Default range components when field not spec'd. */ + end = (char *)arg; + value = (cb->nvals == 1) ? lmax : 0; + } else { + if (!xtables_strtoul(arg, &end, &value, 0, lmax)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad value for option \"--%s\" near " + "\"%s\", or out of range (0-%ju).\n", + cb->ext_name, entry->name, arg, lmax); + if (*end != '\0' && *end != sep) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: Argument to \"--%s\" has " + "unexpected characters near \"%s\".\n", + cb->ext_name, entry->name, end); + } + xtopt_mint_value_to_cb(cb, value); + ++cb->nvals; + xtopt_mint_value_to_ptr(cb, &put, value); + if (*end == '\0') + break; + } +} + +static void xtopt_parse_string(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + size_t z = strlen(cb->arg); + char *p; + + if (entry->min != 0 && z < entry->min) + xt_params->exit_err(PARAMETER_PROBLEM, + "Argument must have a minimum length of " + "%u characters\n", entry->min); + if (entry->max != 0 && z > entry->max) + xt_params->exit_err(PARAMETER_PROBLEM, + "Argument must have a maximum length of " + "%u characters\n", entry->max); + if (!(entry->flags & XTOPT_PUT)) + return; + if (z >= entry->size) + z = entry->size - 1; + p = XTOPT_MKPTR(cb); + strncpy(p, cb->arg, z); + p[z] = '\0'; +} + +static const struct tos_symbol_info { + unsigned char value; + const char *name; +} tos_symbol_names[] = { + {IPTOS_LOWDELAY, "Minimize-Delay"}, + {IPTOS_THROUGHPUT, "Maximize-Throughput"}, + {IPTOS_RELIABILITY, "Maximize-Reliability"}, + {IPTOS_MINCOST, "Minimize-Cost"}, + {IPTOS_NORMALSVC, "Normal-Service"}, + {}, +}; + +/* + * tos_parse_numeric - parse a string like "15/255" + * + * @str: input string + * @tvm: (value/mask) tuple + * @max: maximum allowed value (must be pow(2,some_int)-1) + */ +static bool tos_parse_numeric(const char *str, struct xt_option_call *cb, + unsigned int max) +{ + unsigned int value; + char *end; + + xtables_strtoui(str, &end, &value, 0, max); + cb->val.tos_value = value; + cb->val.tos_mask = max; + + if (*end == '/') { + const char *p = end + 1; + + if (!xtables_strtoui(p, &end, &value, 0, max)) + xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", + str); + cb->val.tos_mask = value; + } + + if (*end != '\0') + xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str); + return true; +} + +/** + * @str: input string + * @tvm: (value/mask) tuple + * @def_mask: mask to force when a symbolic name is used + */ +static void xtopt_parse_tosmask(struct xt_option_call *cb) +{ + const struct tos_symbol_info *symbol; + char *tmp; + + if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) { + tos_parse_numeric(cb->arg, cb, UINT8_MAX); + return; + } + /* + * This is our way we deal with different defaults + * for different revisions. + */ + cb->val.tos_mask = cb->entry->max; + for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) + if (strcasecmp(cb->arg, symbol->name) == 0) { + cb->val.tos_value = symbol->value; + return; + } + + xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", + cb->arg); +} + +/** + * Validate the input for being conformant to "mark[/mask]". + */ +static void xtopt_parse_markmask(struct xt_option_call *cb) +{ + unsigned int mark = 0, mask = ~0U; + char *end; + + if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad mark value for option \"--%s\", " + "or out of range.\n", + cb->ext_name, cb->entry->name); + if (*end == '/' && + !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad mask value for option \"--%s\", " + "or out of range.\n", + cb->ext_name, cb->entry->name); + if (*end != '\0') + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: trailing garbage after value " + "for option \"--%s\".\n", + cb->ext_name, cb->entry->name); + cb->val.mark = mark; + cb->val.mask = mask; +} + +static int xtopt_sysloglvl_compare(const void *a, const void *b) +{ + const char *name = a; + const struct syslog_level *entry = b; + + return strcmp(name, entry->name); +} + +static void xtopt_parse_sysloglevel(struct xt_option_call *cb) +{ + static const struct syslog_level log_names[] = { /* must be sorted */ + {"alert", LOG_ALERT}, + {"crit", LOG_CRIT}, + {"debug", LOG_DEBUG}, + {"emerg", LOG_EMERG}, + {"error", LOG_ERR}, /* deprecated */ + {"info", LOG_INFO}, + {"notice", LOG_NOTICE}, + {"panic", LOG_EMERG}, /* deprecated */ + {"warning", LOG_WARNING}, + }; + const struct syslog_level *e; + unsigned int num = 0; + + if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) { + e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names), + sizeof(*log_names), xtopt_sysloglvl_compare); + if (e == NULL) + xt_params->exit_err(PARAMETER_PROBLEM, + "log level \"%s\" unknown\n", cb->arg); + num = e->level; + } + cb->val.syslog_level = num; + if (cb->entry->flags & XTOPT_PUT) + *(uint8_t *)XTOPT_MKPTR(cb) = num; +} + +static void *xtables_sa_host(const void *sa, unsigned int afproto) +{ + if (afproto == AF_INET6) + return &((struct sockaddr_in6 *)sa)->sin6_addr; + else if (afproto == AF_INET) + return &((struct sockaddr_in *)sa)->sin_addr; + return (void *)sa; +} + +static socklen_t xtables_sa_hostlen(unsigned int afproto) +{ + if (afproto == AF_INET6) + return sizeof(struct in6_addr); + else if (afproto == AF_INET) + return sizeof(struct in_addr); + return 0; +} + +/** + * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The + * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and + * @cb->val.hlen are set for completeness to the appropriate values. + */ +static void xtopt_parse_host(struct xt_option_call *cb) +{ + struct addrinfo hints = {.ai_family = afinfo->family}; + unsigned int adcount = 0; + struct addrinfo *res, *p; + int ret; + + ret = getaddrinfo(cb->arg, NULL, &hints, &res); + if (ret < 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "getaddrinfo: %s\n", gai_strerror(ret)); + + memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask)); + cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; + + for (p = res; p != NULL; p = p->ai_next) { + if (adcount == 0) { + memset(&cb->val.haddr, 0, sizeof(cb->val.haddr)); + memcpy(&cb->val.haddr, + xtables_sa_host(p->ai_addr, p->ai_family), + xtables_sa_hostlen(p->ai_family)); + ++adcount; + continue; + } + if (memcmp(&cb->val.haddr, + xtables_sa_host(p->ai_addr, p->ai_family), + xtables_sa_hostlen(p->ai_family)) != 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s resolves to more than one address\n", + cb->arg); + } + + freeaddrinfo(res); + if (cb->entry->flags & XTOPT_PUT) + /* Validation in xtables_option_metavalidate */ + memcpy(XTOPT_MKPTR(cb), &cb->val.haddr, + sizeof(cb->val.haddr)); +} + +/** + * @name: port name, or number as a string (e.g. "http" or "80") + * + * Resolve a port name to a number. Returns the port number in integral + * form on success, or <0 on error. (errno will not be set.) + */ +static int xtables_getportbyname(const char *name) +{ + struct addrinfo *res = NULL, *p; + int ret; + + ret = getaddrinfo(NULL, name, NULL, &res); + if (ret < 0) + return -1; + ret = -1; + for (p = res; p != NULL; p = p->ai_next) { + if (p->ai_family == AF_INET6) { + ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port; + break; + } else if (p->ai_family == AF_INET) { + ret = ((struct sockaddr_in *)p->ai_addr)->sin_port; + break; + } + } + freeaddrinfo(res); + if (ret < 0) + return ret; + return ntohs(ret); +} + +/** + * Validate and parse a protocol specification (number or name) by use of + * /etc/protocols and put the result into @cb->val.protocol. + */ +static void xtopt_parse_protocol(struct xt_option_call *cb) +{ + cb->val.protocol = xtables_parse_protocol(cb->arg); + if (cb->entry->flags & XTOPT_PUT) + *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol; +} + +/** + * Validate and parse a port specification and put the result into + * @cb->val.port. + */ +static void xtopt_parse_port(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + int ret; + + ret = xtables_getportbyname(cb->arg); + if (ret < 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "Port \"%s\" does not resolve to anything.\n", + cb->arg); + if (entry->flags & XTOPT_NBO) + ret = htons(ret); + cb->val.port = ret; + if (entry->flags & XTOPT_PUT) + *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; +} + +static void xtopt_parse_mport(struct xt_option_call *cb) +{ + static const size_t esize = sizeof(uint16_t); + const struct xt_option_entry *entry = cb->entry; + char *lo_arg, *wp_arg, *arg; + unsigned int maxiter; + int value; + + wp_arg = lo_arg = strdup(cb->arg); + if (lo_arg == NULL) + xt_params->exit_err(RESOURCE_PROBLEM, "strdup"); + + maxiter = entry->size / esize; + if (maxiter == 0) + maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */ + if (entry->size % esize != 0) + xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " + "not have proper size\n", __func__); + + cb->val.port_range[0] = 0; + cb->val.port_range[1] = UINT16_MAX; + cb->nvals = 0; + + while ((arg = strsep(&wp_arg, ":")) != NULL) { + if (cb->nvals == maxiter) + xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " + "components for option \"--%s\" (max: %u)\n", + cb->ext_name, entry->name, maxiter); + if (*arg == '\0') { + ++cb->nvals; + continue; + } + + value = xtables_getportbyname(arg); + if (value < 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "Port \"%s\" does not resolve to " + "anything.\n", arg); + if (entry->flags & XTOPT_NBO) + value = htons(value); + if (cb->nvals < ARRAY_SIZE(cb->val.port_range)) + cb->val.port_range[cb->nvals] = value; + ++cb->nvals; + } + + if (cb->nvals == 1) { + cb->val.port_range[1] = cb->val.port_range[0]; + ++cb->nvals; + } + if (entry->flags & XTOPT_PUT) + memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) * + (cb->nvals <= maxiter ? cb->nvals : maxiter)); + free(lo_arg); +} + +/** + * Parse an integer and ensure it is within the address family's prefix length + * limits. The result is stored in @cb->val.hlen. + */ +static void xtopt_parse_plen(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + unsigned int prefix_len = 128; /* happiness is a warm gcc */ + + cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; + if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad value for option \"--%s\", " + "or out of range (%u-%u).\n", + cb->ext_name, entry->name, 0, cb->val.hlen); + + cb->val.hlen = prefix_len; +} + +/** + * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to + * a bitmask, and make it available through @cb->val.hmask (hlen remains + * valid). If %XTOPT_PUT is used, hmask will be copied to the target area. + */ +static void xtopt_parse_plenmask(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + uint32_t *mask = cb->val.hmask.all; + + xtopt_parse_plen(cb); + + memset(mask, 0xFF, sizeof(union nf_inet_addr)); + /* This shifting is AF-independent. */ + if (cb->val.hlen == 0) { + mask[0] = mask[1] = mask[2] = mask[3] = 0; + } else if (cb->val.hlen <= 32) { + mask[0] <<= 32 - cb->val.hlen; + mask[1] = mask[2] = mask[3] = 0; + } else if (cb->val.hlen <= 64) { + mask[1] <<= 32 - (cb->val.hlen - 32); + mask[2] = mask[3] = 0; + } else if (cb->val.hlen <= 96) { + mask[2] <<= 32 - (cb->val.hlen - 64); + mask[3] = 0; + } else if (cb->val.hlen <= 128) { + mask[3] <<= 32 - (cb->val.hlen - 96); + } + mask[0] = htonl(mask[0]); + mask[1] = htonl(mask[1]); + mask[2] = htonl(mask[2]); + mask[3] = htonl(mask[3]); + if (entry->flags & XTOPT_PUT) + memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr)); +} + +static void xtopt_parse_hostmask(struct xt_option_call *cb) +{ + const char *orig_arg = cb->arg; + char *work, *p; + + if (strchr(cb->arg, '/') == NULL) { + xtopt_parse_host(cb); + return; + } + work = strdup(orig_arg); + if (work == NULL) + xt_params->exit_err(PARAMETER_PROBLEM, "strdup"); + p = strchr(work, '/'); /* by def this can't be NULL now */ + *p++ = '\0'; + /* + * Because xtopt_parse_host and xtopt_parse_plenmask would store + * different things in the same target area, XTTYPE_HOSTMASK must + * disallow XTOPT_PUT, which it does by forcing its absence, + * cf. not being listed in xtopt_psize. + */ + cb->arg = work; + xtopt_parse_host(cb); + cb->arg = p; + xtopt_parse_plenmask(cb); + cb->arg = orig_arg; +} + +static void xtopt_parse_ethermac(struct xt_option_call *cb) +{ + const char *arg = cb->arg; + unsigned int i; + char *end; + + for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) { + cb->val.ethermac[i] = strtoul(arg, &end, 16); + if (*end != ':' || end - arg > 2) + goto out; + arg = end + 1; + } + i = ARRAY_SIZE(cb->val.ethermac) - 1; + cb->val.ethermac[i] = strtoul(arg, &end, 16); + if (*end != '\0' || end - arg > 2) + goto out; + if (cb->entry->flags & XTOPT_PUT) + memcpy(XTOPT_MKPTR(cb), cb->val.ethermac, + sizeof(cb->val.ethermac)); + return; + out: + xt_params->exit_err(PARAMETER_PROBLEM, "ether"); +} + +static void (*const xtopt_subparse[])(struct xt_option_call *) = { + [XTTYPE_UINT8] = xtopt_parse_int, + [XTTYPE_UINT16] = xtopt_parse_int, + [XTTYPE_UINT32] = xtopt_parse_int, + [XTTYPE_UINT64] = xtopt_parse_int, + [XTTYPE_UINT8RC] = xtopt_parse_mint, + [XTTYPE_UINT16RC] = xtopt_parse_mint, + [XTTYPE_UINT32RC] = xtopt_parse_mint, + [XTTYPE_UINT64RC] = xtopt_parse_mint, + [XTTYPE_DOUBLE] = xtopt_parse_float, + [XTTYPE_STRING] = xtopt_parse_string, + [XTTYPE_TOSMASK] = xtopt_parse_tosmask, + [XTTYPE_MARKMASK32] = xtopt_parse_markmask, + [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, + [XTTYPE_HOST] = xtopt_parse_host, + [XTTYPE_HOSTMASK] = xtopt_parse_hostmask, + [XTTYPE_PROTOCOL] = xtopt_parse_protocol, + [XTTYPE_PORT] = xtopt_parse_port, + [XTTYPE_PORTRC] = xtopt_parse_mport, + [XTTYPE_PLEN] = xtopt_parse_plen, + [XTTYPE_PLENMASK] = xtopt_parse_plenmask, + [XTTYPE_ETHERMAC] = xtopt_parse_ethermac, +}; + +/** + * The master option parsing routine. May be used for the ".x6_parse" + * function pointer in extensions if fully automatic parsing is desired. + * It may be also called manually from a custom x6_parse function. + */ +void xtables_option_parse(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + unsigned int eflag = 1 << cb->entry->id; + + /* + * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use + * prevention. Though it turned out that this is too much typing (most + * of the options are one-time use only), so now we also have + * %XTOPT_MULTI. + */ + if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && + cb->xflags & eflag) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: option \"--%s\" can only be used once.\n", + cb->ext_name, cb->entry->name); + if (cb->invert && !(entry->flags & XTOPT_INVERT)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: option \"--%s\" cannot be inverted.\n", + cb->ext_name, entry->name); + if (entry->type != XTTYPE_NONE && optarg == NULL) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: option \"--%s\" requires an argument.\n", + cb->ext_name, entry->name); + /* + * Fill in fallback value for "nvals", in case an extension (as it + * happened with libxt_conntrack.2) tries to read it, despite not using + * a *RC option type. + */ + cb->nvals = 1; + if (entry->type <= ARRAY_SIZE(xtopt_subparse) && + xtopt_subparse[entry->type] != NULL) + xtopt_subparse[entry->type](cb); + /* Exclusion with other flags tested later in finalize. */ + cb->xflags |= 1 << entry->id; +} + +/** + * Verifies that an extension's option map descriptor is valid, and ought to + * be called right after the extension has been loaded, and before option + * merging/xfrm. + */ +void xtables_option_metavalidate(const char *name, + const struct xt_option_entry *entry) +{ + for (; entry->name != NULL; ++entry) { + if (entry->id >= CHAR_BIT * sizeof(unsigned int) || + entry->id >= XT_OPTION_OFFSET_SCALE) + xt_params->exit_err(OTHER_PROBLEM, + "Extension %s uses invalid ID %u\n", + name, entry->id); + if (!(entry->flags & XTOPT_PUT)) { + if (entry->ptroff != 0) + xt_params->exit_err(OTHER_PROBLEM, + "%s: ptroff for \"--%s\" is non-" + "zero but no XTOPT_PUT is specified. " + "Oversight?", name, entry->name); + continue; + } + if (entry->type >= ARRAY_SIZE(xtopt_psize) || + xtopt_psize[entry->type] == 0) + xt_params->exit_err(OTHER_PROBLEM, + "%s: entry type of option \"--%s\" cannot be " + "combined with XTOPT_PUT\n", + name, entry->name); + if (xtopt_psize[entry->type] != -1 && + xtopt_psize[entry->type] != entry->size) + xt_params->exit_err(OTHER_PROBLEM, + "%s: option \"--%s\" points to a memory block " + "of wrong size (expected %zu, got %zu)\n", + name, entry->name, + xtopt_psize[entry->type], entry->size); + } +} + +/** + * Find an option entry by its id. + */ +static const struct xt_option_entry * +xtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) +{ + for (; entry->name != NULL; ++entry) + if (entry->id == id) + return entry; + return NULL; +} + +/** + * @c: getopt id (i.e. with offset) + * @fw: struct ipt_entry or ip6t_entry + * + * Dispatch arguments to the appropriate parse function, based upon the + * extension's choice of API. + */ +void xtables_option_tpcall(unsigned int c, char **argv, bool invert, + struct xtables_target *t, void *fw) +{ + struct xt_option_call cb; + + if (t->x6_parse == NULL) { + if (t->parse != NULL) + t->parse(c - t->option_offset, argv, invert, + &t->tflags, fw, &t->t); + return; + } + + c -= t->option_offset; + cb.entry = xtables_option_lookup(t->x6_options, c); + if (cb.entry == NULL) + xtables_error(OTHER_PROBLEM, + "Extension does not know id %u\n", c); + cb.arg = optarg; + cb.invert = invert; + cb.ext_name = t->name; + cb.data = t->t->data; + cb.xflags = t->tflags; + cb.target = &t->t; + cb.xt_entry = fw; + cb.udata = t->udata; + t->x6_parse(&cb); + t->tflags = cb.xflags; +} + +/** + * @c: getopt id (i.e. with offset) + * @fw: struct ipt_entry or ip6t_entry + * + * Dispatch arguments to the appropriate parse function, based upon the + * extension's choice of API. + */ +void xtables_option_mpcall(unsigned int c, char **argv, bool invert, + struct xtables_match *m, void *fw) +{ + struct xt_option_call cb; + + if (m->x6_parse == NULL) { + if (m->parse != NULL) + m->parse(c - m->option_offset, argv, invert, + &m->mflags, fw, &m->m); + return; + } + + c -= m->option_offset; + cb.entry = xtables_option_lookup(m->x6_options, c); + if (cb.entry == NULL) + xtables_error(OTHER_PROBLEM, + "Extension does not know id %u\n", c); + cb.arg = optarg; + cb.invert = invert; + cb.ext_name = m->name; + cb.data = m->m->data; + cb.xflags = m->mflags; + cb.match = &m->m; + cb.xt_entry = fw; + cb.udata = m->udata; + m->x6_parse(&cb); + m->mflags = cb.xflags; +} + +/** + * @name: name of extension + * @entry: current option (from all ext's entries) being validated + * @xflags: flags the extension has collected + * @i: conflicting option (id) to test for + */ +static void +xtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, + const struct xt_option_entry *other, + unsigned int xflags) +{ + unsigned int ef = 1 << entry->id, of = 1 << other->id; + + if (entry->also & of && !(xflags & of)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: option \"--%s\" also requires \"--%s\".\n", + name, entry->name, other->name); + + if (!(entry->excl & of)) + /* Use of entry does not collide with other option, good. */ + return; + if ((xflags & (ef | of)) != (ef | of)) + /* Conflicting options were not used. */ + return; + + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: option \"--%s\" cannot be used together with \"--%s\".\n", + name, entry->name, other->name); +} + +/** + * @name: name of extension + * @xflags: accumulated flags + * @entry: extension's option table + * + * Check that all option constraints have been met. This effectively replaces + * ->final_check of the older API. + */ +void xtables_options_fcheck(const char *name, unsigned int xflags, + const struct xt_option_entry *table) +{ + const struct xt_option_entry *entry, *other; + unsigned int i; + + for (entry = table; entry->name != NULL; ++entry) { + if (entry->flags & XTOPT_MAND && + !(xflags & (1 << entry->id))) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: option \"--%s\" must be specified\n", + name, entry->name); + if (!(xflags & (1 << entry->id))) + /* Not required, not specified, thus skip. */ + continue; + + for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { + if (entry->id == i) + /* + * Avoid conflict with self. Multi-use check + * was done earlier in xtables_option_parse. + */ + continue; + other = xtables_option_lookup(table, i); + if (other == NULL) + continue; + xtables_option_fcheck2(name, entry, other, xflags); + } + } +} + +/** + * Dispatch arguments to the appropriate final_check function, based upon the + * extension's choice of API. + */ +void xtables_option_tfcall(struct xtables_target *t) +{ + if (t->x6_fcheck != NULL) { + struct xt_fcheck_call cb; + + cb.ext_name = t->name; + cb.data = t->t->data; + cb.xflags = t->tflags; + cb.udata = t->udata; + t->x6_fcheck(&cb); + } else if (t->final_check != NULL) { + t->final_check(t->tflags); + } + if (t->x6_options != NULL) + xtables_options_fcheck(t->name, t->tflags, t->x6_options); +} + +/** + * Dispatch arguments to the appropriate final_check function, based upon the + * extension's choice of API. + */ +void xtables_option_mfcall(struct xtables_match *m) +{ + if (m->x6_fcheck != NULL) { + struct xt_fcheck_call cb; + + cb.ext_name = m->name; + cb.data = m->m->data; + cb.xflags = m->mflags; + cb.udata = m->udata; + m->x6_fcheck(&cb); + } else if (m->final_check != NULL) { + m->final_check(m->mflags); + } + if (m->x6_options != NULL) + xtables_options_fcheck(m->name, m->mflags, m->x6_options); +} + +struct xtables_lmap *xtables_lmap_init(const char *file) +{ + struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; + char buf[512]; + FILE *fp; + char *cur, *nxt; + int id; + + fp = fopen(file, "re"); + if (fp == NULL) + return NULL; + + while (fgets(buf, sizeof(buf), fp) != NULL) { + cur = buf; + while (isspace(*cur)) + ++cur; + if (*cur == '#' || *cur == '\n' || *cur == '\0') + continue; + + /* iproute2 allows hex and dec format */ + errno = 0; + id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); + if (nxt == cur || errno != 0) + continue; + + /* same boundaries as in iproute2 */ + if (id < 0 || id > 255) + continue; + cur = nxt; + + if (!isspace(*cur)) + continue; + while (isspace(*cur)) + ++cur; + if (*cur == '#' || *cur == '\n' || *cur == '\0') + continue; + nxt = cur; + while (*nxt != '\0' && !isspace(*nxt)) + ++nxt; + if (nxt == cur) + continue; + *nxt = '\0'; + + /* found valid data */ + lmap_this = malloc(sizeof(*lmap_this)); + if (lmap_this == NULL) { + perror("malloc"); + goto out; + } + lmap_this->id = id; + lmap_this->name = strdup(cur); + if (lmap_this->name == NULL) { + free(lmap_this); + goto out; + } + lmap_this->next = NULL; + + if (lmap_prev != NULL) + lmap_prev->next = lmap_this; + else + lmap_head = lmap_this; + lmap_prev = lmap_this; + } + + fclose(fp); + return lmap_head; + out: + xtables_lmap_free(lmap_head); + return NULL; +} + +void xtables_lmap_free(struct xtables_lmap *head) +{ + struct xtables_lmap *next; + + for (; head != NULL; head = next) { + next = head->next; + free(head->name); + free(head); + } +} + +int xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) +{ + for (; head != NULL; head = head->next) + if (strcmp(head->name, name) == 0) + return head->id; + return -1; +} + +const char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) +{ + for (; head != NULL; head = head->next) + if (head->id == id) + return head->name; + return NULL; +} -- cgit v1.2.3 From d2b0eaa297dfa87f54b3fbcaa292f14d793e3f3c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Sep 2011 15:38:20 +0200 Subject: build: make check stage not fail when building statically Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 221c2c91..b088684e 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -73,8 +73,8 @@ all: ${targets} check check: ${targets} @echo " CHECK unknown symbols in .so files"; \ . ../libxtables/libxtables.la; \ - for i in "" lib*.so; do \ - [ -z "$$i" ] && continue; \ + for i in lib*.so; do \ + [ "$$i" = "lib*.so" ] && continue; \ LD_PRELOAD="$$dlname" LD_LIBRARY_PATH=../libxtables/.libs \ ldd -r $$i 2>&1 >/dev/null; \ done; -- cgit v1.2.3 From e5152bf4ebd4f573ae1d0770044e2bff7ab66d5e Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Wed, 28 Sep 2011 20:45:24 +0200 Subject: libxtables: Fix file descriptor leak in xtables_lmap_init on error Signed-off-by: Thomas Jarosch Signed-off-by: Pablo Neira Ayuso --- libxtables/xtoptions.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c index 5f617a42..452e0fef 100644 --- a/libxtables/xtoptions.c +++ b/libxtables/xtoptions.c @@ -1139,6 +1139,7 @@ struct xtables_lmap *xtables_lmap_init(const char *file) fclose(fp); return lmap_head; out: + fclose(fp); xtables_lmap_free(lmap_head); return NULL; } -- cgit v1.2.3 From 8fe22aa0a242314349f6cd7219b56a60a9d75276 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Mon, 5 Sep 2011 22:25:39 +0200 Subject: Improve readability of bitwise operation CLUSTERIP: improve readability of bitwise operation Signed-off-by: Thomas Jarosch Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_CLUSTERIP.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libipt_CLUSTERIP.c b/extensions/libipt_CLUSTERIP.c index 301e0e1d..f4b638b2 100644 --- a/extensions/libipt_CLUSTERIP.c +++ b/extensions/libipt_CLUSTERIP.c @@ -144,7 +144,7 @@ static void CLUSTERIP_print(const void *ip, const struct ipt_clusterip_tgt_info *cipinfo = (const struct ipt_clusterip_tgt_info *)target->data; - if (!cipinfo->flags & CLUSTERIP_FLAG_NEW) { + if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { printf(" CLUSTERIP"); return; } @@ -164,7 +164,7 @@ static void CLUSTERIP_save(const void *ip, const struct xt_entry_target *target) /* if this is not a new entry, we don't need to save target * parameters */ - if (!cipinfo->flags & CLUSTERIP_FLAG_NEW) + if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) return; printf(" --new --hashmode %s --clustermac %s --total-nodes %d --local-node %d --hash-init %u", -- cgit v1.2.3 From 3c461ceeed5f55599930051f6feaec014b08f730 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 31 Oct 2011 16:10:57 +0100 Subject: libxt_NFQUEUE: fix --queue-bypass ipt-save output else, this will print "--queue-num 0--queue-bypass ". Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_NFQUEUE.c | 2 +- tests/options-most.rules | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c index e47b586c..8c2f6999 100644 --- a/extensions/libxt_NFQUEUE.c +++ b/extensions/libxt_NFQUEUE.c @@ -152,7 +152,7 @@ static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target NFQUEUE_save_v1(ip, target); if (info->bypass) - printf("--queue-bypass "); + printf(" --queue-bypass"); } static void NFQUEUE_init_v1(struct xt_entry_target *t) diff --git a/tests/options-most.rules b/tests/options-most.rules index ae28b82d..75733615 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -178,6 +178,8 @@ -A ntarg -A ntarg -j NFQUEUE --queue-balance 8:99 -A ntarg +-A ntarg -j NFQUEUE --queue-num 0 --queue-bypass +-A ntarg -A ntarg -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms -A ntarg -A ntarg -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms -- cgit v1.2.3 From 3964023f8640b60456373825b326b91badd7a058 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 25 Nov 2011 15:36:56 +0100 Subject: libipt_SAME: set PROTO_RANDOM on all ranges Resolve the (justified) WTF remark to a clearer version of when/why PROTO_RANDOM needs to be set. Especially when --random is used before --to in SAME, it would have not been appleid. --- extensions/libipt_DNAT.c | 17 ++++++++++------- extensions/libipt_SAME.c | 24 ++++++++++++++---------- extensions/libipt_SNAT.c | 17 ++++++++++------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c index 3b55c69c..466c9def 100644 --- a/extensions/libipt_DNAT.c +++ b/extensions/libipt_DNAT.c @@ -174,21 +174,23 @@ static void DNAT_parse(struct xt_option_call *cb) "DNAT: Multiple --to-destination not supported"); } *cb->target = parse_to(cb->arg, portok, info); - /* WTF do we need this for?? */ - if (cb->xflags & F_RANDOM) - info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; cb->xflags |= F_X_TO_DEST; break; - case O_RANDOM: - if (cb->xflags & F_TO_DEST) - info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; - break; case O_PERSISTENT: info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; break; } } +static void DNAT_fcheck(struct xt_fcheck_call *cb) +{ + static const unsigned int f = F_TO_DEST | F_RANDOM; + struct nf_nat_multi_range *mr = cb->data; + + if ((cb->xflags & f) == f) + mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; +} + static void print_range(const struct nf_nat_range *r) { if (r->flags & IP_NAT_RANGE_MAP_IPS) { @@ -248,6 +250,7 @@ static struct xtables_target dnat_tg_reg = { .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), .help = DNAT_help, .x6_parse = DNAT_parse, + .x6_fcheck = DNAT_fcheck, .print = DNAT_print, .save = DNAT_save, .x6_options = DNAT_opts, diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c index 2ff6c82e..e603ef64 100644 --- a/extensions/libipt_SAME.c +++ b/extensions/libipt_SAME.c @@ -9,7 +9,8 @@ enum { O_TO_ADDR = 0, O_NODST, O_RANDOM, - F_RANDOM = 1 << O_RANDOM, + F_TO_ADDR = 1 << O_TO_ADDR, + F_RANDOM = 1 << O_RANDOM, }; static void SAME_help(void) @@ -73,7 +74,6 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range) static void SAME_parse(struct xt_option_call *cb) { struct ipt_same_info *mr = cb->data; - unsigned int count; xtables_option_parse(cb); switch (cb->entry->id) { @@ -84,22 +84,25 @@ static void SAME_parse(struct xt_option_call *cb) "is %i ranges.\n", IPT_SAME_MAX_RANGE); parse_to(cb->arg, &mr->range[mr->rangesize]); - /* WTF do we need this for? */ - if (cb->xflags & F_RANDOM) - mr->range[mr->rangesize].flags - |= IP_NAT_RANGE_PROTO_RANDOM; mr->rangesize++; break; case O_NODST: mr->info |= IPT_SAME_NODST; break; - case O_RANDOM: - for (count=0; count < mr->rangesize; count++) - mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM; - break; } } +static void SAME_fcheck(struct xt_fcheck_call *cb) +{ + static const unsigned int f = F_TO_ADDR | F_RANDOM; + struct ipt_same_info *mr = cb->data; + unsigned int count; + + if ((cb->xflags & f) == f) + for (count = 0; count < mr->rangesize; ++count) + mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM; +} + static void SAME_print(const void *ip, const struct xt_entry_target *target, int numeric) { @@ -166,6 +169,7 @@ static struct xtables_target same_tg_reg = { .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)), .help = SAME_help, .x6_parse = SAME_parse, + .x6_fcheck = SAME_fcheck, .print = SAME_print, .save = SAME_save, .x6_options = SAME_opts, diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index 80233060..c8cb26df 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -174,21 +174,23 @@ static void SNAT_parse(struct xt_option_call *cb) "SNAT: Multiple --to-source not supported"); } *cb->target = parse_to(cb->arg, portok, info); - /* WTF do we need this for?? */ - if (cb->xflags & F_RANDOM) - info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; cb->xflags |= F_X_TO_SRC; break; - case O_RANDOM: - if (cb->xflags & F_TO_SRC) - info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; - break; case O_PERSISTENT: info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; break; } } +static void SNAT_fcheck(struct xt_fcheck_call *cb) +{ + static const unsigned int f = F_TO_SRC | F_RANDOM; + struct nf_nat_multi_range *mr = cb->data; + + if ((cb->xflags & f) == f) + mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; +} + static void print_range(const struct nf_nat_range *r) { if (r->flags & IP_NAT_RANGE_MAP_IPS) { @@ -248,6 +250,7 @@ static struct xtables_target snat_tg_reg = { .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), .help = SNAT_help, .x6_parse = SNAT_parse, + .x6_fcheck = SNAT_fcheck, .print = SNAT_print, .save = SNAT_save, .x6_options = SNAT_opts, -- cgit v1.2.3 From 79ddbf202a06e6f018e087a328c2ca91e65a8463 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Wed, 30 Nov 2011 08:16:53 -0700 Subject: libxt_recent: Add support for --reap option Support for the reap option was merged in the kernel as of 2.6.35. Cc: Pablo Neira Ayuso Cc: Jan Engelhardt Signed-off-by: Tim Gardner --- extensions/libxt_recent.c | 17 ++++++++++++++++- extensions/libxt_recent.man | 5 +++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c index 1e1a111f..c7dce4e7 100644 --- a/extensions/libxt_recent.c +++ b/extensions/libxt_recent.c @@ -10,6 +10,7 @@ enum { O_UPDATE, O_REMOVE, O_SECONDS, + O_REAP, O_HITCOUNT, O_RTTL, O_NAME, @@ -19,6 +20,7 @@ enum { F_RCHECK = 1 << O_RCHECK, F_UPDATE = 1 << O_UPDATE, F_REMOVE = 1 << O_REMOVE, + F_SECONDS = 1 << O_SECONDS, F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE, }; @@ -33,7 +35,9 @@ static const struct xt_option_entry recent_opts[] = { {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE, .excl = F_ANY_OP, .flags = XTOPT_INVERT}, {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32, - .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)}, + .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds), .min = 1}, + {.name = "reap", .id = O_REAP, .type = XTTYPE_NONE, + .also = F_SECONDS }, {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32, .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)}, {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE, @@ -57,6 +61,8 @@ static void recent_help(void) " --seconds seconds For check and update commands above.\n" " Specifies that the match will only occur if source address last seen within\n" " the last 'seconds' seconds.\n" +" --reap Purge entries older then 'seconds'.\n" +" Can only be used in conjunction with the seconds option.\n" " --hitcount hits For check and update commands above.\n" " Specifies that the match will only occur if source address seen hits times.\n" " May be used in conjunction with the seconds option.\n" @@ -117,11 +123,16 @@ static void recent_parse(struct xt_option_call *cb) case O_RDEST: info->side = XT_RECENT_DEST; break; + case O_REAP: + info->check_set |= XT_RECENT_REAP; + break; } } static void recent_check(struct xt_fcheck_call *cb) { + struct xt_recent_mtinfo *info = cb->data; + if (!(cb->xflags & F_ANY_OP)) xtables_error(PARAMETER_PROBLEM, "recent: you must specify one of `--set', `--rcheck' " @@ -146,6 +157,8 @@ static void recent_print(const void *ip, const struct xt_entry_match *match, if (info->check_set & XT_RECENT_REMOVE) printf(" REMOVE"); if(info->seconds) printf(" seconds: %d", info->seconds); + if (info->check_set & XT_RECENT_REAP) + printf(" reap"); if(info->hit_count) printf(" hit_count: %d", info->hit_count); if (info->check_set & XT_RECENT_TTL) printf(" TTL-Match"); @@ -172,6 +185,8 @@ static void recent_save(const void *ip, const struct xt_entry_match *match) if (info->check_set & XT_RECENT_REMOVE) printf(" --remove"); if(info->seconds) printf(" --seconds %d", info->seconds); + if (info->check_set & XT_RECENT_REAP) + printf(" --reap"); if(info->hit_count) printf(" --hitcount %d", info->hit_count); if (info->check_set & XT_RECENT_TTL) printf(" --rttl"); diff --git a/extensions/libxt_recent.man b/extensions/libxt_recent.man index 0392c2ca..8043df4a 100644 --- a/extensions/libxt_recent.man +++ b/extensions/libxt_recent.man @@ -41,6 +41,11 @@ This option must be used in conjunction with one of \fB\-\-rcheck\fP or \fB\-\-update\fP. When used, this will narrow the match to only happen when the address is in the list and was seen within the last given number of seconds. .TP +\fB\-\-reap\fP +This option can only be used in conjunction with \fB\-\-seconds\fP. +When used, this will cause entries older than the last given number of seconds +to be purged. +.TP \fB\-\-hitcount\fP \fIhits\fP This option must be used in conjunction with one of \fB\-\-rcheck\fP or \fB\-\-update\fP. When used, this will narrow the match to only happen when the -- cgit v1.2.3 From 70af559db7732b6e06a57fca3611c86c6fa5dc00 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Dec 2011 02:44:05 +0100 Subject: doc: clarification on the meaning of -p 0 Signed-off-by: Jan Engelhardt --- iptables/ip6tables.8.in | 16 ++++++++++++---- iptables/iptables.8.in | 10 +++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 748cebba..65f38646 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -250,7 +250,11 @@ But IPv6 extension headers except \fBesp\fP are not allowed. \fBesp\fP and \fBipv6\-nonext\fP can be used with Kernel version 2.6.11 or later. A "!" argument before the protocol inverts the -test. The number zero is equivalent to \fBall\fP. "\fBall\fP" +test. The number zero is equivalent to \fBall\fP, which means that you cannot +test the protocol field for the value 0 directly. To match on a HBH header, +even if it were the last, you cannot use \fB\-p 0\fP, but always need +\fB\-m hbh\fP. +"\fBall\fP" will match with all protocols and is taken as default when this option is omitted. .TP @@ -357,15 +361,19 @@ corresponding to that rule's position in the chain. When adding or inserting rules into a chain, use \fIcommand\fP to load any necessary modules (targets, match extensions, etc). .SH MATCH EXTENSIONS -ip6tables can use extended packet matching modules. These are loaded -in two ways: implicitly, when \fB\-p\fP or \fB\-\-protocol\fP -is specified, or with the \fB\-m\fP or \fB\-\-match\fP +.PP +ip6tables can use extended packet matching modules +with the \fB\-m\fP or \fB\-\-match\fP options, followed by the matching module name; after these, various extra command line options become available, depending on the specific module. You can specify multiple extended match modules in one line, and you can use the \fB\-h\fP or \fB\-\-help\fP options after the module has been specified to receive help specific to that module. +.PP +If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an +unknown option is encountered, ip6tables will try load a match module of the +same name as the protocol, to try making the option available. .\" @MATCH@ .SH TARGET EXTENSIONS ip6tables can use extended target modules: the following are included diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 24618b7b..59d6e040 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -356,15 +356,19 @@ corresponding to that rule's position in the chain. When adding or inserting rules into a chain, use \fIcommand\fP to load any necessary modules (targets, match extensions, etc). .SH MATCH EXTENSIONS -iptables can use extended packet matching modules. These are loaded -in two ways: implicitly, when \fB\-p\fP or \fB\-\-protocol\fP -is specified, or with the \fB\-m\fP or \fB\-\-match\fP +.PP +iptables can use extended packet matching modules +with the \fB\-m\fP or \fB\-\-match\fP options, followed by the matching module name; after these, various extra command line options become available, depending on the specific module. You can specify multiple extended match modules in one line, and you can use the \fB\-h\fP or \fB\-\-help\fP options after the module has been specified to receive help specific to that module. +.PP +If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an +unknown option is encountered, iptables will try load a match module of the +same name as the protocol, to try making the option available. .\" @MATCH@ .SH TARGET EXTENSIONS iptables can use extended target modules: the following are included -- cgit v1.2.3 From b8c42eca0f224a00bf55b60ded81af14a1e07da1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Dec 2011 02:52:15 +0100 Subject: libiptc: provide separate pkgconfig files Signed-off-by: Jan Engelhardt --- configure.ac | 4 +++- libiptc/.gitignore | 2 +- libiptc/Makefile.am | 2 +- libiptc/libip4tc.pc.in | 10 ++++++++++ libiptc/libip6tc.pc.in | 10 ++++++++++ libiptc/libiptc.pc.in | 6 ++---- 6 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 libiptc/libip4tc.pc.in create mode 100644 libiptc/libip6tc.pc.in diff --git a/configure.ac b/configure.ac index 8afba8c1..298d551d 100644 --- a/configure.ac +++ b/configure.ac @@ -112,6 +112,8 @@ AC_SUBST([libxtables_vmajor]) AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc libipq/Makefile libipq/libipq.pc - libiptc/Makefile libiptc/libiptc.pc libxtables/Makefile utils/Makefile + libiptc/Makefile libiptc/libiptc.pc + libiptc/libip4tc.pc libiptc/libip6tc.pc + libxtables/Makefile utils/Makefile include/xtables.h include/iptables/internal.h]) AC_OUTPUT diff --git a/libiptc/.gitignore b/libiptc/.gitignore index 87675507..49ca83d0 100644 --- a/libiptc/.gitignore +++ b/libiptc/.gitignore @@ -1 +1 @@ -/libiptc.pc +/*.pc diff --git a/libiptc/Makefile.am b/libiptc/Makefile.am index 22c920f6..c170cb21 100644 --- a/libiptc/Makefile.am +++ b/libiptc/Makefile.am @@ -3,7 +3,7 @@ AM_CFLAGS = ${regular_CFLAGS} AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CPPFLAGS} -pkgconfig_DATA = libiptc.pc +pkgconfig_DATA = libiptc.pc libip4tc.pc libip6tc.pc lib_LTLIBRARIES = libip4tc.la libip6tc.la libiptc.la libiptc_la_SOURCES = diff --git a/libiptc/libip4tc.pc.in b/libiptc/libip4tc.pc.in new file mode 100644 index 00000000..5efa1ca2 --- /dev/null +++ b/libiptc/libip4tc.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libip4tc +Description: iptables IPv4 ruleset ADT and kernel interface +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lip4tc +Cflags: -I${includedir} diff --git a/libiptc/libip6tc.pc.in b/libiptc/libip6tc.pc.in new file mode 100644 index 00000000..30a61b22 --- /dev/null +++ b/libiptc/libip6tc.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libip6tc +Description: iptables IPv6 ruleset ADT and kernel interface +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lip6tc +Cflags: -I${includedir} diff --git a/libiptc/libiptc.pc.in b/libiptc/libiptc.pc.in index 99a35440..0264bf05 100644 --- a/libiptc/libiptc.pc.in +++ b/libiptc/libiptc.pc.in @@ -5,8 +5,6 @@ libdir=@libdir@ includedir=@includedir@ Name: libiptc -Description: iptables ruleset ADT and kernel interface +Description: iptables v4/v6 ruleset ADT and kernel interface Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -liptc -Libs.private: -lip4tc -lip6tc -Cflags: -I${includedir} +Requires: libip4tc libip6tc -- cgit v1.2.3 From 08628f20f492a1f9178f6df2a276f9a108ac0022 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 16 Dec 2011 18:34:06 +0100 Subject: libxt_connbytes: fix handling of --connbytes FROM quoting man page: match packets from a connection whose packets/bytes/average packet size is more than FROM and less than TO bytes/packets. if TO is omitted only FROM check is done. But, when TO was omitted, we did treat it like "x:x" which is not the same at all. Before commit 09631dc60ce41bc484a42fcf4d4ddf7036820bd1 (libxt_connbytes: use guided option parser), we failed to parse "--connbytes x" ('Bad range "x"'), but treated "x:" like "x:0xffffffff". Also, restore the "from must be smaller than to" check. Signed-off-by: Florian Westphal --- extensions/libxt_connbytes.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/extensions/libxt_connbytes.c b/extensions/libxt_connbytes.c index 46a7e4b9..ed2ad25d 100644 --- a/extensions/libxt_connbytes.c +++ b/extensions/libxt_connbytes.c @@ -37,9 +37,14 @@ static void connbytes_parse(struct xt_option_call *cb) switch (cb->entry->id) { case O_CONNBYTES: sinfo->count.from = cb->val.u64_range[0]; - sinfo->count.to = cb->val.u64_range[0]; + sinfo->count.to = UINT64_MAX; if (cb->nvals == 2) sinfo->count.to = cb->val.u64_range[1]; + + if (sinfo->count.to < sinfo->count.from) + xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu", + (unsigned long long)sinfo->count.from, + (unsigned long long)sinfo->count.to); if (cb->invert) { i = sinfo->count.from; sinfo->count.from = sinfo->count.to; @@ -107,19 +112,29 @@ static void print_direction(const struct xt_connbytes_info *sinfo) } } +static void print_from_to(const struct xt_connbytes_info *sinfo, const char *prefix) +{ + unsigned long long from, to; + + if (sinfo->count.from > sinfo->count.to) { + fputs(" !", stdout); + from = sinfo->count.to; + to = sinfo->count.from; + } else { + to = sinfo->count.to; + from = sinfo->count.from; + } + printf(" %sconnbytes %llu", prefix, from); + if (to && to < UINT64_MAX) + printf(":%llu", to); +} + static void connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct xt_connbytes_info *sinfo = (const void *)match->data; - if (sinfo->count.from > sinfo->count.to) - printf(" connbytes ! %llu:%llu", - (unsigned long long)sinfo->count.to, - (unsigned long long)sinfo->count.from); - else - printf(" connbytes %llu:%llu", - (unsigned long long)sinfo->count.from, - (unsigned long long)sinfo->count.to); + print_from_to(sinfo, ""); fputs(" connbytes mode", stdout); print_mode(sinfo); @@ -132,14 +147,7 @@ static void connbytes_save(const void *ip, const struct xt_entry_match *match) { const struct xt_connbytes_info *sinfo = (const void *)match->data; - if (sinfo->count.from > sinfo->count.to) - printf(" ! --connbytes %llu:%llu", - (unsigned long long)sinfo->count.to, - (unsigned long long)sinfo->count.from); - else - printf(" --connbytes %llu:%llu", - (unsigned long long)sinfo->count.from, - (unsigned long long)sinfo->count.to); + print_from_to(sinfo, "--"); fputs(" --connbytes-mode", stdout); print_mode(sinfo); -- cgit v1.2.3 From 1fda09431938321b1aed6b9cf0e4cbcefae39b11 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 30 Dec 2011 02:14:51 +0100 Subject: nfnl_osf: add missing libnfnetlink_CFLAGS to compile process --- utils/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/Makefile.am b/utils/Makefile.am index 306d9933..f1bbfc52 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,7 +1,8 @@ # -*- Makefile -*- AM_CFLAGS = ${regular_CFLAGS} -AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include +AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include \ + -I${top_srcdir}/include ${libnfnetlink_CFLAGS} sbin_PROGRAMS = nfnl_osf pkgdata_DATA = pf.os -- cgit v1.2.3 From 9e1bb81c7e9d2c402ac62e3955af144e49f96ad8 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Dec 2011 20:20:33 +0100 Subject: Update .gitignore Only ignore these paths if they are a directory. --- .gitignore | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 3e7def5f..deed2210 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,9 @@ *.oo *.so *.o -.deps +.deps/ .dirstamp -.libs +.libs/ Makefile Makefile.in @@ -22,7 +22,7 @@ Makefile.in /include/iptables/internal.h /aclocal.m4 -/autom4te*.cache +/autom4te.cache/ /compile /config.guess /config.h* -- cgit v1.2.3 From de26cd21f367d929a1aff41e268ce250ad49b04b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Dec 2011 20:21:27 +0100 Subject: build: use AC_CONFIG_AUX_DIR and stash away tools --- .gitignore | 12 ++---------- configure.ac | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index deed2210..8e082d23 100644 --- a/.gitignore +++ b/.gitignore @@ -23,16 +23,8 @@ Makefile.in /aclocal.m4 /autom4te.cache/ -/compile -/config.guess -/config.h* -/config.log -/config.status -/config.sub +/build-aux/ +/config.* /configure -/depcomp -/install-sh /libtool -/ltmain.sh -/missing /stamp-h1 diff --git a/configure.ac b/configure.ac index 298d551d..5679098c 100644 --- a/configure.ac +++ b/configure.ac @@ -5,6 +5,7 @@ AC_INIT([iptables], [1.4.12.1]) libxtables_vcurrent=7 libxtables_vage=0 +AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AC_PROG_INSTALL -- cgit v1.2.3 From f63d056f0c1ac122973a0859445c9cb5747e7213 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Dec 2011 20:22:26 +0100 Subject: Update .gitignore Split off extensions/.gitignore. --- .gitignore | 9 --------- extensions/.gitignore | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 extensions/.gitignore diff --git a/.gitignore b/.gitignore index 8e082d23..b7c3dfb8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ -.*.d -.*.dd *.a *.la *.lo -*.oo *.so *.o .deps/ @@ -12,12 +9,6 @@ Makefile Makefile.in -/extensions/GNUmakefile -/extensions/initext.c -/extensions/initext?.c -/extensions/matches?.man -/extensions/targets?.man - /include/xtables.h /include/iptables/internal.h diff --git a/extensions/.gitignore b/extensions/.gitignore new file mode 100644 index 00000000..2e74faf7 --- /dev/null +++ b/extensions/.gitignore @@ -0,0 +1,9 @@ +.*.d +.*.dd +*.oo + +/GNUmakefile +/initext.c +/initext?.c +/matches?.man +/targets?.man -- cgit v1.2.3 From 32d8532a37004e11e5994d93df5e249c43197930 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 18 Dec 2011 04:04:37 +0100 Subject: build: use delayed expansion on the user-settable variables Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index b088684e..84c85de7 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -1,26 +1,26 @@ # -*- Makefile -*- -top_builddir := @top_builddir@ -builddir := @builddir@ -top_srcdir := @top_srcdir@ -srcdir := @srcdir@ -ksourcedir := @ksourcedir@ -prefix := @prefix@ -exec_prefix := @exec_prefix@ -libdir := @libdir@ -libexecdir := @libexecdir@ -xtlibdir := @xtlibdir@ - -CC := @CC@ -CCLD := ${CC} -CFLAGS := @CFLAGS@ -CPPFLAGS := @CPPFLAGS@ -LDFLAGS := @LDFLAGS@ -regular_CFLAGS := @regular_CFLAGS@ -regular_CPPFLAGS := @regular_CPPFLAGS@ -kinclude_CPPFLAGS := @kinclude_CPPFLAGS@ - -AM_CFLAGS := ${regular_CFLAGS} +top_builddir = @top_builddir@ +builddir = @builddir@ +top_srcdir = @top_srcdir@ +srcdir = @srcdir@ +ksourcedir = @ksourcedir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +xtlibdir = @xtlibdir@ + +CC = @CC@ +CCLD = ${CC} +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +regular_CFLAGS = @regular_CFLAGS@ +regular_CPPFLAGS = @regular_CPPFLAGS@ +kinclude_CPPFLAGS = @kinclude_CPPFLAGS@ + +AM_CFLAGS = ${regular_CFLAGS} AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_builddir} -I${top_srcdir}/include ${kinclude_CPPFLAGS} AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@ -- cgit v1.2.3 From 79cefabaac7a0ecf864db7da2a665845c0789f10 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 30 Dec 2011 02:14:00 +0100 Subject: extensions: link on libxtables and check symbols Have each extension link against libxtables.so; with this, all home symbols are known at link time and we can use ld's --no-undefined to run the check, dropping the homebrew solution. By having libxtables.so required by extensions, package managers' automatic dependency discovery will become effective so that manual dependencies for distros with split extension packages (e.g. OpenWRT) will not be necessary anymore. Signed-off-by: Jan Engelhardt --- configure.ac | 10 ++++++++++ extensions/GNUmakefile.in | 14 +++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 5679098c..0f85b831 100644 --- a/configure.ac +++ b/configure.ac @@ -58,6 +58,15 @@ AX_CHECK_LINKER_FLAGS([-Wl,--no-as-needed], [libiptc_LDFLAGS2="-Wl,--no-as-needed"]) AC_SUBST([libiptc_LDFLAGS2]) +AC_MSG_CHECKING([whether $LD knows -Wl,--no-undefined]) +saved_LDFLAGS="$LDFLAGS"; +LDFLAGS="-Wl,--no-undefined"; +AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) {}])], + [noundef_LDFLAGS="$LDFLAGS"; AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])] +) +LDFLAGS="$saved_LDFLAGS"; + blacklist_modules=""; AC_CHECK_HEADERS([linux/dccp.h linux/ip_vs.h linux/magic.h linux/proc_fs.h]) @@ -99,6 +108,7 @@ pkgdatadir='${datadir}/xtables'; AC_SUBST([regular_CFLAGS]) AC_SUBST([regular_CPPFLAGS]) +AC_SUBST([noundef_LDFLAGS]) AC_SUBST([kinclude_CPPFLAGS]) AC_SUBST([kbuilddir]) AC_SUBST([ksourcedir]) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 84c85de7..218dc3ad 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -23,6 +23,7 @@ kinclude_CPPFLAGS = @kinclude_CPPFLAGS@ AM_CFLAGS = ${regular_CFLAGS} AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_builddir} -I${top_srcdir}/include ${kinclude_CPPFLAGS} AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@ +AM_LDFLAGS = @noundef_LDFLAGS@ ifeq (${V},) AM_LIBTOOL_SILENT = --silent @@ -68,16 +69,7 @@ targets_install := .PHONY: all install clean distclean FORCE -all: ${targets} check - -check: ${targets} - @echo " CHECK unknown symbols in .so files"; \ - . ../libxtables/libxtables.la; \ - for i in lib*.so; do \ - [ "$$i" = "lib*.so" ] && continue; \ - LD_PRELOAD="$$dlname" LD_LIBRARY_PATH=../libxtables/.libs \ - ldd -r $$i 2>&1 >/dev/null; \ - done; +all: ${targets} install: ${targets_install} @mkdir -p "${DESTDIR}${xtlibdir}"; @@ -99,7 +91,7 @@ init%.o: init%.c # Shared libraries # lib%.so: lib%.oo - ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< ${$*_LIBADD}; + ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD}; lib%.oo: ${srcdir}/lib%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; -- cgit v1.2.3 From 3852ebcd25f65a42b552a0c705126c4b22da437e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 2 Jan 2012 18:19:09 +0100 Subject: Bump version to 1.4.12.2 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 298d551d..2e5aedb5 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.12.1]) +AC_INIT([iptables], [1.4.12.2]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=7 -- cgit v1.2.3 From 166b92d3fb2a7fc008df1b59332ef528a9a573ea Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 14 Jul 2011 23:56:47 +0200 Subject: extensions: add rpfilter module Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_rpfilter.c | 96 +++++++++++++++++++++++++++++++++++ extensions/libxt_rpfilter.man | 38 ++++++++++++++ include/linux/netfilter/xt_rpfilter.h | 17 +++++++ 3 files changed, 151 insertions(+) create mode 100644 extensions/libxt_rpfilter.c create mode 100644 extensions/libxt_rpfilter.man create mode 100644 include/linux/netfilter/xt_rpfilter.h diff --git a/extensions/libxt_rpfilter.c b/extensions/libxt_rpfilter.c new file mode 100644 index 00000000..168e703f --- /dev/null +++ b/extensions/libxt_rpfilter.c @@ -0,0 +1,96 @@ +#include +#include +#include + +enum { + O_RPF_LOOSE = 0, + O_RPF_VMARK = 1, + O_RPF_ACCEPT_LOCAL = 2, + O_RPF_INVERT = 3, +}; + +static void rpfilter_help(void) +{ + printf( +"rpfilter match options:\n" +" --loose permit reverse path via any interface\n" +" --validmark use skb nfmark when performing route lookup\n" +" --accept-local do not reject packets with a local source address\n" +" --invert match packets that failed the reverse path test\n" + ); +} + +static const struct xt_option_entry rpfilter_opts[] = { + {.name = "loose", .id = O_RPF_LOOSE, .type = XTTYPE_NONE, }, + {.name = "validmark", .id = O_RPF_VMARK, .type = XTTYPE_NONE, }, + {.name = "accept-local", .id = O_RPF_ACCEPT_LOCAL, .type = XTTYPE_NONE, }, + {.name = "invert", .id = O_RPF_INVERT, .type = XTTYPE_NONE, }, + XTOPT_TABLEEND, +}; + +static void rpfilter_parse(struct xt_option_call *cb) +{ + struct xt_rpfilter_info *rpfinfo = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_RPF_LOOSE: + rpfinfo->flags |= XT_RPFILTER_LOOSE; + break; + case O_RPF_VMARK: + rpfinfo->flags |= XT_RPFILTER_VALID_MARK; + break; + case O_RPF_ACCEPT_LOCAL: + rpfinfo->flags |= XT_RPFILTER_ACCEPT_LOCAL; + break; + case O_RPF_INVERT: + rpfinfo->flags |= XT_RPFILTER_INVERT; + break; + } +} + +static void +rpfilter_print_prefix(const void *ip, const void *matchinfo, + const char *prefix) +{ + const struct xt_rpfilter_info *info = matchinfo; + if (info->flags & XT_RPFILTER_LOOSE) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_LOOSE].name); + if (info->flags & XT_RPFILTER_VALID_MARK) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_VMARK].name); + if (info->flags & XT_RPFILTER_ACCEPT_LOCAL) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_ACCEPT_LOCAL].name); + if (info->flags & XT_RPFILTER_INVERT) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_INVERT].name); +} + + +static void +rpfilter_print(const void *ip, const struct xt_entry_match *match, int numeric) +{ + printf(" rpfilter"); + return rpfilter_print_prefix(ip, match->data, ""); +} + +static void rpfilter_save(const void *ip, const struct xt_entry_match *match) +{ + return rpfilter_print_prefix(ip, match->data, "--"); +} + +static struct xtables_match rpfilter_match = { + .family = NFPROTO_UNSPEC, + .name = "rpfilter", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_rpfilter_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_rpfilter_info)), + .help = rpfilter_help, + .print = rpfilter_print, + .save = rpfilter_save, + .x6_parse = rpfilter_parse, + .x6_options = rpfilter_opts, +}; + +void _init(void) +{ + xtables_register_match(&rpfilter_match); +} diff --git a/extensions/libxt_rpfilter.man b/extensions/libxt_rpfilter.man new file mode 100644 index 00000000..aeb4a9d1 --- /dev/null +++ b/extensions/libxt_rpfilter.man @@ -0,0 +1,38 @@ +Performs a reverse path filter test on a packet. +If a reply to the packet would be sent via the same interface +that the packet arrived on, the packet will match. +Note that, unlike the in-kernel rp_filter, packets protected +by IPSec are not treated specially. Combine this match with +the policy match if you want this. +Also, packets arriving via the loopback interface are always permitted. +This match can only be used in the PREROUTING chain of the raw or mangle table. +.TP +\fB\-\-loose\fP +Used to specifiy that the reverse path filter test should match +even if the selected output device is not the expected one. +.TP +\fB\-\-validmark\fP +Also use the packets' nfmark value when performing the reverse path route lookup. +.TP +\fB\-\-accept\-local\fP +This will permit packets arriving from the network with a source address that is also +assigned to the local machine. +\fB\-\-invert\fP +This will invert the sense of the match. Instead of matching packets that passed the +reverse path filter test, match those that have failed it. +.PP +Example to log and drop packets failing the reverse path filter test: + +iptables \-t raw \-N RPFILTER + +iptables \-t raw \-A RPFILTER \-m rpfilter \-j RETURN + +iptables \-t raw \-A RPFILTER \-m limit \-\-limit 10/minute \-j NFLOG \-\-nflog\-prefix "rpfilter drop" + +iptables \-t raw \-A RPFILTER \-j DROP + +iptables \-t raw \-A PREROUTING \-j RPFILTER + +Example to drop failed packets, without logging: + +iptables \-t raw \-A RPFILTER \-m rpfilter \-\-invert \-j DROP diff --git a/include/linux/netfilter/xt_rpfilter.h b/include/linux/netfilter/xt_rpfilter.h new file mode 100644 index 00000000..672b6051 --- /dev/null +++ b/include/linux/netfilter/xt_rpfilter.h @@ -0,0 +1,17 @@ +#ifndef _XT_RPATH_H +#define _XT_RPATH_H + +#include + +enum { + XT_RPFILTER_LOOSE = 1 << 0, + XT_RPFILTER_VALID_MARK = 1 << 1, + XT_RPFILTER_ACCEPT_LOCAL = 1 << 2, + XT_RPFILTER_INVERT = 1 << 3, +}; + +struct xt_rpfilter_info { + __u8 flags; +}; + +#endif -- cgit v1.2.3 From 98e1769b65b71989e3f16b25529b40f374aef323 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 28 Dec 2011 14:27:47 +0100 Subject: extensions: add IPv6 capable ECN match extension Patrick submitted this patch by 9th Jun 2011, I'm recovering and applying it to iptables. Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_ecn.c | 137 -------------------------------- extensions/libipt_ecn.man | 11 --- extensions/libxt_ecn.c | 138 +++++++++++++++++++++++++++++++++ extensions/libxt_ecn.man | 11 +++ include/linux/netfilter/xt_ecn.h | 33 ++++++++ include/linux/netfilter_ipv4/ipt_ecn.h | 35 --------- 6 files changed, 182 insertions(+), 183 deletions(-) delete mode 100644 extensions/libipt_ecn.c delete mode 100644 extensions/libipt_ecn.man create mode 100644 extensions/libxt_ecn.c create mode 100644 extensions/libxt_ecn.man create mode 100644 include/linux/netfilter/xt_ecn.h delete mode 100644 include/linux/netfilter_ipv4/ipt_ecn.h diff --git a/extensions/libipt_ecn.c b/extensions/libipt_ecn.c deleted file mode 100644 index 56a0347e..00000000 --- a/extensions/libipt_ecn.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Shared library add-on to iptables for ECN matching - * - * (C) 2002 by Harald Welte - * - * This program is distributed under the terms of GNU GPL v2, 1991 - * - * libipt_ecn.c borrowed heavily from libipt_dscp.c - * - */ -#include -#include -#include - -enum { - O_ECN_TCP_CWR = 0, - O_ECN_TCP_ECE, - O_ECN_IP_ECT, -}; - -static void ecn_help(void) -{ - printf( -"ECN match options\n" -"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n" -"[!] --ecn-tcp-ece Match ECE bit of TCP header\n" -"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n"); -} - -static const struct xt_option_entry ecn_opts[] = { - {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE, - .flags = XTOPT_INVERT}, - {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE, - .flags = XTOPT_INVERT}, - {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, - .min = 0, .max = 3, .flags = XTOPT_INVERT}, - XTOPT_TABLEEND, -}; - -static void ecn_parse(struct xt_option_call *cb) -{ - struct ipt_ecn_info *einfo = cb->data; - - xtables_option_parse(cb); - switch (cb->entry->id) { - case O_ECN_TCP_CWR: - einfo->operation |= IPT_ECN_OP_MATCH_CWR; - if (cb->invert) - einfo->invert |= IPT_ECN_OP_MATCH_CWR; - break; - case O_ECN_TCP_ECE: - einfo->operation |= IPT_ECN_OP_MATCH_ECE; - if (cb->invert) - einfo->invert |= IPT_ECN_OP_MATCH_ECE; - break; - case O_ECN_IP_ECT: - if (cb->invert) - einfo->invert |= IPT_ECN_OP_MATCH_IP; - einfo->operation |= IPT_ECN_OP_MATCH_IP; - einfo->ip_ect = cb->val.u8; - break; - } -} - -static void ecn_check(struct xt_fcheck_call *cb) -{ - if (cb->xflags == 0) - xtables_error(PARAMETER_PROBLEM, - "ECN match: some option required"); -} - -static void ecn_print(const void *ip, const struct xt_entry_match *match, - int numeric) -{ - const struct ipt_ecn_info *einfo = - (const struct ipt_ecn_info *)match->data; - - printf(" ECN match"); - - if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { - printf(" %sECE", - (einfo->invert & IPT_ECN_OP_MATCH_ECE) ? "!" : ""); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { - printf(" %sCWR", - (einfo->invert & IPT_ECN_OP_MATCH_CWR) ? "!" : ""); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_IP) { - printf(" %sECT=%d", - (einfo->invert & IPT_ECN_OP_MATCH_IP) ? "!" : "", - einfo->ip_ect); - } -} - -static void ecn_save(const void *ip, const struct xt_entry_match *match) -{ - const struct ipt_ecn_info *einfo = - (const struct ipt_ecn_info *)match->data; - - if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { - if (einfo->invert & IPT_ECN_OP_MATCH_ECE) - printf(" !"); - printf(" --ecn-tcp-ece"); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { - if (einfo->invert & IPT_ECN_OP_MATCH_CWR) - printf(" !"); - printf(" --ecn-tcp-cwr"); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_IP) { - if (einfo->invert & IPT_ECN_OP_MATCH_IP) - printf(" !"); - printf(" --ecn-ip-ect %d", einfo->ip_ect); - } -} - -static struct xtables_match ecn_mt_reg = { - .name = "ecn", - .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_ecn_info)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)), - .help = ecn_help, - .print = ecn_print, - .save = ecn_save, - .x6_parse = ecn_parse, - .x6_fcheck = ecn_check, - .x6_options = ecn_opts, -}; - -void _init(void) -{ - xtables_register_match(&ecn_mt_reg); -} diff --git a/extensions/libipt_ecn.man b/extensions/libipt_ecn.man deleted file mode 100644 index 7f806477..00000000 --- a/extensions/libipt_ecn.man +++ /dev/null @@ -1,11 +0,0 @@ -This allows you to match the ECN bits of the IPv4 and TCP header. ECN is the Explicit Congestion Notification mechanism as specified in RFC3168 -.TP -[\fB!\fP] \fB\-\-ecn\-tcp\-cwr\fP -This matches if the TCP ECN CWR (Congestion Window Received) bit is set. -.TP -[\fB!\fP] \fB\-\-ecn\-tcp\-ece\fP -This matches if the TCP ECN ECE (ECN Echo) bit is set. -.TP -[\fB!\fP] \fB\-\-ecn\-ip\-ect\fP \fInum\fP -This matches a particular IPv4 ECT (ECN-Capable Transport). You have to specify -a number between `0' and `3'. diff --git a/extensions/libxt_ecn.c b/extensions/libxt_ecn.c new file mode 100644 index 00000000..286782a3 --- /dev/null +++ b/extensions/libxt_ecn.c @@ -0,0 +1,138 @@ +/* Shared library add-on to iptables for ECN matching + * + * (C) 2002 by Harald Welte + * (C) 2011 by Patrick McHardy + * + * This program is distributed under the terms of GNU GPL v2, 1991 + * + * libipt_ecn.c borrowed heavily from libipt_dscp.c + * + */ +#include +#include +#include + +enum { + O_ECN_TCP_CWR = 0, + O_ECN_TCP_ECE, + O_ECN_IP_ECT, +}; + +static void ecn_help(void) +{ + printf( +"ECN match options\n" +"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n" +"[!] --ecn-tcp-ece Match ECE bit of TCP header\n" +"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4/IPv6 header\n"); +} + +static const struct xt_option_entry ecn_opts[] = { + {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, + {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, + {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, + .min = 0, .max = 3, .flags = XTOPT_INVERT}, + XTOPT_TABLEEND, +}; + +static void ecn_parse(struct xt_option_call *cb) +{ + struct xt_ecn_info *einfo = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_ECN_TCP_CWR: + einfo->operation |= XT_ECN_OP_MATCH_CWR; + if (cb->invert) + einfo->invert |= XT_ECN_OP_MATCH_CWR; + break; + case O_ECN_TCP_ECE: + einfo->operation |= XT_ECN_OP_MATCH_ECE; + if (cb->invert) + einfo->invert |= XT_ECN_OP_MATCH_ECE; + break; + case O_ECN_IP_ECT: + if (cb->invert) + einfo->invert |= XT_ECN_OP_MATCH_IP; + einfo->operation |= XT_ECN_OP_MATCH_IP; + einfo->ip_ect = cb->val.u8; + break; + } +} + +static void ecn_check(struct xt_fcheck_call *cb) +{ + if (cb->xflags == 0) + xtables_error(PARAMETER_PROBLEM, + "ECN match: some option required"); +} + +static void ecn_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct xt_ecn_info *einfo = + (const struct xt_ecn_info *)match->data; + + printf(" ECN match"); + + if (einfo->operation & XT_ECN_OP_MATCH_ECE) { + printf(" %sECE", + (einfo->invert & XT_ECN_OP_MATCH_ECE) ? "!" : ""); + } + + if (einfo->operation & XT_ECN_OP_MATCH_CWR) { + printf(" %sCWR", + (einfo->invert & XT_ECN_OP_MATCH_CWR) ? "!" : ""); + } + + if (einfo->operation & XT_ECN_OP_MATCH_IP) { + printf(" %sECT=%d", + (einfo->invert & XT_ECN_OP_MATCH_IP) ? "!" : "", + einfo->ip_ect); + } +} + +static void ecn_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_ecn_info *einfo = + (const struct xt_ecn_info *)match->data; + + if (einfo->operation & XT_ECN_OP_MATCH_ECE) { + if (einfo->invert & XT_ECN_OP_MATCH_ECE) + printf(" !"); + printf(" --ecn-tcp-ece"); + } + + if (einfo->operation & XT_ECN_OP_MATCH_CWR) { + if (einfo->invert & XT_ECN_OP_MATCH_CWR) + printf(" !"); + printf(" --ecn-tcp-cwr"); + } + + if (einfo->operation & XT_ECN_OP_MATCH_IP) { + if (einfo->invert & XT_ECN_OP_MATCH_IP) + printf(" !"); + printf(" --ecn-ip-ect %d", einfo->ip_ect); + } +} + +static struct xtables_match ecn_mt_reg = { + .name = "ecn", + .version = XTABLES_VERSION, + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_ecn_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_ecn_info)), + .help = ecn_help, + .print = ecn_print, + .save = ecn_save, + .x6_parse = ecn_parse, + .x6_fcheck = ecn_check, + .x6_options = ecn_opts, +}; + +void _init(void) +{ + xtables_register_match(&ecn_mt_reg); +} diff --git a/extensions/libxt_ecn.man b/extensions/libxt_ecn.man new file mode 100644 index 00000000..31c0a3e8 --- /dev/null +++ b/extensions/libxt_ecn.man @@ -0,0 +1,11 @@ +This allows you to match the ECN bits of the IPv4/IPv6 and TCP header. ECN is the Explicit Congestion Notification mechanism as specified in RFC3168 +.TP +[\fB!\fP] \fB\-\-ecn\-tcp\-cwr\fP +This matches if the TCP ECN CWR (Congestion Window Received) bit is set. +.TP +[\fB!\fP] \fB\-\-ecn\-tcp\-ece\fP +This matches if the TCP ECN ECE (ECN Echo) bit is set. +.TP +[\fB!\fP] \fB\-\-ecn\-ip\-ect\fP \fInum\fP +This matches a particular IPv4/IPv6 ECT (ECN-Capable Transport). You have to specify +a number between `0' and `3'. diff --git a/include/linux/netfilter/xt_ecn.h b/include/linux/netfilter/xt_ecn.h new file mode 100644 index 00000000..c21cc280 --- /dev/null +++ b/include/linux/netfilter/xt_ecn.h @@ -0,0 +1,33 @@ +/* iptables module for matching the ECN header in IPv4 and TCP header + * + * (C) 2002 Harald Welte + * + * This software is distributed under GNU GPL v2, 1991 +*/ +#ifndef _XT_ECN_H +#define _XT_ECN_H + +#include +#include + +#define XT_ECN_IP_MASK (~XT_DSCP_MASK) + +#define XT_ECN_OP_MATCH_IP 0x01 +#define XT_ECN_OP_MATCH_ECE 0x10 +#define XT_ECN_OP_MATCH_CWR 0x20 + +#define XT_ECN_OP_MATCH_MASK 0xce + +/* match info */ +struct xt_ecn_info { + __u8 operation; + __u8 invert; + __u8 ip_ect; + union { + struct { + __u8 ect; + } tcp; + } proto; +}; + +#endif /* _XT_ECN_H */ diff --git a/include/linux/netfilter_ipv4/ipt_ecn.h b/include/linux/netfilter_ipv4/ipt_ecn.h deleted file mode 100644 index eabf95fb..00000000 --- a/include/linux/netfilter_ipv4/ipt_ecn.h +++ /dev/null @@ -1,35 +0,0 @@ -/* iptables module for matching the ECN header in IPv4 and TCP header - * - * (C) 2002 Harald Welte - * - * This software is distributed under GNU GPL v2, 1991 - * - * ipt_ecn.h,v 1.4 2002/08/05 19:39:00 laforge Exp -*/ -#ifndef _IPT_ECN_H -#define _IPT_ECN_H - -#include -#include - -#define IPT_ECN_IP_MASK (~XT_DSCP_MASK) - -#define IPT_ECN_OP_MATCH_IP 0x01 -#define IPT_ECN_OP_MATCH_ECE 0x10 -#define IPT_ECN_OP_MATCH_CWR 0x20 - -#define IPT_ECN_OP_MATCH_MASK 0xce - -/* match info */ -struct ipt_ecn_info { - __u8 operation; - __u8 invert; - __u8 ip_ect; - union { - struct { - __u8 ect; - } tcp; - } proto; -}; - -#endif /* _IPT_ECN_H */ -- cgit v1.2.3 From d65702c5c5bbab0ef12298386fa4098c72584e6c Mon Sep 17 00:00:00 2001 From: Jonh Wendell Date: Wed, 4 Jan 2012 15:44:01 -0200 Subject: libiptc: Returns the position the entry was inserted Jan Engelhardt showed no objections to this patch. --- include/libiptc/libiptc.h | 3 ++- libiptc/libiptc.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index 24cdbdb7..b9a42c96 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -74,7 +74,8 @@ int iptc_replace_entry(const xt_chainlabel chain, struct xtc_handle *handle); /* Append entry `e' to chain `chain'. Equivalent to insert with - rulenum = length of chain. */ + rulenum = length of chain. Returns the position the entry was + inserted or 0 if an error occurs */ int iptc_append_entry(const xt_chainlabel chain, const struct ipt_entry *e, struct xtc_handle *handle); diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 63fcfc2a..ddaee128 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -1836,7 +1836,8 @@ TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, } /* Append entry `fw' to chain `chain'. Equivalent to insert with - rulenum = length of chain. */ + rulenum = length of chain. Returns the position the entry was + inserted or 0 if an error occurs */ int TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *e, @@ -1872,7 +1873,7 @@ TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, set_changed(handle); - return 1; + return c->num_rules; } static inline int -- cgit v1.2.3 From 7c1b69b97571ddeb8c624b0a1da366a456895a6d Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 1 Mar 2012 00:27:50 +0100 Subject: Revert "libiptc: Returns the position the entry was inserted" This reverts commit d65702c5c5bbab0ef12298386fa4098c72584e6c. This is breaking my iptables scripts: iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables: Incompatible with this kernel. --- include/libiptc/libiptc.h | 3 +-- libiptc/libiptc.c | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index b9a42c96..24cdbdb7 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -74,8 +74,7 @@ int iptc_replace_entry(const xt_chainlabel chain, struct xtc_handle *handle); /* Append entry `e' to chain `chain'. Equivalent to insert with - rulenum = length of chain. Returns the position the entry was - inserted or 0 if an error occurs */ + rulenum = length of chain. */ int iptc_append_entry(const xt_chainlabel chain, const struct ipt_entry *e, struct xtc_handle *handle); diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index ddaee128..63fcfc2a 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -1836,8 +1836,7 @@ TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, } /* Append entry `fw' to chain `chain'. Equivalent to insert with - rulenum = length of chain. Returns the position the entry was - inserted or 0 if an error occurs */ + rulenum = length of chain. */ int TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *e, @@ -1873,7 +1872,7 @@ TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, set_changed(handle); - return c->num_rules; + return 1; } static inline int -- cgit v1.2.3 From 1a7732f965c2b09e526eeca8a551538fbdc099ef Mon Sep 17 00:00:00 2001 From: Franz Flasch Date: Thu, 8 Mar 2012 04:20:37 +0000 Subject: iptables: missing free() in function cache_add_entry() Fixed a memory leak in the error path of function cache_add_entry(). Signed-off-by: Franz Flasch Signed-off-by: Christian Engelmayer Signed-off-by: Pablo Neira Ayuso --- libiptc/libiptc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 63fcfc2a..396bc8f5 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -1003,6 +1003,7 @@ new_rule: if (t->target.u.target_size != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { errno = EINVAL; + free(r); return -1; } -- cgit v1.2.3 From 61b8f7ecb64b3b6fe04d2a6ad9598f66e42ceea8 Mon Sep 17 00:00:00 2001 From: Franz Flasch Date: Thu, 8 Mar 2012 04:20:41 +0000 Subject: iptables: missing free() in function delete_entry() Fixed a memory leak in the dry run path of function delete_entry(). Signed-off-by: Franz Flasch Signed-off-by: Christian Engelmayer Signed-off-by: Pablo Neira Ayuso --- libiptc/libiptc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 396bc8f5..13e41d52 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -1993,8 +1993,10 @@ static int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, continue; /* if we are just doing a dry run, we simply skip the rest */ - if (dry_run) + if (dry_run){ + free(r); return 1; + } /* If we are about to delete the rule that is the * current iterator, move rule iterator back. next -- cgit v1.2.3 From c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 21 Mar 2012 00:52:00 +0000 Subject: src: mark newly opened fds as FD_CLOEXEC (close on exec) By default, Unix-like systems leak file descriptors after fork/exec call. I think this seem to result in SELinux spotting a strange AVC log messages according to what I can find on the web. Fedora 18 iptables source includes this change. Maciej says: "iptables does potentially fork/exec modprobe to load modules. That can cause a selinux 'domain'/'role'/whatever-it-is-called crossing. You can do automated inspection of what gets carried across such privilege changes and any unexpected open file descriptors flag problems, patches like this cut down on the noise." Signed-off-by: Maciej enczykowski Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_set.h | 7 +++++++ libiptc/libiptc.c | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/extensions/libxt_set.h b/extensions/libxt_set.h index 4ac84fa9..47c3f5b6 100644 --- a/extensions/libxt_set.h +++ b/extensions/libxt_set.h @@ -2,6 +2,7 @@ #define _LIBXT_SET_H #include +#include #include #include #include @@ -23,6 +24,12 @@ get_version(unsigned *version) xtables_error(OTHER_PROBLEM, "Can't open socket to ipset.\n"); + if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { + xtables_error(OTHER_PROBLEM, + "Could not set close on exec: %s\n", + strerror(errno)); + } + req_version.op = IP_SET_OP_VERSION; res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size); if (res != 0) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 13e41d52..63965e73 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -29,6 +29,8 @@ * - performance work: speedup initial ruleset parsing. * - sponsored by ComX Networks A/S (http://www.comx.dk/) */ +#include +#include #include #include #include @@ -1316,6 +1318,12 @@ TC_INIT(const char *tablename) if (sockfd < 0) return NULL; + if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { + fprintf(stderr, "Could not set close on exec: %s\n", + strerror(errno)); + abort(); + } + retry: s = sizeof(info); -- cgit v1.2.3 From f233df44196f568075a5d70fc29f31b72b512783 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 27 Mar 2012 10:23:49 +0200 Subject: extensions: add nfacct match This patch provides the user-space iptables support for the nfacct match. This can be used as it follows: nfacct add http-traffic iptables -I INPUT -p tcp --sport 80 -m nfacct --nfacct-name http-traffic iptables -I OUTPUT -p tcp --dport 80 -m nfacct --nfacct-name http-traffic nfacct get http-traffic See also man nfacct(8) for more information. Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_nfacct.c | 89 +++++++++++++++++++++++++++++++++++++ extensions/libxt_nfacct.man | 30 +++++++++++++ include/linux/netfilter/xt_nfacct.h | 17 +++++++ 3 files changed, 136 insertions(+) create mode 100644 extensions/libxt_nfacct.c create mode 100644 extensions/libxt_nfacct.man create mode 100644 include/linux/netfilter/xt_nfacct.h diff --git a/extensions/libxt_nfacct.c b/extensions/libxt_nfacct.c new file mode 100644 index 00000000..2ad59d52 --- /dev/null +++ b/extensions/libxt_nfacct.c @@ -0,0 +1,89 @@ +/* + * (C) 2011 by Pablo Neira Ayuso + * (C) 2011 by Intra2Net AG + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 (or + * any later at your option) as published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +enum { + O_NAME = 0, +}; + +#define s struct xt_nfacct_match_info +static const struct xt_option_entry nfacct_opts[] = { + {.name = "nfacct-name", .id = O_NAME, .type = XTTYPE_STRING, + .min = 1, .flags = XTOPT_MAND|XTOPT_PUT, XTOPT_POINTER(s, name)}, + XTOPT_TABLEEND, +}; +#undef s + +static void nfacct_help(void) +{ + printf("nfacct match options:\n" + " --nfacct-name STRING Name of accouting area\n"); +} + +static void nfacct_parse(struct xt_option_call *cb) +{ + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_NAME: + if (strchr(cb->arg, '\n') != NULL) + xtables_error(PARAMETER_PROBLEM, + "Newlines not allowed in --nfacct-name"); + break; + } +} + +static void +nfacct_print_name(const struct xt_nfacct_match_info *info, char *name) +{ + printf(" %snfacct-name ", name); + xtables_save_string(info->name); +} + +static void nfacct_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct xt_nfacct_match_info *info = + (struct xt_nfacct_match_info *)match->data; + + nfacct_print_name(info, ""); +} + +static void nfacct_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_nfacct_match_info *info = + (struct xt_nfacct_match_info *)match->data; + + nfacct_print_name(info, "--"); +} + +static struct xtables_match nfacct_match = { + .family = NFPROTO_UNSPEC, + .name = "nfacct", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_nfacct_match_info)), + .userspacesize = offsetof(struct xt_nfacct_match_info, nfacct), + .help = nfacct_help, + .x6_parse = nfacct_parse, + .print = nfacct_print, + .save = nfacct_save, + .x6_options = nfacct_opts, +}; + +void _init(void) +{ + xtables_register_match(&nfacct_match); +} diff --git a/extensions/libxt_nfacct.man b/extensions/libxt_nfacct.man new file mode 100644 index 00000000..b755f977 --- /dev/null +++ b/extensions/libxt_nfacct.man @@ -0,0 +1,30 @@ +The nfacct match provides the extended accounting infrastructure for iptables. +You have to use this match together with the standalone user-space utility +.B nfacct(8) +.PP +The only option available for this match is the following: +.TP +\fB\-\-nfacct\-name\fP \fIname\fP +This allows you to specify the existing object name that will be use for +accounting the traffic that this rule-set is matching. +.PP +To use this extension, you have to create an accounting object: +.IP +nfacct add http\-traffic +.PP +Then, you have to attach it to the accounting object via iptables: +.IP +iptables \-I INPUT \-p tcp \-\-sport 80 \-m nfacct \-\-nfacct\-name http\-traffic +.IP +iptables \-I OUTPUT \-p tcp \-\-dport 80 \-m nfacct \-\-nfacct\-name http\-traffic +.PP +Then, you can check for the amount of traffic that the rules match: +.IP +nfacct get http\-traffic +.IP +{ pkts = 00000000000000000156, bytes = 00000000000000151786 } = http-traffic; +.PP +You can obtain +.B nfacct(8) +from http://www.netfilter.org or, alternatively, from the git.netfilter.org +repository. diff --git a/include/linux/netfilter/xt_nfacct.h b/include/linux/netfilter/xt_nfacct.h new file mode 100644 index 00000000..59ab00dd --- /dev/null +++ b/include/linux/netfilter/xt_nfacct.h @@ -0,0 +1,17 @@ +#ifndef _XT_NFACCT_MATCH_H +#define _XT_NFACCT_MATCH_H + +#include + +#ifndef NFACCT_NAME_MAX +#define NFACCT_NAME_MAX 32 +#endif + +struct nf_acct; + +struct xt_nfacct_match_info { + char name[NFACCT_NAME_MAX]; + struct nf_acct *nfacct; +}; + +#endif /* _XT_NFACCT_MATCH_H */ -- cgit v1.2.3 From c4a6b0d437b02458fb3cb827b694fd94b3fbe044 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 27 Mar 2012 13:33:02 +0200 Subject: Bump version to 1.4.13 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3be2cc90..6678d905 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.12.2]) +AC_INIT([iptables], [1.4.13]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=7 -- cgit v1.2.3 From e8f32983048d6aa4a908b6a92da55fa71c859623 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Feb 2012 13:48:36 +0100 Subject: libxt_CT: add --timeout option This patch adds the --timeout option to allow to attach timeout policy objects to flows, eg. iptables -I PREROUTING -t raw -s 1.1.1.1 -p tcp \ -j CT --timeout custom-tcp-policy You need the nfct(8) tool which is available at: http://git.netfilter.org/cgi-bin/gitweb.cgi?p=nfct.git To define the cttimeout policies. Example of usage: nfct timeout add custom-tcp-policy inet tcp established 1000 The new nfct tool also requires libnetfilter_cttimeout: http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libnetfilter_cttimeout.git Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_CT.c | 134 ++++++++++++++++++++++++++++++++++++---- extensions/libxt_CT.man | 5 ++ include/linux/netfilter/xt_CT.h | 12 ++++ 3 files changed, 139 insertions(+), 12 deletions(-) diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index 7b93bfaf..27a20e2e 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -16,9 +16,23 @@ static void ct_help(void) ); } +static void ct_help_v1(void) +{ + printf( +"CT target options:\n" +" --notrack Don't track connection\n" +" --helper name Use conntrack helper 'name' for connection\n" +" --timeout name Use timeout policy 'name' for connection\n" +" --ctevents event[,event...] Generate specified conntrack events for connection\n" +" --expevents event[,event...] Generate specified expectation events for connection\n" +" --zone ID Assign/Lookup connection in zone ID\n" + ); +} + enum { O_NOTRACK = 0, O_HELPER, + O_TIMEOUT, O_CTEVENTS, O_EXPEVENTS, O_ZONE, @@ -37,6 +51,21 @@ static const struct xt_option_entry ct_opts[] = { }; #undef s +#define s struct xt_ct_target_info_v1 +static const struct xt_option_entry ct_opts_v1[] = { + {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE}, + {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)}, + {.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, timeout)}, + {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING}, + {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING}, + {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)}, + XTOPT_TABLEEND, +}; +#undef s + struct event_tbl { const char *name; unsigned int event; @@ -114,6 +143,28 @@ static void ct_parse(struct xt_option_call *cb) } } +static void ct_parse_v1(struct xt_option_call *cb) +{ + struct xt_ct_target_info_v1 *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_NOTRACK: + info->flags |= XT_CT_NOTRACK; + break; + case O_CTEVENTS: + info->ct_events = ct_parse_events(ct_event_tbl, + ARRAY_SIZE(ct_event_tbl), + cb->arg); + break; + case O_EXPEVENTS: + info->exp_events = ct_parse_events(exp_event_tbl, + ARRAY_SIZE(exp_event_tbl), + cb->arg); + break; + } +} + static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric) { const struct xt_ct_target_info *info = @@ -134,6 +185,29 @@ static void ct_print(const void *ip, const struct xt_entry_target *target, int n printf("zone %u ", info->zone); } +static void +ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric) +{ + const struct xt_ct_target_info_v1 *info = + (const struct xt_ct_target_info_v1 *)target->data; + + printf(" CT"); + if (info->flags & XT_CT_NOTRACK) + printf(" notrack"); + if (info->helper[0]) + printf(" helper %s", info->helper); + if (info->timeout[0]) + printf(" timeout %s", info->timeout); + if (info->ct_events) + ct_print_events("ctevents", ct_event_tbl, + ARRAY_SIZE(ct_event_tbl), info->ct_events); + if (info->exp_events) + ct_print_events("expevents", exp_event_tbl, + ARRAY_SIZE(exp_event_tbl), info->exp_events); + if (info->zone) + printf("zone %u ", info->zone); +} + static void ct_save(const void *ip, const struct xt_entry_target *target) { const struct xt_ct_target_info *info = @@ -153,20 +227,56 @@ static void ct_save(const void *ip, const struct xt_entry_target *target) printf(" --zone %u", info->zone); } -static struct xtables_target ct_target = { - .family = NFPROTO_UNSPEC, - .name = "CT", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), - .userspacesize = offsetof(struct xt_ct_target_info, ct), - .help = ct_help, - .print = ct_print, - .save = ct_save, - .x6_parse = ct_parse, - .x6_options = ct_opts, +static void ct_save_v1(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_ct_target_info_v1 *info = + (const struct xt_ct_target_info_v1 *)target->data; + + if (info->flags & XT_CT_NOTRACK) + printf(" --notrack"); + if (info->helper[0]) + printf(" --helper %s", info->helper); + if (info->timeout[0]) + printf(" --timeout %s", info->timeout); + if (info->ct_events) + ct_print_events("--ctevents", ct_event_tbl, + ARRAY_SIZE(ct_event_tbl), info->ct_events); + if (info->exp_events) + ct_print_events("--expevents", exp_event_tbl, + ARRAY_SIZE(exp_event_tbl), info->exp_events); + if (info->zone) + printf(" --zone %u", info->zone); +} + +static struct xtables_target ct_target_reg[] = { + { + .family = NFPROTO_UNSPEC, + .name = "CT", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), + .userspacesize = offsetof(struct xt_ct_target_info, ct), + .help = ct_help, + .print = ct_print, + .save = ct_save, + .x6_parse = ct_parse, + .x6_options = ct_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "CT", + .revision = 1, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), + .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), + .help = ct_help_v1, + .print = ct_print_v1, + .save = ct_save_v1, + .x6_parse = ct_parse_v1, + .x6_options = ct_opts_v1, + }, }; void _init(void) { - xtables_register_target(&ct_target); + xtables_register_targets(ct_target_reg, ARRAY_SIZE(ct_target_reg)); } diff --git a/extensions/libxt_CT.man b/extensions/libxt_CT.man index ff258b79..a93eb149 100644 --- a/extensions/libxt_CT.man +++ b/extensions/libxt_CT.man @@ -23,3 +23,8 @@ Possible event types are: \fBnew\fP. \fB\-\-zone\fP \fIid\fP Assign this packet to zone \fIid\fP and only have lookups done in that zone. By default, packets have zone 0. +.TP +\fB\-\-timeout\fP \fIname\fP +Use the timeout policy identified by \fIname\fP for the connection. This is +provides more flexible timeout policy definition than global timeout values +available at /proc/sys/net/netfilter/nf_conntrack_*_timeout_*. diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h index b56e7681..a064b8af 100644 --- a/include/linux/netfilter/xt_CT.h +++ b/include/linux/netfilter/xt_CT.h @@ -16,4 +16,16 @@ struct xt_ct_target_info { struct nf_conn *ct __attribute__((aligned(8))); }; +struct xt_ct_target_info_v1 { + __u16 flags; + __u16 zone; + __u32 ct_events; + __u32 exp_events; + char helper[16]; + char timeout[32]; + + /* Used internally by the kernel */ + struct nf_conn *ct __attribute__((aligned(8))); +}; + #endif /* _XT_CT_H */ -- cgit v1.2.3 From 8db1044ba608a78035bbf89007aab6b6d8ff6f68 Mon Sep 17 00:00:00 2001 From: Miguel GAIO Date: Thu, 19 Apr 2012 00:14:33 +0000 Subject: libiptc: fix retry path in TC_INIT There is an issue on TC_INIT retry path: In error case, TC_FREE is called and close sockfd. The retry does not reopen then always fail. The proposing patch reopens sockfd in retry patch. Signed-off-by: Miguel GAIO Signed-off-by: Pablo Neira Ayuso --- libiptc/libiptc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 63965e73..f0f78155 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -1307,6 +1307,7 @@ TC_INIT(const char *tablename) socklen_t s; int sockfd; +retry: iptc_fn = TC_INIT; if (strlen(tablename) >= TABLE_MAXNAMELEN) { @@ -1324,7 +1325,6 @@ TC_INIT(const char *tablename) abort(); } -retry: s = sizeof(info); strcpy(info.name, tablename); -- cgit v1.2.3 From 6111382a6c27e73c1cef1777c1253be0453a9dbb Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 9 May 2012 00:28:41 +0200 Subject: libipt_ULOG: fix --ulog-cprange In 1f2474a libipt_ULOG: use guided option parser. A bug has been accidentally introduced in --ulog-cprange, limiting possible values from 1 to 50. However, that limit should be applied to --ulog-qthreshold. Reported-by: Gaurav Sinha Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_ULOG.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libipt_ULOG.c b/extensions/libipt_ULOG.c index e08ae056..fafb220b 100644 --- a/extensions/libipt_ULOG.c +++ b/extensions/libipt_ULOG.c @@ -37,9 +37,9 @@ static const struct xt_option_entry ULOG_opts[] = { {.name = "ulog-prefix", .id = O_ULOG_PREFIX, .type = XTTYPE_STRING, .flags = XTOPT_PUT, XTOPT_POINTER(struct ipt_ulog_info, prefix), .min = 1}, - {.name = "ulog-cprange", .id = O_ULOG_CPRANGE, .type = XTTYPE_UINT64, + {.name = "ulog-cprange", .id = O_ULOG_CPRANGE, .type = XTTYPE_UINT64}, + {.name = "ulog-qthreshold", .id = O_ULOG_QTHR, .type = XTTYPE_UINT64, .min = 1, .max = ULOG_MAX_QLEN}, - {.name = "ulog-qthreshold", .id = O_ULOG_QTHR, .type = XTTYPE_UINT64}, XTOPT_TABLEEND, }; -- cgit v1.2.3 From cb999dfdaf25d5a774d2ee84cb99355438d57c93 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 10 May 2012 05:42:47 +0000 Subject: ip(6)tables-restore: make sure argv is NULL terminated Else, argv[argc] may point to free'd memory. Some extensions, e.g. rateest, may fail to parse valid input because argv[optind] (with optind == argc) is not NULL. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.c | 2 +- iptables/iptables-restore.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 92bdc302..3894d68d 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -98,7 +98,7 @@ static int add_argv(char *what) { DEBUGP("add_argv: %s\n", what); if (what && newargc + 1 < ARRAY_SIZE(newargv)) { newargv[newargc] = strdup(what); - newargc++; + newargv[++newargc] = NULL; return 1; } else { xtables_error(PARAMETER_PROBLEM, diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 6b1c7929..034f9606 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -97,7 +97,7 @@ static int add_argv(char *what) { DEBUGP("add_argv: %s\n", what); if (what && newargc + 1 < ARRAY_SIZE(newargv)) { newargv[newargc] = strdup(what); - newargc++; + newargv[++newargc] = NULL; return 1; } else { xtables_error(PARAMETER_PROBLEM, -- cgit v1.2.3 From a05910364fa0f2f919dbe0b01bcaba9c3cb127ca Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 17 May 2012 01:03:08 +0000 Subject: extensions: libxt_rateest: output all options in save hook ipt-restore fails to parse the ipt-save output: zmatches -m rateest --rateest RE1 --rateest-pps --rateest-lt 5 (should be "--rateest-pps 5 --rateest-lt"). Also, the "delta" option was never shown in -save output, but twice in some cases when using "iptables -L". Also, the "b/pps1" option must be shown when "delta" option is used with relative mode. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_rateest.c | 55 ++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c index 86bbb06f..185a8135 100644 --- a/extensions/libxt_rateest.c +++ b/extensions/libxt_rateest.c @@ -348,8 +348,8 @@ rateest_print(const void *ip, const struct xt_entry_match *match, int numeric) if (info->flags & XT_RATEEST_MATCH_DELTA) rateest_print_rate(info->bps1, numeric); if (info->flags & XT_RATEEST_MATCH_ABS) { - rateest_print_mode(info, ""); rateest_print_rate(info->bps2, numeric); + rateest_print_mode(info, ""); } } if (info->flags & XT_RATEEST_MATCH_PPS) { @@ -366,8 +366,6 @@ rateest_print(const void *ip, const struct xt_entry_match *match, int numeric) rateest_print_mode(info, ""); printf(" %s", info->name2); - if (info->flags & XT_RATEEST_MATCH_DELTA) - printf(" delta"); if (info->flags & XT_RATEEST_MATCH_BPS) { printf(" bps"); @@ -382,33 +380,48 @@ rateest_print(const void *ip, const struct xt_entry_match *match, int numeric) } } +static void __rateest_save_rate(const struct xt_rateest_match_info *info, + const char *name, uint32_t r1, uint32_t r2, + int numeric) +{ + if (info->flags & XT_RATEEST_MATCH_DELTA) { + printf(" --rateest-%s1", name); + rateest_print_rate(r1, numeric); + rateest_print_mode(info, "--rateest-"); + printf(" --rateest-%s2", name); + } else { + rateest_print_mode(info, "--rateest-"); + printf(" --rateest-%s", name); + } + + if (info->flags & (XT_RATEEST_MATCH_ABS|XT_RATEEST_MATCH_DELTA)) + rateest_print_rate(r2, numeric); +} + +static void rateest_save_rates(const struct xt_rateest_match_info *info) +{ + if (info->flags & XT_RATEEST_MATCH_BPS) + __rateest_save_rate(info, "bps", info->bps1, info->bps2, 0); + if (info->flags & XT_RATEEST_MATCH_PPS) + __rateest_save_rate(info, "pps", info->pps1, info->pps2, 1); +} + + static void rateest_save(const void *ip, const struct xt_entry_match *match) { const struct xt_rateest_match_info *info = (const void *)match->data; + if (info->flags & XT_RATEEST_MATCH_DELTA) + printf(" --rateest-delta"); + if (info->flags & XT_RATEEST_MATCH_REL) { printf(" --rateest1 %s", info->name1); - if (info->flags & XT_RATEEST_MATCH_BPS) - printf(" --rateest-bps"); - if (info->flags & XT_RATEEST_MATCH_PPS) - printf(" --rateest-pps"); - rateest_print_mode(info, " --rateest-"); + rateest_save_rates(info); printf(" --rateest2 %s", info->name2); - } else { + } else { /* XT_RATEEST_MATCH_ABS */ printf(" --rateest %s", info->name1); - if (info->flags & XT_RATEEST_MATCH_BPS) { - printf(" --rateest-bps1"); - rateest_print_rate(info->bps1, 0); - printf(" --rateest-bps2"); - rateest_print_rate(info->bps2, 0); - rateest_print_mode(info, "--rateest-"); - } - if (info->flags & XT_RATEEST_MATCH_PPS) { - printf(" --rateest-pps"); - rateest_print_mode(info, "--rateest-"); - printf(" %u", info->pps2); - } + rateest_save_rates(info); } } -- cgit v1.2.3 From c022454ff5ad39c5e37fa6cd29b85159ad16ed0f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 17 May 2012 01:03:09 +0000 Subject: tests: add rateest match rules also, -p mobility gets us EINVAL from kernel, use -p ipv6-mh instead. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- tests/options-most.rules | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/tests/options-most.rules b/tests/options-most.rules index 75733615..30dac16b 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -54,8 +54,7 @@ -A INPUT -p tcp -m tcpmss --mss 1:2 -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 4/0 -A INPUT --A INPUT -p mobility --A INPUT -p mobility -m mh --mh-type 3 +-A INPUT -p ipv6-mh -m mh --mh-type 3 -A OUTPUT -m owner --socket-exists --uid-owner 1-2 --gid-owner 2-3 -A OUTPUT -m owner ! --socket-exists ! --uid-owner 0 ! --gid-owner 0 -A matches -m connbytes --connbytes 1 --connbytes-mode bytes --connbytes-dir both @@ -184,20 +183,17 @@ -A ntarg -A ntarg -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms -A ntarg -#-A zmatches -m rateest --rateest RE1 --rateest-lt --rateest-bps 8bit -#-A zmatches -m rateest --rateest RE1 --rateest-eq --rateest-bps 8bit -#-A zmatches -m rateest --rateest RE1 --rateest-gt --rateest-bps 8bit -#-A zmatches -m rateest --rateest RE1 --rateest-lt --rateest-pps 5 -#-A zmatches -m rateest --rateest RE1 --rateest-eq --rateest-pps 5 -#-A zmatches -m rateest --rateest RE1 --rateest-gt --rateest-pps 5 -#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-lt --rateest-bps2 16bit -#-A zmatches -m rateest --rateest1 RE1 --rateest-lt --rateest2 RE2 --bytes -#-A zmatches -m rateest --rateest1 RE1 --rateest-lt --rateest2 RE2 --packets -#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-eq --rateest-bps2 16bit -#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-gt --rateest-bps2 16bit -#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-lt --rateest-pps2 9 -#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-eq --rateest-pps2 9 -#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-gt --rateest-pps2 9 +-A zmatches -m rateest --rateest RE1 --rateest-lt --rateest-bps 8bit +-A zmatches -m rateest --rateest RE1 --rateest-eq --rateest-pps 5 +-A zmatches -m rateest --rateest RE1 --rateest-gt --rateest-bps 5kbit +-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-lt --rateest-bps2 16bit +-A zmatches -m rateest --rateest1 RE1 --rateest-lt --rateest-bps --rateest2 RE2 +-A zmatches -m rateest --rateest-delta --rateest1 RE1 --rateest-lt --rateest2 RE2 --rateest-pps2 42 +-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-eq --rateest-bps2 16bit +-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-gt --rateest-bps2 16bit +-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-lt --rateest-pps2 9 +-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-eq --rateest-pps2 9 +-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-gt --rateest-pps2 9 COMMIT *mangle :PREROUTING ACCEPT [0:0] -- cgit v1.2.3 From 9eaa87401ce5ac64cc6baa55775f58f59ca26f34 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 26 May 2012 18:44:33 +0200 Subject: Bump version to 1.4.14 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6678d905..2909a987 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.13]) +AC_INIT([iptables], [1.4.14]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=7 -- cgit v1.2.3 From 7e2b63603fef2253b463ad33395520297cfe8378 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 2 Jul 2012 11:03:12 +0000 Subject: libxt_devgroup: add man page snippet Signed-off-by: Florian Westphal --- extensions/libxt_devgroup.man | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 extensions/libxt_devgroup.man diff --git a/extensions/libxt_devgroup.man b/extensions/libxt_devgroup.man new file mode 100644 index 00000000..4a66c9fe --- /dev/null +++ b/extensions/libxt_devgroup.man @@ -0,0 +1,7 @@ +Match device group of a packets incoming/outgoing interface. +.TP +[\fB!\fP] \fB\-\-src\-group\fP \fIname\fP +Match device group of incoming device +.TP +[\fB!\fP] \fB\-\-dst\-group\fP \fIname\fP +Match device group of outgoing device -- cgit v1.2.3 From a96166c24eaac1c91bed4815c09e91733409d888 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 14 Jul 2012 15:39:20 +0200 Subject: libxtables: add xtables_ip[6]mask_to_cidr This patch adds generic functions to return the mask in CIDR notation whenever is possible. This patch also simplifies xtables_ip[6]mask_to_numeric, that now use these new two functions. This patch also bumps libxtables_vcurrent and libxtables_vage since we added a couple new interfaces (thanks to Jan Engelhardt for his little reminder on this). Signed-off-by: Pablo Neira Ayuso --- configure.ac | 4 ++-- include/xtables.h.in | 2 ++ libxtables/xtables.c | 33 ++++++++++++++++++++++++--------- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 2909a987..989ffd73 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ AC_INIT([iptables], [1.4.14]) # See libtool.info "Libtool's versioning system" -libxtables_vcurrent=7 -libxtables_vage=0 +libxtables_vcurrent=8 +libxtables_vage=1 AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/include/xtables.h.in b/include/xtables.h.in index 28e29337..db69c03b 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -442,6 +442,7 @@ extern const char *xtables_ipaddr_to_anyname(const struct in_addr *); extern const char *xtables_ipmask_to_numeric(const struct in_addr *); extern struct in_addr *xtables_numeric_to_ipaddr(const char *); extern struct in_addr *xtables_numeric_to_ipmask(const char *); +extern int xtables_ipmask_to_cidr(const struct in_addr *); extern void xtables_ipparse_any(const char *, struct in_addr **, struct in_addr *, unsigned int *); extern void xtables_ipparse_multiple(const char *, struct in_addr **, @@ -451,6 +452,7 @@ extern struct in6_addr *xtables_numeric_to_ip6addr(const char *); extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *); extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *); extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *); +extern int xtables_ip6mask_to_cidr(const struct in6_addr *); extern void xtables_ip6parse_any(const char *, struct in6_addr **, struct in6_addr *, unsigned int *); extern void xtables_ip6parse_multiple(const char *, struct in6_addr **, diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 014e115b..d8185796 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -1133,28 +1133,43 @@ const char *xtables_ipaddr_to_anyname(const struct in_addr *addr) return xtables_ipaddr_to_numeric(addr); } -const char *xtables_ipmask_to_numeric(const struct in_addr *mask) +int xtables_ipmask_to_cidr(const struct in_addr *mask) { - static char buf[20]; uint32_t maskaddr, bits; int i; maskaddr = ntohl(mask->s_addr); - + /* shortcut for /32 networks */ if (maskaddr == 0xFFFFFFFFL) - /* we don't want to see "/32" */ - return ""; + return 32; i = 32; bits = 0xFFFFFFFEL; while (--i >= 0 && maskaddr != bits) bits <<= 1; if (i >= 0) - sprintf(buf, "/%d", i); - else + return i; + + /* this mask cannot be converted to CIDR notation */ + return -1; +} + +const char *xtables_ipmask_to_numeric(const struct in_addr *mask) +{ + static char buf[20]; + uint32_t cidr; + + cidr = xtables_ipmask_to_cidr(mask); + if (cidr < 0) { /* mask was not a decent combination of 1's and 0's */ sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); + return buf; + } else if (cidr == 32) { + /* we don't want to see "/32" */ + return ""; + } + sprintf(buf, "/%d", cidr); return buf; } @@ -1465,7 +1480,7 @@ const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) return xtables_ip6addr_to_numeric(addr); } -static int ip6addr_prefix_length(const struct in6_addr *k) +int xtables_ip6mask_to_cidr(const struct in6_addr *k) { unsigned int bits = 0; uint32_t a, b, c, d; @@ -1492,7 +1507,7 @@ static int ip6addr_prefix_length(const struct in6_addr *k) const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) { static char buf[50+2]; - int l = ip6addr_prefix_length(addrp); + int l = xtables_ip6mask_to_cidr(addrp); if (l == -1) { strcpy(buf, "/"); -- cgit v1.2.3 From 4df8cb6ab176f3c1f2bf9498d0abde8d9362087b Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Mon, 23 Apr 2012 03:35:28 +0000 Subject: extensions: add HMARK target The target allows you to set mark packets based Jenkins' hash calculation: h(t, rnd) = x mark = (x % mod) + offset where: * t is a tuple that is used for the hashing: t = [ src, dst, proto, sport, dport ] Note that you can customize the tuple, thus, removing some component that you don't want to use for the calculation. You can also use spi instead of sport and dport, btw. * rnd is the random seed that is explicitly passed via --hmark-rnd * mod is the modulus, to determine the range of possible marks * offset determines where the mark starts from This target only works for the "raw" and "mangle" tables. This can be used to distribute flows between a cluster of systems and uplinks. Initially based on work from Hans Schillingstrom. Pablo took it over and introduced several improvements. Signed-off-by: Hans Schillstrom Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_HMARK.c | 443 +++++++++++++++++++++++++++++++++++++ extensions/libxt_HMARK.man | 60 +++++ include/linux/netfilter/xt_HMARK.h | 50 +++++ 3 files changed, 553 insertions(+) create mode 100644 extensions/libxt_HMARK.c create mode 100644 extensions/libxt_HMARK.man create mode 100644 include/linux/netfilter/xt_HMARK.h diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c new file mode 100644 index 00000000..719effe8 --- /dev/null +++ b/extensions/libxt_HMARK.c @@ -0,0 +1,443 @@ +/* + * (C) 2012 by Hans Schillstrom + * (C) 2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Description: shared library add-on to iptables to add HMARK target support + * + * Initial development by Hans Schillstrom. Pablo's improvements to this piece + * of software has been sponsored by Sophos Astaro . + */ + +#include +#include +#include + +#include "xtables.h" +#include + +static void HMARK_help(void) +{ + printf( +"HMARK target options, i.e. modify hash calculation by:\n" +" --hmark-tuple [src|dst|sport|dport|spi|proto|ct][,...]\n" +" --hmark-mod value nfmark modulus value\n" +" --hmark-offset value Last action add value to nfmark\n\n" +" --hmark-rnd Random seed for hashing\n" +" Alternatively, fine tuning of what will be included in hash calculation\n" +" --hmark-src-prefix length Source address mask CIDR prefix\n" +" --hmark-dst-prefix length Dest address mask CIDR prefix\n" +" --hmark-sport-mask value Mask src port with value\n" +" --hmark-dport-mask value Mask dst port with value\n" +" --hmark-spi-mask value For esp and ah AND spi with value\n" +" --hmark-sport-set value OR src port with value\n" +" --hmark-dport-set value OR dst port with value\n" +" --hmark-spi-set value For esp and ah OR spi with value\n" +" --hmark-proto-mask value Mask Protocol with value\n"); +} + +#define hi struct xt_hmark_info + +enum { + O_HMARK_SADDR_MASK, + O_HMARK_DADDR_MASK, + O_HMARK_SPI, + O_HMARK_SPI_MASK, + O_HMARK_SPORT, + O_HMARK_DPORT, + O_HMARK_SPORT_MASK, + O_HMARK_DPORT_MASK, + O_HMARK_PROTO_MASK, + O_HMARK_RND, + O_HMARK_MODULUS, + O_HMARK_OFFSET, + O_HMARK_CT, + O_HMARK_TYPE, +}; + +#define HMARK_OPT_PKT_MASK \ + ((1 << O_HMARK_SADDR_MASK) | \ + (1 << O_HMARK_DADDR_MASK) | \ + (1 << O_HMARK_SPI_MASK) | \ + (1 << O_HMARK_SPORT_MASK) | \ + (1 << O_HMARK_DPORT_MASK) | \ + (1 << O_HMARK_PROTO_MASK) | \ + (1 << O_HMARK_SPI_MASK) | \ + (1 << O_HMARK_SPORT) | \ + (1 << O_HMARK_DPORT) | \ + (1 << O_HMARK_SPI)) + +static const struct xt_option_entry HMARK_opts[] = { + { .name = "hmark-tuple", + .type = XTTYPE_STRING, + .id = O_HMARK_TYPE, + }, + { .name = "hmark-src-prefix", + .type = XTTYPE_PLENMASK, + .id = O_HMARK_SADDR_MASK, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, src_mask) + }, + { .name = "hmark-dst-prefix", + .type = XTTYPE_PLENMASK, + .id = O_HMARK_DADDR_MASK, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, dst_mask) + }, + { .name = "hmark-sport-mask", + .type = XTTYPE_UINT16, + .id = O_HMARK_SPORT_MASK, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src) + }, + { .name = "hmark-dport-mask", + .type = XTTYPE_UINT16, + .id = O_HMARK_DPORT_MASK, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst) + }, + { .name = "hmark-spi-mask", + .type = XTTYPE_UINT32, + .id = O_HMARK_SPI_MASK, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32) + }, + { .name = "hmark-sport", + .type = XTTYPE_UINT16, + .id = O_HMARK_SPORT, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src) + }, + { .name = "hmark-dport", + .type = XTTYPE_UINT16, + .id = O_HMARK_DPORT, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst) + }, + { .name = "hmark-spi", + .type = XTTYPE_UINT32, + .id = O_HMARK_SPI, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32) + }, + { .name = "hmark-proto-mask", + .type = XTTYPE_UINT16, + .id = O_HMARK_PROTO_MASK, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, proto_mask) + }, + { .name = "hmark-rnd", + .type = XTTYPE_UINT32, + .id = O_HMARK_RND, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd) + }, + { .name = "hmark-mod", + .type = XTTYPE_UINT32, + .id = O_HMARK_MODULUS, + .min = 1, + .flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmodulus) + }, + { .name = "hmark-offset", + .type = XTTYPE_UINT32, + .id = O_HMARK_OFFSET, + .flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffset) + }, + XTOPT_TABLEEND, +}; + +static int +hmark_parse(const char *type, size_t len, struct xt_hmark_info *info, + unsigned int *xflags) +{ + if (strncasecmp(type, "ct", len) == 0) { + info->flags |= XT_HMARK_FLAG(XT_HMARK_CT); + *xflags |= (1 << O_HMARK_CT); + } else if (strncasecmp(type, "src", len) == 0) { + memset(&info->src_mask, 0xff, sizeof(info->src_mask)); + info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK); + *xflags |= (1 << O_HMARK_SADDR_MASK); + } else if (strncasecmp(type, "dst", len) == 0) { + memset(&info->dst_mask, 0xff, sizeof(info->dst_mask)); + info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK); + *xflags |= (1 << O_HMARK_DADDR_MASK); + } else if (strncasecmp(type, "sport", len) == 0) { + memset(&info->port_mask.p16.src, 0xff, + sizeof(info->port_mask.p16.src)); + info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK); + *xflags |= (1 << O_HMARK_SPORT_MASK); + } else if (strncasecmp(type, "dport", len) == 0) { + memset(&info->port_mask.p16.dst, 0xff, + sizeof(info->port_mask.p16.dst)); + info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK); + *xflags |= (1 << O_HMARK_DPORT_MASK); + } else if (strncasecmp(type, "proto", len) == 0) { + memset(&info->proto_mask, 0xff, sizeof(info->proto_mask)); + info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK); + *xflags |= (1 << O_HMARK_PROTO_MASK); + } else if (strncasecmp(type, "spi", len) == 0) { + memset(&info->port_mask.v32, 0xff, sizeof(info->port_mask.v32)); + info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK); + *xflags |= (1 << O_HMARK_SPI_MASK); + } else + return 0; + + return 1; +} + +static void +hmark_parse_type(struct xt_option_call *cb) +{ + const char *arg = cb->arg; + struct xt_hmark_info *info = cb->data; + const char *comma; + + while ((comma = strchr(arg, ',')) != NULL) { + if (comma == arg || + !hmark_parse(arg, comma-arg, info, &cb->xflags)) + xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg); + arg = comma+1; + } + if (!*arg) + xtables_error(PARAMETER_PROBLEM, "\"--hmark-tuple\" requires " + "a list of types with no " + "spaces, e.g. " + "src,dst,sport,dport,proto"); + if (strlen(arg) == 0 || + !hmark_parse(arg, strlen(arg), info, &cb->xflags)) + xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg); +} + +static void HMARK_parse(struct xt_option_call *cb, int plen) +{ + struct xt_hmark_info *info = cb->data; + + xtables_option_parse(cb); + + switch (cb->entry->id) { + case O_HMARK_TYPE: + hmark_parse_type(cb); + break; + case O_HMARK_SADDR_MASK: + info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK); + break; + case O_HMARK_DADDR_MASK: + info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK); + break; + case O_HMARK_SPI: + info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK); + break; + case O_HMARK_SPORT: + info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT); + break; + case O_HMARK_DPORT: + info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT); + break; + case O_HMARK_SPORT_MASK: + info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK); + break; + case O_HMARK_DPORT_MASK: + info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK); + break; + case O_HMARK_PROTO_MASK: + info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK); + break; + case O_HMARK_RND: + info->flags |= XT_HMARK_FLAG(XT_HMARK_RND); + break; + case O_HMARK_MODULUS: + info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS); + break; + case O_HMARK_OFFSET: + info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET); + break; + case O_HMARK_CT: + info->flags |= XT_HMARK_FLAG(XT_HMARK_CT); + break; + } + cb->xflags |= (1 << cb->entry->id); +} + +static void HMARK_ip4_parse(struct xt_option_call *cb) +{ + HMARK_parse(cb, 32); +} +static void HMARK_ip6_parse(struct xt_option_call *cb) +{ + HMARK_parse(cb, 128); +} + +static void HMARK_check(struct xt_fcheck_call *cb) +{ + if (!(cb->xflags & (1 << O_HMARK_MODULUS))) + xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory"); + if (!(cb->xflags & (1 << O_HMARK_RND))) + xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory"); + if (cb->xflags & (1 << O_HMARK_SPI_MASK) && + (cb->xflags & (1 << O_HMARK_SPORT_MASK || + cb->xflags & (1 << O_HMARK_DPORT_MASK)))) + xtables_error(PARAMETER_PROBLEM, "you cannot use " + "--hmark-spi-mask and --hmark-?port-mask," + "at the same time"); + if (!((cb->xflags & HMARK_OPT_PKT_MASK) || + cb->xflags & (1 << O_HMARK_CT))) + xtables_error(PARAMETER_PROBLEM, "you have to specify " + "--hmark-tuple at least"); + if (!(cb->xflags & (1 << O_HMARK_OFFSET))) + xtables_error(PARAMETER_PROBLEM, "--hmark-offset is mandatory"); +} + +static void HMARK_print(const struct xt_hmark_info *info) +{ + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT)) + printf("sport-mask 0x%x ", htons(info->port_mask.p16.src)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT)) + printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI)) + printf("spi-mask 0x%x ", htonl(info->port_mask.v32)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK)) + printf("sport-set 0x%x ", htons(info->port_set.p16.src)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)) + printf("dport-set 0x%x ", htons(info->port_set.p16.dst)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK)) + printf("spi-set 0x%x ", htonl(info->port_set.v32)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK)) + printf("proto-mask 0x%x ", info->proto_mask); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND)) + printf("rnd 0x%x ", info->hashrnd); +} + +static void HMARK_ip6_print(const void *ip, + const struct xt_entry_target *target, int numeric) +{ + const struct xt_hmark_info *info = + (const struct xt_hmark_info *)target->data; + + printf(" HMARK "); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS)) + printf("mod %u ", info->hmodulus); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET)) + printf("+ 0x%x ", info->hoffset); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT)) + printf("ct, "); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) + printf("src-prefix %s ", + xtables_ip6mask_to_numeric(&info->src_mask.in6) + 1); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) + printf("dst-prefix %s ", + xtables_ip6mask_to_numeric(&info->dst_mask.in6) + 1); + HMARK_print(info); +} +static void HMARK_ip4_print(const void *ip, + const struct xt_entry_target *target, int numeric) +{ + const struct xt_hmark_info *info = + (const struct xt_hmark_info *)target->data; + + printf(" HMARK "); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS)) + printf("mod %u ", info->hmodulus); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET)) + printf("+ 0x%x ", info->hoffset); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT)) + printf("ct, "); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) + printf("src-prefix %s ", + xtables_ipmask_to_numeric(&info->src_mask.in) + 1); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) + printf("dst-prefix %s ", + xtables_ipmask_to_numeric(&info->dst_mask.in) + 1); + HMARK_print(info); +} + +static void HMARK_save(const struct xt_hmark_info *info) +{ + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK)) + printf(" --hmark-sport-mask 0x%04x", + htons(info->port_mask.p16.src)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)) + printf(" --hmark-dport-mask 0x%04x", + htons(info->port_mask.p16.dst)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI)) + printf(" --hmark-spi-mask 0x%08x", + htonl(info->port_mask.v32)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT)) + printf(" --hmark-sport-set 0x%04x", + htons(info->port_set.p16.src)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT)) + printf(" --hmark-dport-set 0x%04x", + htons(info->port_set.p16.dst)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK)) + printf(" --hmark-spi-set 0x%08x", htonl(info->port_set.v32)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK)) + printf(" --hmark-proto-mask 0x%02x", info->proto_mask); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND)) + printf(" --hmark-rnd 0x%08x", info->hashrnd); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS)) + printf(" --hmark-mod %u", info->hmodulus); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET)) + printf(" --hmark-offset %u", info->hoffset); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT)) + printf(" --hmark-tuple ct"); +} + +static void HMARK_ip6_save(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_hmark_info *info = + (const struct xt_hmark_info *)target->data; + int ret; + + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) { + ret = xtables_ip6mask_to_cidr(&info->src_mask.in6); + printf(" --hmark-src-prefix %d", ret); + } + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) { + ret = xtables_ip6mask_to_cidr(&info->dst_mask.in6); + printf(" --hmark-dst-prefix %d", ret); + } + HMARK_save(info); +} + +static void HMARK_ip4_save(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_hmark_info *info = + (const struct xt_hmark_info *)target->data; + int ret; + + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) { + ret = xtables_ipmask_to_cidr(&info->src_mask.in); + printf(" --hmark-src-prefix %d", ret); + } + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) { + ret = xtables_ipmask_to_cidr(&info->dst_mask.in); + printf(" --hmark-dst-prefix %d", ret); + } + HMARK_save(info); +} + +static struct xtables_target mark_tg_reg[] = { + { + .family = NFPROTO_IPV4, + .name = "HMARK", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_hmark_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)), + .help = HMARK_help, + .print = HMARK_ip4_print, + .save = HMARK_ip4_save, + .x6_parse = HMARK_ip4_parse, + .x6_fcheck = HMARK_check, + .x6_options = HMARK_opts, + }, + { + .family = NFPROTO_IPV6, + .name = "HMARK", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_hmark_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)), + .help = HMARK_help, + .print = HMARK_ip6_print, + .save = HMARK_ip6_save, + .x6_parse = HMARK_ip6_parse, + .x6_fcheck = HMARK_check, + .x6_options = HMARK_opts, + }, +}; + +void _init(void) +{ + xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg)); +} diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man new file mode 100644 index 00000000..2b004b5a --- /dev/null +++ b/extensions/libxt_HMARK.man @@ -0,0 +1,60 @@ +Like MARK, i.e. set the fwmark, but the mark is calculated from hashing +packet selector at choice. You have also to specify the mark range and, +optionally, the offset to start from. ICMP error messages are inspected +and used to calculate the hashing. +.PP +Existing options are: +.TP +\fB\-\-hmark\-tuple\fP tuple\fI\fP +Possible tuple members are: +.B src +meaning source address (IPv4, IPv6 address), +.B dst +meaning destination address (IPv4, IPv6 address), +.B sport +meaning source port (TCP, UDP, UDPlite, SCTP, DCCP), +.B dport +meaning destination port (TCP, UDP, UDPlite, SCTP, DCCP), +.B spi +meaning Security Parameter Index (AH, ESP), and +.B ct +meaning the usage of the conntrack tuple instead of the packet selectors. +.TP +\fB\-\-hmark\-mod\fP \fIvalue (must be > 0)\fP +Modulus for hash calculation (to limit the range of possible marks) +.TP +\fB\-\-hmark\-offset\fP \fIvalue\fP +Offset to start marks from. +.TP +For advanced usage, instead of using \-\-hmark\-tuple, you can specify custom +prefixes and masks: +.TP +\fB\-\-hmark\-src\-prefix\fP \fIcidr\fP +The source address mask in CIDR notation. +.TP +\fB\-\-hmark\-dst\-prefix\fP \fIcidr\fP +The destination address mask in CIDR notation. +.TP +\fB\-\-hmark\-sport\-mask\fP \fIvalue\fP +A 16 bit source port mask in hexadecimal. +.TP +\fB\-\-hmark\-dport\-mask\fP \fIvalue\fP +A 16 bit destination port mask in hexadecimal. +.TP +\fB\-\-hmark\-spi\-mask\fP \fIvalue\fP +A 32 bit field with spi mask. +.TP +\fB\-\-hmark\-proto\-mask\fP \fIvalue\fP +An 8 bit field with layer 4 protocol number. +.TP +\fB\-\-hmark\-rnd\fP \fIvalue\fP +A 32 bit random custom value to feed hash calculation. +.PP +\fIExamples:\fP +.PP +iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW + \-j HMARK \-\-hmark-tuple ct \-\-hmark-offset 10000 \-\-hmark\-mod 10 +\-\-hmark\-rnd 0xfeedcafe +.PP +iptables \-t mangle \-A PREROUTING -j HMARK \-\-hmark\-offset 10000 +\-\-hmark-tuple src,dst,proto \-\-hmark-mod 10 \-\-hmark\-rnd 0xdeafbeef diff --git a/include/linux/netfilter/xt_HMARK.h b/include/linux/netfilter/xt_HMARK.h new file mode 100644 index 00000000..826fc580 --- /dev/null +++ b/include/linux/netfilter/xt_HMARK.h @@ -0,0 +1,50 @@ +#ifndef XT_HMARK_H_ +#define XT_HMARK_H_ + +#include + +enum { + XT_HMARK_SADDR_MASK, + XT_HMARK_DADDR_MASK, + XT_HMARK_SPI, + XT_HMARK_SPI_MASK, + XT_HMARK_SPORT, + XT_HMARK_DPORT, + XT_HMARK_SPORT_MASK, + XT_HMARK_DPORT_MASK, + XT_HMARK_PROTO_MASK, + XT_HMARK_RND, + XT_HMARK_MODULUS, + XT_HMARK_OFFSET, + XT_HMARK_CT, + XT_HMARK_METHOD_L3, + XT_HMARK_METHOD_L3_4, +}; +#define XT_HMARK_FLAG(flag) (1 << flag) + +union hmark_ports { + struct { + __u16 src; + __u16 dst; + } p16; + struct { + __be16 src; + __be16 dst; + } b16; + __u32 v32; + __be32 b32; +}; + +struct xt_hmark_info { + union nf_inet_addr src_mask; + union nf_inet_addr dst_mask; + union hmark_ports port_mask; + union hmark_ports port_set; + __u32 flags; + __u16 proto_mask; + __u32 hashrnd; + __u32 hmodulus; + __u32 hoffset; /* Mark offset to start from */ +}; + +#endif /* XT_HMARK_H_ */ -- cgit v1.2.3 From 874d7ee3c36ba54220fd204e6aa7cbc731a66395 Mon Sep 17 00:00:00 2001 From: Eldad Zack Date: Wed, 4 Jul 2012 11:53:54 +0000 Subject: libxt_recent: remove unused variable The info variable is assigned but never read in recent_check(). Signed-off-by: Eldad Zack Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_recent.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c index c7dce4e7..3dcb41dc 100644 --- a/extensions/libxt_recent.c +++ b/extensions/libxt_recent.c @@ -131,8 +131,6 @@ static void recent_parse(struct xt_option_call *cb) static void recent_check(struct xt_fcheck_call *cb) { - struct xt_recent_mtinfo *info = cb->data; - if (!(cb->xflags & F_ANY_OP)) xtables_error(PARAMETER_PROBLEM, "recent: you must specify one of `--set', `--rcheck' " -- cgit v1.2.3 From abdef13f36b63758f8775eb86febd96bf062df6f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 8 May 2012 03:16:52 +0000 Subject: libxt_hashlimit: add support for byte-based operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit allows --hashlimit-(upto|above) Xb/s [ --hashlimit-burst Yb ] to make hashlimit match when X bytes/second are exceeded; optionally, Y bytes will not be matched (i.e. bursted). [ Pablo fixed minor compilation warning in this patch with gcc-4.6 and x86_64 ] libxt_hashlimit.c: In function ‘parse_bytes’: libxt_hashlimit.c:216:6: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘uint64_t’ [-Wformat] Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_hashlimit.c | 171 ++++++++++++++++++++++++++++++--- extensions/libxt_hashlimit.man | 19 +++- include/linux/netfilter/xt_hashlimit.h | 6 +- tests/options-most.rules | 3 + 4 files changed, 183 insertions(+), 16 deletions(-) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index da34cb22..37a31489 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -20,6 +20,10 @@ #include #define XT_HASHLIMIT_BURST 5 +#define XT_HASHLIMIT_BURST_MAX 10000 + +#define XT_HASHLIMIT_BYTE_EXPIRE 15 +#define XT_HASHLIMIT_BYTE_EXPIRE_BURST 60 /* miliseconds */ #define XT_HASHLIMIT_GCINTERVAL 1000 @@ -59,6 +63,7 @@ enum { O_HTABLE_MAX, O_HTABLE_GCINT, O_HTABLE_EXPIRE, + F_BURST = 1 << O_BURST, F_UPTO = 1 << O_UPTO, F_ABOVE = 1 << O_ABOVE, F_HTABLE_EXPIRE = 1 << O_HTABLE_EXPIRE, @@ -90,7 +95,7 @@ static const struct xt_option_entry hashlimit_opts[] = { {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE, .type = XTTYPE_STRING}, {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32, - .min = 1, .max = 10000, .flags = XTOPT_PUT, + .min = 1, .max = XT_HASHLIMIT_BURST_MAX, .flags = XTOPT_PUT, XTOPT_POINTER(s, cfg.burst)}, {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE, .type = XTTYPE_UINT32, .flags = XTOPT_PUT, @@ -122,9 +127,7 @@ static const struct xt_option_entry hashlimit_mt_opts[] = { .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */ {.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN}, {.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN}, - {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32, - .min = 1, .max = 10000, .flags = XTOPT_PUT, - XTOPT_POINTER(s, cfg.burst)}, + {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING}, {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE, .type = XTTYPE_UINT32, .flags = XTOPT_PUT, XTOPT_POINTER(s, cfg.size)}, @@ -144,6 +147,82 @@ static const struct xt_option_entry hashlimit_mt_opts[] = { }; #undef s +static uint32_t cost_to_bytes(uint32_t cost) +{ + uint32_t r; + + r = cost ? UINT32_MAX / cost : UINT32_MAX; + r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT; + return r; +} + +static uint64_t bytes_to_cost(uint32_t bytes) +{ + uint32_t r = bytes >> XT_HASHLIMIT_BYTE_SHIFT; + return UINT32_MAX / (r+1); +} + +static uint32_t get_factor(int chr) +{ + switch (chr) { + case 'm': return 1024 * 1024; + case 'k': return 1024; + } + return 1; +} + +static void burst_error(void) +{ + xtables_error(PARAMETER_PROBLEM, "bad value for option " + "\"--hashlimit-burst\", or out of range (1-%u).", XT_HASHLIMIT_BURST_MAX); +} + +static uint32_t parse_burst(const char *burst, struct xt_hashlimit_mtinfo1 *info) +{ + uintmax_t v; + char *end; + + if (!xtables_strtoul(burst, &end, &v, 1, UINT32_MAX) || + (*end == 0 && v > XT_HASHLIMIT_BURST_MAX)) + burst_error(); + + v *= get_factor(*end); + if (v > UINT32_MAX) + xtables_error(PARAMETER_PROBLEM, "bad value for option " + "\"--hashlimit-burst\", value \"%s\" too large " + "(max %umb).", burst, UINT32_MAX/1024/1024); + return v; +} + +static bool parse_bytes(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud) +{ + unsigned int factor = 1; + uint64_t tmp; + int r; + const char *mode = strstr(rate, "b/s"); + if (!mode || mode == rate) + return false; + + mode--; + r = atoi(rate); + if (r == 0) + return false; + + factor = get_factor(*mode); + tmp = (uint64_t) r * factor; + if (tmp > UINT32_MAX) + xtables_error(PARAMETER_PROBLEM, + "Rate value too large \"%llu\" (max %u)\n", + (unsigned long long)tmp, UINT32_MAX); + + *val = bytes_to_cost(tmp); + if (*val == 0) + xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"\n", rate); + + ud->mult = XT_HASHLIMIT_BYTE_EXPIRE; + return true; +} + static int parse_rate(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud) { @@ -265,17 +344,24 @@ static void hashlimit_mt_parse(struct xt_option_call *cb) xtables_option_parse(cb); switch (cb->entry->id) { + case O_BURST: + info->cfg.burst = parse_burst(cb->arg, info); + break; case O_UPTO: if (cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) + if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata)) + info->cfg.mode |= XT_HASHLIMIT_BYTES; + else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", "--hashlimit-upto", cb->arg); break; case O_ABOVE: if (!cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) + if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata)) + info->cfg.mode |= XT_HASHLIMIT_BYTES; + else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", "--hashlimit-above", cb->arg); break; @@ -315,6 +401,24 @@ static void hashlimit_mt_check(struct xt_fcheck_call *cb) "You have to specify --hashlimit"); if (!(cb->xflags & F_HTABLE_EXPIRE)) info->cfg.expire = udata->mult * 1000; /* from s to msec */ + + if (info->cfg.mode & XT_HASHLIMIT_BYTES) { + uint32_t burst = 0; + if (cb->xflags & F_BURST) { + if (info->cfg.burst < cost_to_bytes(info->cfg.avg)) + xtables_error(PARAMETER_PROBLEM, + "burst cannot be smaller than %ub", cost_to_bytes(info->cfg.avg)); + + burst = info->cfg.burst; + burst /= cost_to_bytes(info->cfg.avg); + if (info->cfg.burst % cost_to_bytes(info->cfg.avg)) + burst++; + if (!(cb->xflags & F_HTABLE_EXPIRE)) + info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000; + } + info->cfg.burst = burst; + } else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX) + burst_error(); } static const struct rates @@ -340,6 +444,41 @@ static uint32_t print_rate(uint32_t period) return rates[i-1].mult / XT_HASHLIMIT_SCALE * 1000; } +static const struct { + const char *name; + uint32_t thresh; +} units[] = { + { "m", 1024 * 1024 }, + { "k", 1024 }, + { "", 1 }, +}; + +static uint32_t print_bytes(uint32_t avg, uint32_t burst, const char *prefix) +{ + unsigned int i; + unsigned long long r; + + r = cost_to_bytes(avg); + + for (i = 0; i < ARRAY_SIZE(units) -1; ++i) + if (r >= units[i].thresh && + bytes_to_cost(r & ~(units[i].thresh - 1)) == avg) + break; + printf(" %llu%sb/s", r/units[i].thresh, units[i].name); + + if (burst == 0) + return XT_HASHLIMIT_BYTE_EXPIRE * 1000; + + r *= burst; + printf(" %s", prefix); + for (i = 0; i < ARRAY_SIZE(units) -1; ++i) + if (r >= units[i].thresh) + break; + + printf("burst %llu%sb", r / units[i].thresh, units[i].name); + return XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000; +} + static void print_mode(unsigned int mode, char separator) { bool prevmode = false; @@ -398,8 +537,13 @@ hashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) fputs(" limit: above", stdout); else fputs(" limit: up to", stdout); - quantum = print_rate(info->cfg.avg); - printf(" burst %u", info->cfg.burst); + + if (info->cfg.mode & XT_HASHLIMIT_BYTES) { + quantum = print_bytes(info->cfg.avg, info->cfg.burst, ""); + } else { + quantum = print_rate(info->cfg.avg); + printf(" burst %u", info->cfg.burst); + } if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) { fputs(" mode", stdout); @@ -449,7 +593,7 @@ static void hashlimit_save(const void *ip, const struct xt_entry_match *match) fputs(" --hashlimit-mode", stdout); print_mode(r->cfg.mode, ','); - + printf(" --hashlimit-name %s", r->name); if (r->cfg.size) @@ -471,8 +615,13 @@ hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) fputs(" --hashlimit-above", stdout); else fputs(" --hashlimit-upto", stdout); - quantum = print_rate(info->cfg.avg); - printf(" --hashlimit-burst %u", info->cfg.burst); + + if (info->cfg.mode & XT_HASHLIMIT_BYTES) { + quantum = print_bytes(info->cfg.avg, info->cfg.burst, "--hashlimit-"); + } else { + quantum = print_rate(info->cfg.avg); + printf(" --hashlimit-burst %u", info->cfg.burst); + } if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) { diff --git a/extensions/libxt_hashlimit.man b/extensions/libxt_hashlimit.man index f90577e7..17cb2b00 100644 --- a/extensions/libxt_hashlimit.man +++ b/extensions/libxt_hashlimit.man @@ -2,14 +2,15 @@ \fBlimit\fP match) for a group of connections using a \fBsingle\fP iptables rule. Grouping can be done per-hostgroup (source and/or destination address) and/or per-port. It gives you the ability to express "\fIN\fP packets per time -quantum per group" (see below for some examples). +quantum per group" or "\fIN\fP bytes per seconds" (see below for some examples). .PP A hash limit option (\fB\-\-hashlimit\-upto\fP, \fB\-\-hashlimit\-above\fP) and \fB\-\-hashlimit\-name\fP are required. .TP \fB\-\-hashlimit\-upto\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP] -Match if the rate is below or equal to \fIamount\fP/quantum. It is specified as -a number, with an optional time quantum suffix; the default is 3/hour. +Match if the rate is below or equal to \fIamount\fP/quantum. It is specified either as +a number, with an optional time quantum suffix (the default is 3/hour), or as +\fIamount\fPb/second (number of bytes per second). .TP \fB\-\-hashlimit\-above\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP] Match if the rate is above \fIamount\fP/quantum. @@ -17,7 +18,9 @@ Match if the rate is above \fIamount\fP/quantum. \fB\-\-hashlimit\-burst\fP \fIamount\fP Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number; the -default is 5. +default is 5. When byte-based rate matching is requested, this option specifies +the amount of bytes that can exceed the given rate. This option should be used +with caution -- if the entry expires, the burst value is reset too. .TP \fB\-\-hashlimit\-mode\fP {\fBsrcip\fP|\fBsrcport\fP|\fBdstip\fP|\fBdstport\fP}\fB,\fP... A comma-separated list of objects to take into consideration. If no @@ -63,3 +66,11 @@ matching on subnet "10000 packets per minute for every /28 subnet (groups of 8 addresses) in 10.0.0.0/8" => \-s 10.0.0.8 \-\-hashlimit\-mask 28 \-\-hashlimit\-upto 10000/min +.TP +matching bytes per second +"flows exceeding 512kbyte/s" => +\-\-hashlimit-mode srcip,dstip,srcport,dstport \-\-hashlimit\-above 512kb/s +.TP +matching bytes per second +"hosts that exceed 512kbyte/s, but permit up to 1Megabytes without matching" +\-\-hashlimit-mode dstip \-\-hashlimit\-above 512kb/s \-\-hashlimit-burst 1mb diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h index b1925b59..141efbd1 100644 --- a/include/linux/netfilter/xt_hashlimit.h +++ b/include/linux/netfilter/xt_hashlimit.h @@ -6,7 +6,10 @@ /* timings are in milliseconds. */ #define XT_HASHLIMIT_SCALE 10000 /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 - seconds, or one every 59 hours. */ + seconds, or one packet every 59 hours. */ + +/* packet length accounting is done in 16-byte steps */ +#define XT_HASHLIMIT_BYTE_SHIFT 4 /* details of this structure hidden by the implementation */ struct xt_hashlimit_htable; @@ -17,6 +20,7 @@ enum { XT_HASHLIMIT_HASH_SIP = 1 << 2, XT_HASHLIMIT_HASH_SPT = 1 << 3, XT_HASHLIMIT_INVERT = 1 << 4, + XT_HASHLIMIT_BYTES = 1 << 5, }; struct hashlimit_cfg { diff --git a/tests/options-most.rules b/tests/options-most.rules index 30dac16b..ef4e7f1c 100644 --- a/tests/options-most.rules +++ b/tests/options-most.rules @@ -96,6 +96,9 @@ -A matches -m hashlimit --hashlimit-upto 1/min --hashlimit-burst 1 --hashlimit-name mini2 -A matches -m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 1 --hashlimit-name mini3 -A matches -m hashlimit --hashlimit-upto 1/day --hashlimit-burst 1 --hashlimit-name mini4 +-A matches -m hashlimit --hashlimit-upto 4kb/s --hashlimit-burst 400kb --hashlimit-name mini5 +-A matches -m hashlimit --hashlimit-upto 10mb/s --hashlimit-name mini6 +-A matches -m hashlimit --hashlimit-upto 123456b/s --hashlimit-burst 1mb --hashlimit-name mini7 -A matches -A matches -m hbh ! --hbh-len 5 -A matches -- cgit v1.2.3 From 3ee90dffea02c9be38dca6544ad5f22d4467e334 Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Mon, 16 Jul 2012 13:53:42 +0200 Subject: libxt_HMARK: fix output of iptables -L Fix accidental swap of [s|d]port-mask and [s|d]port-port. Use xtables_ipmask_to_cidr instead of xtables_ipmask_to_numeric. Signed-off-by: Hans Schillstrom Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_HMARK.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c index 719effe8..736a671a 100644 --- a/extensions/libxt_HMARK.c +++ b/extensions/libxt_HMARK.c @@ -282,15 +282,15 @@ static void HMARK_check(struct xt_fcheck_call *cb) static void HMARK_print(const struct xt_hmark_info *info) { - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT)) + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK)) printf("sport-mask 0x%x ", htons(info->port_mask.p16.src)); - if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT)) + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)) printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI)) printf("spi-mask 0x%x ", htonl(info->port_mask.v32)); - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK)) + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT)) printf("sport-set 0x%x ", htons(info->port_set.p16.src)); - if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)) + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT)) printf("dport-set 0x%x ", htons(info->port_set.p16.dst)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK)) printf("spi-set 0x%x ", htonl(info->port_set.v32)); @@ -335,11 +335,11 @@ static void HMARK_ip4_print(const void *ip, if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT)) printf("ct, "); if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) - printf("src-prefix %s ", - xtables_ipmask_to_numeric(&info->src_mask.in) + 1); + printf("src-prefix %u ", + xtables_ipmask_to_cidr(&info->src_mask.in)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) - printf("dst-prefix %s ", - xtables_ipmask_to_numeric(&info->dst_mask.in) + 1); + printf("dst-prefix %u ", + xtables_ipmask_to_cidr(&info->dst_mask.in)); HMARK_print(info); } -- cgit v1.2.3 From 7fb49101acfbec265e96c1d5e475c7051beece19 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Jul 2012 14:04:10 +0200 Subject: libxt_HMARK: fix ct case example ... -j HMARK --hmark-tuple ct,src,dst --hmark-offset 10000 ... Note `ct' requires also the tuples. Reported-by: Hans Schillstrom Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_HMARK.man | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man index 2b004b5a..0b418842 100644 --- a/extensions/libxt_HMARK.man +++ b/extensions/libxt_HMARK.man @@ -53,8 +53,8 @@ A 32 bit random custom value to feed hash calculation. \fIExamples:\fP .PP iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW - \-j HMARK \-\-hmark-tuple ct \-\-hmark-offset 10000 \-\-hmark\-mod 10 -\-\-hmark\-rnd 0xfeedcafe + \-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark-offset 10000 +\-\-hmark\-mod 10 \-\-hmark\-rnd 0xfeedcafe .PP iptables \-t mangle \-A PREROUTING -j HMARK \-\-hmark\-offset 10000 \-\-hmark-tuple src,dst,proto \-\-hmark-mod 10 \-\-hmark\-rnd 0xdeafbeef -- cgit v1.2.3 From f4a6c20c39c97214e22625764bfa80ef8e1e3147 Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Tue, 17 Jul 2012 18:27:24 +0200 Subject: libxt_HMARK: correct a number of errors introduced by Pablo's rework * Fix typo in --hmark-rnd description. * Remove trailing -set from port and spi options. * Take missing value for ports and spi from command line. * Fix spi / port validation. * Remove --hmark-offset as mandatory. Signed-off-by: Hans Schillstrom Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_HMARK.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c index 736a671a..94aebe9a 100644 --- a/extensions/libxt_HMARK.c +++ b/extensions/libxt_HMARK.c @@ -26,16 +26,16 @@ static void HMARK_help(void) " --hmark-tuple [src|dst|sport|dport|spi|proto|ct][,...]\n" " --hmark-mod value nfmark modulus value\n" " --hmark-offset value Last action add value to nfmark\n\n" -" --hmark-rnd Random seed for hashing\n" +" --hmark-rnd Random see for hashing\n" " Alternatively, fine tuning of what will be included in hash calculation\n" " --hmark-src-prefix length Source address mask CIDR prefix\n" " --hmark-dst-prefix length Dest address mask CIDR prefix\n" " --hmark-sport-mask value Mask src port with value\n" " --hmark-dport-mask value Mask dst port with value\n" " --hmark-spi-mask value For esp and ah AND spi with value\n" -" --hmark-sport-set value OR src port with value\n" -" --hmark-dport-set value OR dst port with value\n" -" --hmark-spi-set value For esp and ah OR spi with value\n" +" --hmark-sport value OR src port with value\n" +" --hmark-dport value OR dst port with value\n" +" --hmark-spi value For esp and ah OR spi with value\n" " --hmark-proto-mask value Mask Protocol with value\n"); } @@ -218,20 +218,29 @@ static void HMARK_parse(struct xt_option_call *cb, int plen) info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK); break; case O_HMARK_SPI: - info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK); + info->port_set.v32 = htonl(cb->val.u32); + info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI); break; case O_HMARK_SPORT: + info->port_set.p16.src = htons(cb->val.u16); info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT); break; case O_HMARK_DPORT: + info->port_set.p16.dst = htons(cb->val.u16); info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT); break; case O_HMARK_SPORT_MASK: + info->port_mask.p16.src = htons(cb->val.u16); info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK); break; case O_HMARK_DPORT_MASK: + info->port_mask.p16.dst = htons(cb->val.u16); info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK); break; + case O_HMARK_SPI_MASK: + info->port_mask.v32 = htonl(cb->val.u32); + info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK); + break; case O_HMARK_PROTO_MASK: info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK); break; @@ -267,8 +276,8 @@ static void HMARK_check(struct xt_fcheck_call *cb) if (!(cb->xflags & (1 << O_HMARK_RND))) xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory"); if (cb->xflags & (1 << O_HMARK_SPI_MASK) && - (cb->xflags & (1 << O_HMARK_SPORT_MASK || - cb->xflags & (1 << O_HMARK_DPORT_MASK)))) + (cb->xflags & ((1 << O_HMARK_SPORT_MASK) | + (1 << O_HMARK_DPORT_MASK)))) xtables_error(PARAMETER_PROBLEM, "you cannot use " "--hmark-spi-mask and --hmark-?port-mask," "at the same time"); @@ -276,8 +285,6 @@ static void HMARK_check(struct xt_fcheck_call *cb) cb->xflags & (1 << O_HMARK_CT))) xtables_error(PARAMETER_PROBLEM, "you have to specify " "--hmark-tuple at least"); - if (!(cb->xflags & (1 << O_HMARK_OFFSET))) - xtables_error(PARAMETER_PROBLEM, "--hmark-offset is mandatory"); } static void HMARK_print(const struct xt_hmark_info *info) @@ -286,14 +293,14 @@ static void HMARK_print(const struct xt_hmark_info *info) printf("sport-mask 0x%x ", htons(info->port_mask.p16.src)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)) printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst)); - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI)) + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK)) printf("spi-mask 0x%x ", htonl(info->port_mask.v32)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT)) - printf("sport-set 0x%x ", htons(info->port_set.p16.src)); + printf("sport 0x%x ", htons(info->port_set.p16.src)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT)) - printf("dport-set 0x%x ", htons(info->port_set.p16.dst)); - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK)) - printf("spi-set 0x%x ", htonl(info->port_set.v32)); + printf("dport 0x%x ", htons(info->port_set.p16.dst)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI)) + printf("spi 0x%x ", htonl(info->port_set.v32)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK)) printf("proto-mask 0x%x ", info->proto_mask); if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND)) @@ -351,17 +358,17 @@ static void HMARK_save(const struct xt_hmark_info *info) if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)) printf(" --hmark-dport-mask 0x%04x", htons(info->port_mask.p16.dst)); - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI)) + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK)) printf(" --hmark-spi-mask 0x%08x", htonl(info->port_mask.v32)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT)) - printf(" --hmark-sport-set 0x%04x", + printf(" --hmark-sport 0x%04x", htons(info->port_set.p16.src)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT)) - printf(" --hmark-dport-set 0x%04x", + printf(" --hmark-dport 0x%04x", htons(info->port_set.p16.dst)); - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK)) - printf(" --hmark-spi-set 0x%08x", htonl(info->port_set.v32)); + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI)) + printf(" --hmark-spi 0x%08x", htonl(info->port_set.v32)); if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK)) printf(" --hmark-proto-mask 0x%02x", info->proto_mask); if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND)) -- cgit v1.2.3 From 44191bdbd71e685fba9eab864b9df25e63905220 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 23 Jul 2012 12:27:16 +0200 Subject: iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7) This patch seems to be a mere cleanup that moves the parameter parsing code to add_param_to_argv. But, in reality, it also fixes iptables when compiled with gcc-4.7. Moving param_buffer declaration out of the loop seems to resolve the issue. gcc-4.7 seems to be generating bad code regarding param_buffer. @@ -380,9 +380,9 @@ quote_open = 0; escaped = 0; param_len = 0; + char param_buffer[1024]; for (curchar = parsestart; *curchar; curchar++) { - char param_buffer[1024]; if (quote_open) { if (escaped) { But I have hard time to apply this patch in such a way. Instead, I came up with the idea of this cleanup, which does not harm after all (and fixes the issue for us). Someone in: https://bugzilla.redhat.com/show_bug.cgi?id=82579 put some light on this: "Yes, I ran into this too. The issue is that the gcc optimizer is optimizing out the code that collects quoted strings in iptables-restore.c at line 396. If inside a quotemark and it hasn't seen another one yet, it executes param_buffer[param_len++] = *curchar; continue; At -O1 or higher, the write to param_buffer[] never happens. It just increments param_len and continues. Moving the definition of char param_buffer[1024]; outside the loop fixes it. Why, I'm not sure. Defining the param_buffer[] inside the loop should simply restrict its scope to inside the loop." Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.c | 133 +++++++++++++++++++++---------------------- iptables/iptables-restore.c | 133 +++++++++++++++++++++---------------------- 2 files changed, 130 insertions(+), 136 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 3894d68d..9a03dff4 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -114,6 +114,70 @@ static void free_argv(void) { free(newargv[i]); } +static void add_param_to_argv(char *parsestart) +{ + int quote_open = 0, escaped = 0, param_len = 0; + char param_buffer[1024], *curchar; + + /* After fighting with strtok enough, here's now + * a 'real' parser. According to Rusty I'm now no + * longer a real hacker, but I can live with that */ + + for (curchar = parsestart; *curchar; curchar++) { + if (quote_open) { + if (escaped) { + param_buffer[param_len++] = *curchar; + escaped = 0; + continue; + } else if (*curchar == '\\') { + escaped = 1; + continue; + } else if (*curchar == '"') { + quote_open = 0; + *curchar = ' '; + } else { + param_buffer[param_len++] = *curchar; + continue; + } + } else { + if (*curchar == '"') { + quote_open = 1; + continue; + } + } + + if (*curchar == ' ' + || *curchar == '\t' + || * curchar == '\n') { + if (!param_len) { + /* two spaces? */ + continue; + } + + param_buffer[param_len] = '\0'; + + /* check if table name specified */ + if (!strncmp(param_buffer, "-t", 2) + || !strncmp(param_buffer, "--table", 8)) { + xtables_error(PARAMETER_PROBLEM, + "Line %u seems to have a " + "-t table option.\n", line); + exit(1); + } + + add_argv(param_buffer); + param_len = 0; + } else { + /* regular character, copy to buffer */ + param_buffer[param_len++] = *curchar; + + if (param_len >= sizeof(param_buffer)) + xtables_error(PARAMETER_PROBLEM, + "Parameter too long!"); + } + } +} + int ip6tables_restore_main(int argc, char *argv[]) { struct xtc_handle *handle = NULL; @@ -325,11 +389,6 @@ int ip6tables_restore_main(int argc, char *argv[]) char *bcnt = NULL; char *parsestart; - /* the parser */ - char *curchar; - int quote_open, escaped; - size_t param_len; - /* reset the newargv */ newargc = 0; @@ -370,69 +429,7 @@ int ip6tables_restore_main(int argc, char *argv[]) add_argv((char *) bcnt); } - /* After fighting with strtok enough, here's now - * a 'real' parser. According to Rusty I'm now no - * longer a real hacker, but I can live with that */ - - quote_open = 0; - escaped = 0; - param_len = 0; - - for (curchar = parsestart; *curchar; curchar++) { - char param_buffer[1024]; - - if (quote_open) { - if (escaped) { - param_buffer[param_len++] = *curchar; - escaped = 0; - continue; - } else if (*curchar == '\\') { - escaped = 1; - continue; - } else if (*curchar == '"') { - quote_open = 0; - *curchar = ' '; - } else { - param_buffer[param_len++] = *curchar; - continue; - } - } else { - if (*curchar == '"') { - quote_open = 1; - continue; - } - } - - if (*curchar == ' ' - || *curchar == '\t' - || * curchar == '\n') { - if (!param_len) { - /* two spaces? */ - continue; - } - - param_buffer[param_len] = '\0'; - - /* check if table name specified */ - if (!strncmp(param_buffer, "-t", 2) - || !strncmp(param_buffer, "--table", 8)) { - xtables_error(PARAMETER_PROBLEM, - "Line %u seems to have a " - "-t table option.\n", line); - exit(1); - } - - add_argv(param_buffer); - param_len = 0; - } else { - /* regular character, copy to buffer */ - param_buffer[param_len++] = *curchar; - - if (param_len >= sizeof(param_buffer)) - xtables_error(PARAMETER_PROBLEM, - "Parameter too long!"); - } - } + add_param_to_argv(parsestart); DEBUGP("calling do_command6(%u, argv, &%s, handle):\n", newargc, curtable); diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 034f9606..c974cb37 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -113,6 +113,70 @@ static void free_argv(void) { free(newargv[i]); } +static void add_param_to_argv(char *parsestart) +{ + int quote_open = 0, escaped = 0, param_len = 0; + char param_buffer[1024], *curchar; + + /* After fighting with strtok enough, here's now + * a 'real' parser. According to Rusty I'm now no + * longer a real hacker, but I can live with that */ + + for (curchar = parsestart; *curchar; curchar++) { + if (quote_open) { + if (escaped) { + param_buffer[param_len++] = *curchar; + escaped = 0; + continue; + } else if (*curchar == '\\') { + escaped = 1; + continue; + } else if (*curchar == '"') { + quote_open = 0; + *curchar = ' '; + } else { + param_buffer[param_len++] = *curchar; + continue; + } + } else { + if (*curchar == '"') { + quote_open = 1; + continue; + } + } + + if (*curchar == ' ' + || *curchar == '\t' + || * curchar == '\n') { + if (!param_len) { + /* two spaces? */ + continue; + } + + param_buffer[param_len] = '\0'; + + /* check if table name specified */ + if (!strncmp(param_buffer, "-t", 2) + || !strncmp(param_buffer, "--table", 8)) { + xtables_error(PARAMETER_PROBLEM, + "Line %u seems to have a " + "-t table option.\n", line); + exit(1); + } + + add_argv(param_buffer); + param_len = 0; + } else { + /* regular character, copy to buffer */ + param_buffer[param_len++] = *curchar; + + if (param_len >= sizeof(param_buffer)) + xtables_error(PARAMETER_PROBLEM, + "Parameter too long!"); + } + } +} + int iptables_restore_main(int argc, char *argv[]) { @@ -325,11 +389,6 @@ iptables_restore_main(int argc, char *argv[]) char *bcnt = NULL; char *parsestart; - /* the parser */ - char *curchar; - int quote_open, escaped; - size_t param_len; - /* reset the newargv */ newargc = 0; @@ -370,69 +429,7 @@ iptables_restore_main(int argc, char *argv[]) add_argv((char *) bcnt); } - /* After fighting with strtok enough, here's now - * a 'real' parser. According to Rusty I'm now no - * longer a real hacker, but I can live with that */ - - quote_open = 0; - escaped = 0; - param_len = 0; - - for (curchar = parsestart; *curchar; curchar++) { - char param_buffer[1024]; - - if (quote_open) { - if (escaped) { - param_buffer[param_len++] = *curchar; - escaped = 0; - continue; - } else if (*curchar == '\\') { - escaped = 1; - continue; - } else if (*curchar == '"') { - quote_open = 0; - *curchar = ' '; - } else { - param_buffer[param_len++] = *curchar; - continue; - } - } else { - if (*curchar == '"') { - quote_open = 1; - continue; - } - } - - if (*curchar == ' ' - || *curchar == '\t' - || * curchar == '\n') { - if (!param_len) { - /* two spaces? */ - continue; - } - - param_buffer[param_len] = '\0'; - - /* check if table name specified */ - if (!strncmp(param_buffer, "-t", 2) - || !strncmp(param_buffer, "--table", 8)) { - xtables_error(PARAMETER_PROBLEM, - "Line %u seems to have a " - "-t table option.\n", line); - exit(1); - } - - add_argv(param_buffer); - param_len = 0; - } else { - /* regular character, copy to buffer */ - param_buffer[param_len++] = *curchar; - - if (param_len >= sizeof(param_buffer)) - xtables_error(PARAMETER_PROBLEM, - "Parameter too long!"); - } - } + add_param_to_argv(parsestart); DEBUGP("calling do_command4(%u, argv, &%s, handle):\n", newargc, curtable); -- cgit v1.2.3 From f1c668268e9ddaedd8d78d7ae44cd26db1e8469f Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 30 Jul 2012 02:56:43 +0200 Subject: Revert "iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)" This reverts commit 44191bdbd71e685fba9eab864b9df25e63905220. Apply instead a patch that really clarifies the bug in iptables-restore. This should be good for the record (specifically, for distributors so they can find the fix by googling). --- iptables/ip6tables-restore.c | 133 ++++++++++++++++++++++--------------------- iptables/iptables-restore.c | 133 ++++++++++++++++++++++--------------------- 2 files changed, 136 insertions(+), 130 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 9a03dff4..3894d68d 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -114,70 +114,6 @@ static void free_argv(void) { free(newargv[i]); } -static void add_param_to_argv(char *parsestart) -{ - int quote_open = 0, escaped = 0, param_len = 0; - char param_buffer[1024], *curchar; - - /* After fighting with strtok enough, here's now - * a 'real' parser. According to Rusty I'm now no - * longer a real hacker, but I can live with that */ - - for (curchar = parsestart; *curchar; curchar++) { - if (quote_open) { - if (escaped) { - param_buffer[param_len++] = *curchar; - escaped = 0; - continue; - } else if (*curchar == '\\') { - escaped = 1; - continue; - } else if (*curchar == '"') { - quote_open = 0; - *curchar = ' '; - } else { - param_buffer[param_len++] = *curchar; - continue; - } - } else { - if (*curchar == '"') { - quote_open = 1; - continue; - } - } - - if (*curchar == ' ' - || *curchar == '\t' - || * curchar == '\n') { - if (!param_len) { - /* two spaces? */ - continue; - } - - param_buffer[param_len] = '\0'; - - /* check if table name specified */ - if (!strncmp(param_buffer, "-t", 2) - || !strncmp(param_buffer, "--table", 8)) { - xtables_error(PARAMETER_PROBLEM, - "Line %u seems to have a " - "-t table option.\n", line); - exit(1); - } - - add_argv(param_buffer); - param_len = 0; - } else { - /* regular character, copy to buffer */ - param_buffer[param_len++] = *curchar; - - if (param_len >= sizeof(param_buffer)) - xtables_error(PARAMETER_PROBLEM, - "Parameter too long!"); - } - } -} - int ip6tables_restore_main(int argc, char *argv[]) { struct xtc_handle *handle = NULL; @@ -389,6 +325,11 @@ int ip6tables_restore_main(int argc, char *argv[]) char *bcnt = NULL; char *parsestart; + /* the parser */ + char *curchar; + int quote_open, escaped; + size_t param_len; + /* reset the newargv */ newargc = 0; @@ -429,7 +370,69 @@ int ip6tables_restore_main(int argc, char *argv[]) add_argv((char *) bcnt); } - add_param_to_argv(parsestart); + /* After fighting with strtok enough, here's now + * a 'real' parser. According to Rusty I'm now no + * longer a real hacker, but I can live with that */ + + quote_open = 0; + escaped = 0; + param_len = 0; + + for (curchar = parsestart; *curchar; curchar++) { + char param_buffer[1024]; + + if (quote_open) { + if (escaped) { + param_buffer[param_len++] = *curchar; + escaped = 0; + continue; + } else if (*curchar == '\\') { + escaped = 1; + continue; + } else if (*curchar == '"') { + quote_open = 0; + *curchar = ' '; + } else { + param_buffer[param_len++] = *curchar; + continue; + } + } else { + if (*curchar == '"') { + quote_open = 1; + continue; + } + } + + if (*curchar == ' ' + || *curchar == '\t' + || * curchar == '\n') { + if (!param_len) { + /* two spaces? */ + continue; + } + + param_buffer[param_len] = '\0'; + + /* check if table name specified */ + if (!strncmp(param_buffer, "-t", 2) + || !strncmp(param_buffer, "--table", 8)) { + xtables_error(PARAMETER_PROBLEM, + "Line %u seems to have a " + "-t table option.\n", line); + exit(1); + } + + add_argv(param_buffer); + param_len = 0; + } else { + /* regular character, copy to buffer */ + param_buffer[param_len++] = *curchar; + + if (param_len >= sizeof(param_buffer)) + xtables_error(PARAMETER_PROBLEM, + "Parameter too long!"); + } + } DEBUGP("calling do_command6(%u, argv, &%s, handle):\n", newargc, curtable); diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index c974cb37..034f9606 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -113,70 +113,6 @@ static void free_argv(void) { free(newargv[i]); } -static void add_param_to_argv(char *parsestart) -{ - int quote_open = 0, escaped = 0, param_len = 0; - char param_buffer[1024], *curchar; - - /* After fighting with strtok enough, here's now - * a 'real' parser. According to Rusty I'm now no - * longer a real hacker, but I can live with that */ - - for (curchar = parsestart; *curchar; curchar++) { - if (quote_open) { - if (escaped) { - param_buffer[param_len++] = *curchar; - escaped = 0; - continue; - } else if (*curchar == '\\') { - escaped = 1; - continue; - } else if (*curchar == '"') { - quote_open = 0; - *curchar = ' '; - } else { - param_buffer[param_len++] = *curchar; - continue; - } - } else { - if (*curchar == '"') { - quote_open = 1; - continue; - } - } - - if (*curchar == ' ' - || *curchar == '\t' - || * curchar == '\n') { - if (!param_len) { - /* two spaces? */ - continue; - } - - param_buffer[param_len] = '\0'; - - /* check if table name specified */ - if (!strncmp(param_buffer, "-t", 2) - || !strncmp(param_buffer, "--table", 8)) { - xtables_error(PARAMETER_PROBLEM, - "Line %u seems to have a " - "-t table option.\n", line); - exit(1); - } - - add_argv(param_buffer); - param_len = 0; - } else { - /* regular character, copy to buffer */ - param_buffer[param_len++] = *curchar; - - if (param_len >= sizeof(param_buffer)) - xtables_error(PARAMETER_PROBLEM, - "Parameter too long!"); - } - } -} - int iptables_restore_main(int argc, char *argv[]) { @@ -389,6 +325,11 @@ iptables_restore_main(int argc, char *argv[]) char *bcnt = NULL; char *parsestart; + /* the parser */ + char *curchar; + int quote_open, escaped; + size_t param_len; + /* reset the newargv */ newargc = 0; @@ -429,7 +370,69 @@ iptables_restore_main(int argc, char *argv[]) add_argv((char *) bcnt); } - add_param_to_argv(parsestart); + /* After fighting with strtok enough, here's now + * a 'real' parser. According to Rusty I'm now no + * longer a real hacker, but I can live with that */ + + quote_open = 0; + escaped = 0; + param_len = 0; + + for (curchar = parsestart; *curchar; curchar++) { + char param_buffer[1024]; + + if (quote_open) { + if (escaped) { + param_buffer[param_len++] = *curchar; + escaped = 0; + continue; + } else if (*curchar == '\\') { + escaped = 1; + continue; + } else if (*curchar == '"') { + quote_open = 0; + *curchar = ' '; + } else { + param_buffer[param_len++] = *curchar; + continue; + } + } else { + if (*curchar == '"') { + quote_open = 1; + continue; + } + } + + if (*curchar == ' ' + || *curchar == '\t' + || * curchar == '\n') { + if (!param_len) { + /* two spaces? */ + continue; + } + + param_buffer[param_len] = '\0'; + + /* check if table name specified */ + if (!strncmp(param_buffer, "-t", 2) + || !strncmp(param_buffer, "--table", 8)) { + xtables_error(PARAMETER_PROBLEM, + "Line %u seems to have a " + "-t table option.\n", line); + exit(1); + } + + add_argv(param_buffer); + param_len = 0; + } else { + /* regular character, copy to buffer */ + param_buffer[param_len++] = *curchar; + + if (param_len >= sizeof(param_buffer)) + xtables_error(PARAMETER_PROBLEM, + "Parameter too long!"); + } + } DEBUGP("calling do_command4(%u, argv, &%s, handle):\n", newargc, curtable); -- cgit v1.2.3 From 2165f38d2582e88e8a9dd9416f34eca7a7672e5a Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 30 Jul 2012 03:08:51 +0200 Subject: iptables-restore: fix parameter parsing (shows up with gcc-4.7) This patch fixes parameter parsing in iptables-restore since time ago. The problem has shown up with gcc-4.7. This version of gcc seem to perform more agressive memory management than previous. Peter Lekensteyn provided the following sample code similar to the one in iptables-restore: int i = 0; for (;;) { char x[5]; x[i] = '0' + i; if (++i == 4) { x[i] = '\0'; /* terminate string with null byte */ printf("%s\n", x); break; } } Many may expect 0123 as output. But GCC 4.7 does not do that when compiling with optimization enabled (-O1 and higher). It instead puts random data in the first bytes of the character array, which becomes: | 0 | 1 | 2 | 3 | 4 | | RANDOM | '3' | '\0' | Since the array is declared inside the scope of loop's body, you can think of it as of a new array being allocated in the automatic storage area for each loop iteration. The correct code should be: char x[5]; for (;;) { x[i] = '0' + i; if (++i == 4) { x[i] = '\0'; /* terminate string with null byte */ printf("%s\n", x); break; } } Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.c | 3 +-- iptables/iptables-restore.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 3894d68d..1ec3dd95 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -329,6 +329,7 @@ int ip6tables_restore_main(int argc, char *argv[]) char *curchar; int quote_open, escaped; size_t param_len; + char param_buffer[1024]; /* reset the newargv */ newargc = 0; @@ -379,8 +380,6 @@ int ip6tables_restore_main(int argc, char *argv[]) param_len = 0; for (curchar = parsestart; *curchar; curchar++) { - char param_buffer[1024]; - if (quote_open) { if (escaped) { param_buffer[param_len++] = *curchar; diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 034f9606..9f51f993 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -329,6 +329,7 @@ iptables_restore_main(int argc, char *argv[]) char *curchar; int quote_open, escaped; size_t param_len; + char param_buffer[1024]; /* reset the newargv */ newargc = 0; @@ -379,8 +380,6 @@ iptables_restore_main(int argc, char *argv[]) param_len = 0; for (curchar = parsestart; *curchar; curchar++) { - char param_buffer[1024]; - if (quote_open) { if (escaped) { param_buffer[param_len++] = *curchar; -- cgit v1.2.3 From 74ded7257e5da5e309844d386290f24ae91950a6 Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Thu, 17 May 2012 10:08:57 +0000 Subject: libxt_recent: add --mask netmask This new option will be available in the Linux kernel 3.5 [ Pablo fixed coding-style issues and cleaned up this. Added manpages as well ] Signed-off-by: Denys Fedoryshchenko Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_recent.c | 179 +++++++++++++++++++++++++++++++----- extensions/libxt_recent.man | 3 + include/linux/netfilter/xt_recent.h | 10 ++ 3 files changed, 171 insertions(+), 21 deletions(-) diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c index 3dcb41dc..f4ebe6a3 100644 --- a/extensions/libxt_recent.c +++ b/extensions/libxt_recent.c @@ -16,6 +16,7 @@ enum { O_NAME, O_RSOURCE, O_RDEST, + O_MASK, F_SET = 1 << O_SET, F_RCHECK = 1 << O_RCHECK, F_UPDATE = 1 << O_UPDATE, @@ -25,7 +26,7 @@ enum { }; #define s struct xt_recent_mtinfo -static const struct xt_option_entry recent_opts[] = { +static const struct xt_option_entry recent_opts_v0[] = { {.name = "set", .id = O_SET, .type = XTTYPE_NONE, .excl = F_ANY_OP, .flags = XTOPT_INVERT}, {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE, @@ -50,6 +51,32 @@ static const struct xt_option_entry recent_opts[] = { }; #undef s +#define s struct xt_recent_mtinfo_v1 +static const struct xt_option_entry recent_opts_v1[] = { + {.name = "set", .id = O_SET, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)}, + {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)}, + {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE, + .excl = F_SET | F_REMOVE}, + {.name = "name", .id = O_NAME, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, name)}, + {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE}, + {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE}, + {.name = "mask", .id = O_MASK, .type = XTTYPE_HOST, + .flags = XTOPT_PUT, XTOPT_POINTER(s, mask)}, + XTOPT_TABLEEND, +}; +#undef s + static void recent_help(void) { printf( @@ -74,18 +101,28 @@ static void recent_help(void) " --name name Name of the recent list to be used. DEFAULT used if none given.\n" " --rsource Match/Save the source address of each packet in the recent list table (default).\n" " --rdest Match/Save the destination address of each packet in the recent list table.\n" +" --mask netmask Netmask that will be applied to this recent list.\n" "xt_recent by: Stephen Frost . http://snowman.net/projects/ipt_recent/\n"); } -static void recent_init(struct xt_entry_match *match) +enum { + XT_RECENT_REV_0 = 0, + XT_RECENT_REV_1, +}; + +static void recent_init(struct xt_entry_match *match, unsigned int rev) { - struct xt_recent_mtinfo *info = (void *)(match)->data; + struct xt_recent_mtinfo *info = (struct xt_recent_mtinfo *)match->data; + struct xt_recent_mtinfo_v1 *info_v1 = + (struct xt_recent_mtinfo_v1 *)match->data; strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN); /* even though XT_RECENT_NAME_LEN is currently defined as 200, * better be safe, than sorry */ info->name[XT_RECENT_NAME_LEN-1] = '\0'; info->side = XT_RECENT_SOURCE; + if (rev == XT_RECENT_REV_1) + memset(&info_v1->mask, 0xFF, sizeof(info_v1->mask)); } static void recent_parse(struct xt_option_call *cb) @@ -138,9 +175,9 @@ static void recent_check(struct xt_fcheck_call *cb) } static void recent_print(const void *ip, const struct xt_entry_match *match, - int numeric) + unsigned int family) { - const struct xt_recent_mtinfo *info = (const void *)match->data; + const struct xt_recent_mtinfo_v1 *info = (const void *)match->data; if (info->invert) printf(" !"); @@ -165,11 +202,23 @@ static void recent_print(const void *ip, const struct xt_entry_match *match, printf(" side: source"); if (info->side == XT_RECENT_DEST) printf(" side: dest"); + + switch(family) { + case NFPROTO_IPV4: + printf(" mask: %s", + xtables_ipaddr_to_numeric(&info->mask.in)); + break; + case NFPROTO_IPV6: + printf(" mask: %s", + xtables_ip6addr_to_numeric(&info->mask.in6)); + break; + } } -static void recent_save(const void *ip, const struct xt_entry_match *match) +static void recent_save(const void *ip, const struct xt_entry_match *match, + unsigned int family) { - const struct xt_recent_mtinfo *info = (const void *)match->data; + const struct xt_recent_mtinfo_v1 *info = (const void *)match->data; if (info->invert) printf(" !"); @@ -189,28 +238,116 @@ static void recent_save(const void *ip, const struct xt_entry_match *match) if (info->check_set & XT_RECENT_TTL) printf(" --rttl"); if(info->name) printf(" --name %s",info->name); + + switch(family) { + case NFPROTO_IPV4: + printf(" --mask %s", + xtables_ipaddr_to_numeric(&info->mask.in)); + break; + case NFPROTO_IPV6: + printf(" --mask %s", + xtables_ip6addr_to_numeric(&info->mask.in6)); + break; + } + if (info->side == XT_RECENT_SOURCE) printf(" --rsource"); if (info->side == XT_RECENT_DEST) printf(" --rdest"); } -static struct xtables_match recent_mt_reg = { - .name = "recent", - .version = XTABLES_VERSION, - .family = NFPROTO_UNSPEC, - .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)), - .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)), - .help = recent_help, - .init = recent_init, - .x6_parse = recent_parse, - .x6_fcheck = recent_check, - .print = recent_print, - .save = recent_save, - .x6_options = recent_opts, +static void recent_init_v0(struct xt_entry_match *match) +{ + recent_init(match, XT_RECENT_REV_0); +} + +static void recent_init_v1(struct xt_entry_match *match) +{ + recent_init(match, XT_RECENT_REV_1); +} + +static void recent_save_v0(const void *ip, const struct xt_entry_match *match) +{ + recent_save(ip, match, NFPROTO_UNSPEC); +} + +static void recent_save_v4(const void *ip, const struct xt_entry_match *match) +{ + recent_save(ip, match, NFPROTO_IPV4); +} + +static void recent_save_v6(const void *ip, const struct xt_entry_match *match) +{ + recent_save(ip, match, NFPROTO_IPV6); +} + +static void recent_print_v0(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + recent_print(ip, match, NFPROTO_UNSPEC); +} + +static void recent_print_v4(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + recent_print(ip, match, NFPROTO_IPV4); +} + +static void recent_print_v6(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + recent_print(ip, match, NFPROTO_IPV6); +} + +static struct xtables_match recent_mt_reg[] = { + { + .name = "recent", + .version = XTABLES_VERSION, + .revision = 0, + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)), + .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)), + .help = recent_help, + .init = recent_init_v0, + .x6_parse = recent_parse, + .x6_fcheck = recent_check, + .print = recent_print_v0, + .save = recent_save_v0, + .x6_options = recent_opts_v0, + }, + { + .name = "recent", + .version = XTABLES_VERSION, + .revision = 1, + .family = NFPROTO_IPV4, + .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)), + .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)), + .help = recent_help, + .init = recent_init_v1, + .x6_parse = recent_parse, + .x6_fcheck = recent_check, + .print = recent_print_v4, + .save = recent_save_v4, + .x6_options = recent_opts_v1, + }, + { + .name = "recent", + .version = XTABLES_VERSION, + .revision = 1, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)), + .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)), + .help = recent_help, + .init = recent_init_v1, + .x6_parse = recent_parse, + .x6_fcheck = recent_check, + .print = recent_print_v6, + .save = recent_save_v6, + .x6_options = recent_opts_v1, + }, }; void _init(void) { - xtables_register_match(&recent_mt_reg); + xtables_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); } diff --git a/extensions/libxt_recent.man b/extensions/libxt_recent.man index 8043df4a..8e6a8e91 100644 --- a/extensions/libxt_recent.man +++ b/extensions/libxt_recent.man @@ -24,6 +24,9 @@ is the default. \fB\-\-rdest\fP Match/save the destination address of each packet in the recent list table. .TP +\fB\-\-mask\fPnetmask +Netmask that will be applied to this recent list. +.TP [\fB!\fP] \fB\-\-rcheck\fP Check if the source address of the packet is currently in the list. .TP diff --git a/include/linux/netfilter/xt_recent.h b/include/linux/netfilter/xt_recent.h index 83318e01..6ef36c11 100644 --- a/include/linux/netfilter/xt_recent.h +++ b/include/linux/netfilter/xt_recent.h @@ -32,4 +32,14 @@ struct xt_recent_mtinfo { __u8 side; }; +struct xt_recent_mtinfo_v1 { + __u32 seconds; + __u32 hit_count; + __u8 check_set; + __u8 invert; + char name[XT_RECENT_NAME_LEN]; + __u8 side; + union nf_inet_addr mask; +}; + #endif /* _LINUX_NETFILTER_XT_RECENT_H */ -- cgit v1.2.3 From 42ba40035e40b492e8667932f20922cee0682167 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 31 Jul 2012 12:44:36 +0200 Subject: bump version to 1.4.15 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 989ffd73..179c2d82 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.14]) +AC_INIT([iptables], [1.4.15]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=8 -- cgit v1.2.3 From c5300d11308ccb429d551c32dffe752575c30b77 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 17 Jun 2012 11:49:22 +0200 Subject: iptables-restore: warn about -t in rule lines save-restore syntax uses *table, not -t table. Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.c | 6 ++++-- iptables/iptables-restore.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 1ec3dd95..294b242e 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -416,8 +416,10 @@ int ip6tables_restore_main(int argc, char *argv[]) if (!strncmp(param_buffer, "-t", 2) || !strncmp(param_buffer, "--table", 8)) { xtables_error(PARAMETER_PROBLEM, - "Line %u seems to have a " - "-t table option.\n", line); + "The -t option (seen in " + "line %u) cannot be used " + "in ip6tables-restore.\n", + line); exit(1); } diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 9f51f993..f21754a4 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -416,8 +416,10 @@ iptables_restore_main(int argc, char *argv[]) if (!strncmp(param_buffer, "-t", 2) || !strncmp(param_buffer, "--table", 8)) { xtables_error(PARAMETER_PROBLEM, - "Line %u seems to have a " - "-t table option.\n", line); + "The -t option (seen in " + "line %u) cannot be used " + "in iptables-restore.\n", + line); exit(1); } -- cgit v1.2.3 From a3c1c206a665d81afa2363507a5e162c20694311 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 13 Jul 2012 22:45:00 +0200 Subject: doc: grammatical updates to libxt_SET Cherry-picked these from recent patches from Mr Dash Four. Signed-off-by: Jan Engelhardt --- extensions/libxt_SET.man | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/libxt_SET.man b/extensions/libxt_SET.man index 63eb3831..c35ba93d 100644 --- a/extensions/libxt_SET.man +++ b/extensions/libxt_SET.man @@ -1,24 +1,24 @@ -This modules adds and/or deletes entries from IP sets which can be defined +This module adds and/or deletes entries from IP sets which can be defined by ipset(8). .TP \fB\-\-add\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...] -add the address(es)/port(s) of the packet to the sets +add the address(es)/port(s) of the packet to the set .TP \fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...] -delete the address(es)/port(s) of the packet from the sets +delete the address(es)/port(s) of the packet from the set .IP -where flags are +where \fIflag\fP(s) are .BR "src" and/or .BR "dst" specifications and there can be no more than six of them. .TP \fB\-\-timeout\fP \fIvalue\fP -when adding entry, the timeout value to use instead of the default +when adding an entry, the timeout value to use instead of the default one from the set definition .TP \fB\-\-exist\fP -when adding entry if it already exists, reset the timeout value +when adding an entry if it already exists, reset the timeout value to the specified one or to the default from the set definition .PP Use of -j SET requires that ipset kernel support is provided, which, for -- cgit v1.2.3 From dc23c2d7afd2103cbc589372769c2f6723ea5235 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 13 Jul 2012 23:18:29 +0200 Subject: libxt_u32: do bounds checking for @'s operands Using only strtoul is prone to accept all values, including negative ones which are not explicitly allowed. Therefore, use xtables_strtoui with bounds checking. Signed-off-by: Jan Engelhardt --- extensions/libxt_u32.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/extensions/libxt_u32.c b/extensions/libxt_u32.c index 6d024fb6..2a7f5d80 100644 --- a/extensions/libxt_u32.c +++ b/extensions/libxt_u32.c @@ -88,17 +88,13 @@ static void u32_dump(const struct xt_u32 *data) /* string_to_number() is not quite what we need here ... */ static uint32_t parse_number(const char **s, int pos) { - uint32_t number; + unsigned int number; char *end; - errno = 0; - number = strtoul(*s, &end, 0); - if (end == *s) + if (!xtables_strtoui(*s, &end, &number, 0, UINT32_MAX) || + end == *s) xtables_error(PARAMETER_PROBLEM, - "u32: at char %d: expected number", pos); - if (errno != 0) - xtables_error(PARAMETER_PROBLEM, - "u32: at char %d: error reading number", pos); + "u32: at char %d: not a number or out of range", pos); *s = end; return number; } -- cgit v1.2.3 From c0b7138f39882e2bf8f3d85d15e0ffbd868ed7ba Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 14 Jul 2012 00:06:45 +0200 Subject: libxt_devgroup: consolidate devgroup specification parsing This is a small cleanup, reducing the two copies of X/Y parsing to one. Signed-off-by: Jan Engelhardt --- extensions/libxt_devgroup.c | 70 +++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/extensions/libxt_devgroup.c b/extensions/libxt_devgroup.c index 4487c833..69ae279d 100644 --- a/extensions/libxt_devgroup.c +++ b/extensions/libxt_devgroup.c @@ -42,58 +42,48 @@ static void devgroup_init(struct xt_entry_match *match) fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno)); } +static void devgroup_parse_groupspec(const char *arg, unsigned int *group, + unsigned int *mask) +{ + char *end; + + *group = strtoul(arg, &end, 0); + if (end != arg && (*end == '/' || *end == '\0')) { + if (*end == '/') + *mask = strtoul(end + 1, &end, 0); + else + *mask = ~0U; + if (*end != '\0' || end == arg) + xtables_error(PARAMETER_PROBLEM, + "Bad group value \"%s\"", arg); + } else { + *group = xtables_lmap_name2id(devgroups, arg); + if (*group == -1) + xtables_error(PARAMETER_PROBLEM, + "Device group \"%s\" not found", arg); + *mask = ~0U; + } +} + static void devgroup_parse(struct xt_option_call *cb) { struct xt_devgroup_info *info = cb->data; - unsigned int id; - char *end; + unsigned int id, mask; xtables_option_parse(cb); switch (cb->entry->id) { case O_SRC_GROUP: - info->src_group = strtoul(cb->arg, &end, 0); - if (end != cb->arg && (*end == '/' || *end == '\0')) { - if (*end == '/') - info->src_mask = strtoul(end+1, &end, 0); - else - info->src_mask = 0xffffffff; - if (*end != '\0' || end == cb->arg) - xtables_error(PARAMETER_PROBLEM, - "Bad src-group value `%s'", - cb->arg); - } else { - id = xtables_lmap_name2id(devgroups, cb->arg); - if (id == -1) - xtables_error(PARAMETER_PROBLEM, - "Device group `%s' not found", - cb->arg); - info->src_group = id; - info->src_mask = 0xffffffff; - } + devgroup_parse_groupspec(cb->arg, &id, &mask); + info->src_group = id; + info->src_mask = mask; info->flags |= XT_DEVGROUP_MATCH_SRC; if (cb->invert) info->flags |= XT_DEVGROUP_INVERT_SRC; break; case O_DST_GROUP: - info->dst_group = strtoul(cb->arg, &end, 0); - if (end != cb->arg && (*end == '/' || *end == '\0')) { - if (*end == '/') - info->dst_mask = strtoul(end+1, &end, 0); - else - info->dst_mask = 0xffffffff; - if (*end != '\0' || end == cb->arg) - xtables_error(PARAMETER_PROBLEM, - "Bad dst-group value `%s'", - cb->arg); - } else { - id = xtables_lmap_name2id(devgroups, cb->arg); - if (id == -1) - xtables_error(PARAMETER_PROBLEM, - "Device group `%s' not found", - cb->arg); - info->dst_group = id; - info->dst_mask = 0xffffffff; - } + devgroup_parse_groupspec(cb->arg, &id, &mask); + info->dst_group = id; + info->dst_mask = mask; info->flags |= XT_DEVGROUP_MATCH_DST; if (cb->invert) info->flags |= XT_DEVGROUP_INVERT_DST; -- cgit v1.2.3 From d18b451ec82bbaeaf385241ebdf926912a075ade Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 14 Jul 2012 00:06:45 +0200 Subject: libxt_devgroup: guard against negative numbers More corrections of the strtoul kind. Signed-off-by: Jan Engelhardt --- extensions/libxt_devgroup.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_devgroup.c b/extensions/libxt_devgroup.c index 69ae279d..4a69c822 100644 --- a/extensions/libxt_devgroup.c +++ b/extensions/libxt_devgroup.c @@ -46,14 +46,16 @@ static void devgroup_parse_groupspec(const char *arg, unsigned int *group, unsigned int *mask) { char *end; + bool ok; - *group = strtoul(arg, &end, 0); - if (end != arg && (*end == '/' || *end == '\0')) { + ok = xtables_strtoui(arg, &end, group, 0, UINT32_MAX); + if (ok && (*end == '/' || *end == '\0')) { if (*end == '/') - *mask = strtoul(end + 1, &end, 0); + ok = xtables_strtoui(end + 1, NULL, mask, + 0, UINT32_MAX); else *mask = ~0U; - if (*end != '\0' || end == arg) + if (!ok) xtables_error(PARAMETER_PROBLEM, "Bad group value \"%s\"", arg); } else { -- cgit v1.2.3 From a19988f2795770ce470562c1795e1cf53e3aa54b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 15 Jul 2012 22:21:00 +0200 Subject: libxt_LED: guard against negative numbers Signed-off-by: Jan Engelhardt --- extensions/libxt_LED.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_LED.c b/extensions/libxt_LED.c index 9d68fa27..e6cf8497 100644 --- a/extensions/libxt_LED.c +++ b/extensions/libxt_LED.c @@ -49,6 +49,7 @@ static void LED_help(void) static void LED_parse(struct xt_option_call *cb) { struct xt_led_info *led = cb->data; + unsigned int delay; xtables_option_parse(cb); switch (cb->entry->id) { @@ -59,8 +60,10 @@ static void LED_parse(struct xt_option_call *cb) case O_LED_DELAY: if (strncasecmp(cb->arg, "inf", 3) == 0) led->delay = -1; - else - led->delay = strtoul(cb->arg, NULL, 0); + else if (!xtables_strtoui(cb->arg, NULL, &delay, 0, UINT32_MAX)) + xtables_error(PARAMETER_PROBLEM, + "Delay value must be within range 0..%u", + UINT32_MAX); break; case O_LED_ALWAYS_BLINK: led->always_blink = 1; -- cgit v1.2.3 From 9d69da4bdb1d546218d168b72f12ac8aa042e3d8 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 28 Jul 2012 19:10:08 +0200 Subject: libxt_*limit: avoid division by zero It was possible to specify -A mychain -m hashlimit --hashlimit 600059/minute; this would convert to r->avg=0, which subsequently causes a division by zero when printing with -S mychain. 1. Avoid division by zero in print_rate by printing infinity instead. 2. Rewrite the test in parse_rate to properly reject too high rates. Signed-off-by: Jan Engelhardt --- extensions/libxt_hashlimit.c | 17 ++++++++++++----- extensions/libxt_limit.c | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index 37a31489..831345b7 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -10,6 +10,7 @@ * * Error corections by nmalykh@bilim.com (22.01.2005) */ +#include #include #include #include @@ -250,12 +251,13 @@ int parse_rate(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud) if (!r) return 0; - /* This would get mapped to infinite (1/day is minimum they - can specify, so we're ok at that end). */ - if (r / ud->mult > XT_HASHLIMIT_SCALE) - xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate); - *val = XT_HASHLIMIT_SCALE * ud->mult / r; + if (*val == 0) + /* + * The rate maps to infinity. (1/day is the minimum they can + * specify, so we are ok at that end). + */ + xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate); return 1; } @@ -434,6 +436,11 @@ static uint32_t print_rate(uint32_t period) { unsigned int i; + if (period == 0) { + printf(" %f", INFINITY); + return 0; + } + for (i = 1; i < ARRAY_SIZE(rates); ++i) if (period > rates[i].mult || rates[i].mult/period < rates[i].mult%period) diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c index b15b02f2..023500cf 100644 --- a/extensions/libxt_limit.c +++ b/extensions/libxt_limit.c @@ -3,6 +3,7 @@ * Jérôme de Vivie * Hervé Eychenne */ +#include #include #include #include @@ -64,12 +65,13 @@ int parse_rate(const char *rate, uint32_t *val) if (!r) return 0; - /* This would get mapped to infinite (1/day is minimum they - can specify, so we're ok at that end). */ - if (r / mult > XT_LIMIT_SCALE) - xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate); - *val = XT_LIMIT_SCALE * mult / r; + if (*val == 0) + /* + * The rate maps to infinity. (1/day is the minimum they can + * specify, so we are ok at that end). + */ + xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate); return 1; } @@ -118,6 +120,11 @@ static void print_rate(uint32_t period) { unsigned int i; + if (period == 0) { + printf(" %f", INFINITY); + return; + } + for (i = 1; i < ARRAY_SIZE(rates); ++i) if (period > rates[i].mult || rates[i].mult/period < rates[i].mult%period) -- cgit v1.2.3 From ad8858c0d3ef875e2c118ebcc69487070fb87f72 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 3 Aug 2012 10:41:40 +0200 Subject: include: add missing linux/netfilter_ipv4/ip_queue.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes compilation of libipq with headers from Linux kernel 3.5: In file included from libipq.c:34:0: ../include/libipq/libipq.h:33:43: fatal error: linux/netfilter_ipv4/ip_queue.h: No such file or directory ip_queue is gone since Linux kernel 3.5. However, you can still use new iptables versions with old Linux kernels. We have to keep libipq in this tree for a while (1.5-2 years should be OK). Reported-by: Arkadiusz MiÅ›kiewicz Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter_ipv4/ip_queue.h | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 include/linux/netfilter_ipv4/ip_queue.h diff --git a/include/linux/netfilter_ipv4/ip_queue.h b/include/linux/netfilter_ipv4/ip_queue.h new file mode 100644 index 00000000..a03507f4 --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_queue.h @@ -0,0 +1,72 @@ +/* + * This is a module which is used for queueing IPv4 packets and + * communicating with userspace via netlink. + * + * (C) 2000 James Morris, this code is GPL. + */ +#ifndef _IP_QUEUE_H +#define _IP_QUEUE_H + +#ifdef __KERNEL__ +#ifdef DEBUG_IPQ +#define QDEBUG(x...) printk(KERN_DEBUG ## x) +#else +#define QDEBUG(x...) +#endif /* DEBUG_IPQ */ +#else +#include +#endif /* ! __KERNEL__ */ + +/* Messages sent from kernel */ +typedef struct ipq_packet_msg { + unsigned long packet_id; /* ID of queued packet */ + unsigned long mark; /* Netfilter mark value */ + long timestamp_sec; /* Packet arrival time (seconds) */ + long timestamp_usec; /* Packet arrvial time (+useconds) */ + unsigned int hook; /* Netfilter hook we rode in on */ + char indev_name[IFNAMSIZ]; /* Name of incoming interface */ + char outdev_name[IFNAMSIZ]; /* Name of outgoing interface */ + __be16 hw_protocol; /* Hardware protocol (network order) */ + unsigned short hw_type; /* Hardware type */ + unsigned char hw_addrlen; /* Hardware address length */ + unsigned char hw_addr[8]; /* Hardware address */ + size_t data_len; /* Length of packet data */ + unsigned char payload[0]; /* Optional packet data */ +} ipq_packet_msg_t; + +/* Messages sent from userspace */ +typedef struct ipq_mode_msg { + unsigned char value; /* Requested mode */ + size_t range; /* Optional range of packet requested */ +} ipq_mode_msg_t; + +typedef struct ipq_verdict_msg { + unsigned int value; /* Verdict to hand to netfilter */ + unsigned long id; /* Packet ID for this verdict */ + size_t data_len; /* Length of replacement data */ + unsigned char payload[0]; /* Optional replacement packet */ +} ipq_verdict_msg_t; + +typedef struct ipq_peer_msg { + union { + ipq_verdict_msg_t verdict; + ipq_mode_msg_t mode; + } msg; +} ipq_peer_msg_t; + +/* Packet delivery modes */ +enum { + IPQ_COPY_NONE, /* Initial mode, packets are dropped */ + IPQ_COPY_META, /* Copy metadata */ + IPQ_COPY_PACKET /* Copy metadata + packet (range) */ +}; +#define IPQ_COPY_MAX IPQ_COPY_PACKET + +/* Types of messages */ +#define IPQM_BASE 0x10 /* standard netlink messages below this */ +#define IPQM_MODE (IPQM_BASE + 1) /* Mode request from peer */ +#define IPQM_VERDICT (IPQM_BASE + 2) /* Verdict from peer */ +#define IPQM_PACKET (IPQM_BASE + 3) /* Packet from kernel */ +#define IPQM_MAX (IPQM_BASE + 4) + +#endif /*_IP_QUEUE_H*/ -- cgit v1.2.3 From 23a98b56935c42ef460020e37a9ff8006eee58e2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 3 Aug 2012 11:12:14 +0200 Subject: ip[6]tables-restore: cleanup to reduce one level of indentation This patch moves the parameter parsing to one function to reduce one level of indentation. Jan Engelhardt likes this. Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.c | 134 +++++++++++++++++++++---------------------- iptables/iptables-restore.c | 134 +++++++++++++++++++++---------------------- 2 files changed, 130 insertions(+), 138 deletions(-) diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 294b242e..0e8252f4 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -114,6 +114,70 @@ static void free_argv(void) { free(newargv[i]); } +static void add_param_to_argv(char *parsestart) +{ + int quote_open = 0, escaped = 0, param_len = 0; + char param_buffer[1024], *curchar; + + /* After fighting with strtok enough, here's now + * a 'real' parser. According to Rusty I'm now no + * longer a real hacker, but I can live with that */ + + for (curchar = parsestart; *curchar; curchar++) { + if (quote_open) { + if (escaped) { + param_buffer[param_len++] = *curchar; + escaped = 0; + continue; + } else if (*curchar == '\\') { + escaped = 1; + continue; + } else if (*curchar == '"') { + quote_open = 0; + *curchar = ' '; + } else { + param_buffer[param_len++] = *curchar; + continue; + } + } else { + if (*curchar == '"') { + quote_open = 1; + continue; + } + } + + if (*curchar == ' ' + || *curchar == '\t' + || * curchar == '\n') { + if (!param_len) { + /* two spaces? */ + continue; + } + + param_buffer[param_len] = '\0'; + + /* check if table name specified */ + if (!strncmp(param_buffer, "-t", 2) + || !strncmp(param_buffer, "--table", 8)) { + xtables_error(PARAMETER_PROBLEM, + "The -t option (seen in line %u) cannot be " + "used in ip6tables-restore.\n", line); + exit(1); + } + + add_argv(param_buffer); + param_len = 0; + } else { + /* regular character, copy to buffer */ + param_buffer[param_len++] = *curchar; + + if (param_len >= sizeof(param_buffer)) + xtables_error(PARAMETER_PROBLEM, + "Parameter too long!"); + } + } +} + int ip6tables_restore_main(int argc, char *argv[]) { struct xtc_handle *handle = NULL; @@ -325,12 +389,6 @@ int ip6tables_restore_main(int argc, char *argv[]) char *bcnt = NULL; char *parsestart; - /* the parser */ - char *curchar; - int quote_open, escaped; - size_t param_len; - char param_buffer[1024]; - /* reset the newargv */ newargc = 0; @@ -371,69 +429,7 @@ int ip6tables_restore_main(int argc, char *argv[]) add_argv((char *) bcnt); } - /* After fighting with strtok enough, here's now - * a 'real' parser. According to Rusty I'm now no - * longer a real hacker, but I can live with that */ - - quote_open = 0; - escaped = 0; - param_len = 0; - - for (curchar = parsestart; *curchar; curchar++) { - if (quote_open) { - if (escaped) { - param_buffer[param_len++] = *curchar; - escaped = 0; - continue; - } else if (*curchar == '\\') { - escaped = 1; - continue; - } else if (*curchar == '"') { - quote_open = 0; - *curchar = ' '; - } else { - param_buffer[param_len++] = *curchar; - continue; - } - } else { - if (*curchar == '"') { - quote_open = 1; - continue; - } - } - - if (*curchar == ' ' - || *curchar == '\t' - || * curchar == '\n') { - if (!param_len) { - /* two spaces? */ - continue; - } - - param_buffer[param_len] = '\0'; - - /* check if table name specified */ - if (!strncmp(param_buffer, "-t", 2) - || !strncmp(param_buffer, "--table", 8)) { - xtables_error(PARAMETER_PROBLEM, - "The -t option (seen in " - "line %u) cannot be used " - "in ip6tables-restore.\n", - line); - exit(1); - } - - add_argv(param_buffer); - param_len = 0; - } else { - /* regular character, copy to buffer */ - param_buffer[param_len++] = *curchar; - - if (param_len >= sizeof(param_buffer)) - xtables_error(PARAMETER_PROBLEM, - "Parameter too long!"); - } - } + add_param_to_argv(parsestart); DEBUGP("calling do_command6(%u, argv, &%s, handle):\n", newargc, curtable); diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index f21754a4..08225139 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -113,6 +113,70 @@ static void free_argv(void) { free(newargv[i]); } +static void add_param_to_argv(char *parsestart) +{ + int quote_open = 0, escaped = 0, param_len = 0; + char param_buffer[1024], *curchar; + + /* After fighting with strtok enough, here's now + * a 'real' parser. According to Rusty I'm now no + * longer a real hacker, but I can live with that */ + + for (curchar = parsestart; *curchar; curchar++) { + if (quote_open) { + if (escaped) { + param_buffer[param_len++] = *curchar; + escaped = 0; + continue; + } else if (*curchar == '\\') { + escaped = 1; + continue; + } else if (*curchar == '"') { + quote_open = 0; + *curchar = ' '; + } else { + param_buffer[param_len++] = *curchar; + continue; + } + } else { + if (*curchar == '"') { + quote_open = 1; + continue; + } + } + + if (*curchar == ' ' + || *curchar == '\t' + || * curchar == '\n') { + if (!param_len) { + /* two spaces? */ + continue; + } + + param_buffer[param_len] = '\0'; + + /* check if table name specified */ + if (!strncmp(param_buffer, "-t", 2) + || !strncmp(param_buffer, "--table", 8)) { + xtables_error(PARAMETER_PROBLEM, + "The -t option (seen in line %u) cannot be " + "used in iptables-restore.\n", line); + exit(1); + } + + add_argv(param_buffer); + param_len = 0; + } else { + /* regular character, copy to buffer */ + param_buffer[param_len++] = *curchar; + + if (param_len >= sizeof(param_buffer)) + xtables_error(PARAMETER_PROBLEM, + "Parameter too long!"); + } + } +} + int iptables_restore_main(int argc, char *argv[]) { @@ -325,12 +389,6 @@ iptables_restore_main(int argc, char *argv[]) char *bcnt = NULL; char *parsestart; - /* the parser */ - char *curchar; - int quote_open, escaped; - size_t param_len; - char param_buffer[1024]; - /* reset the newargv */ newargc = 0; @@ -371,69 +429,7 @@ iptables_restore_main(int argc, char *argv[]) add_argv((char *) bcnt); } - /* After fighting with strtok enough, here's now - * a 'real' parser. According to Rusty I'm now no - * longer a real hacker, but I can live with that */ - - quote_open = 0; - escaped = 0; - param_len = 0; - - for (curchar = parsestart; *curchar; curchar++) { - if (quote_open) { - if (escaped) { - param_buffer[param_len++] = *curchar; - escaped = 0; - continue; - } else if (*curchar == '\\') { - escaped = 1; - continue; - } else if (*curchar == '"') { - quote_open = 0; - *curchar = ' '; - } else { - param_buffer[param_len++] = *curchar; - continue; - } - } else { - if (*curchar == '"') { - quote_open = 1; - continue; - } - } - - if (*curchar == ' ' - || *curchar == '\t' - || * curchar == '\n') { - if (!param_len) { - /* two spaces? */ - continue; - } - - param_buffer[param_len] = '\0'; - - /* check if table name specified */ - if (!strncmp(param_buffer, "-t", 2) - || !strncmp(param_buffer, "--table", 8)) { - xtables_error(PARAMETER_PROBLEM, - "The -t option (seen in " - "line %u) cannot be used " - "in iptables-restore.\n", - line); - exit(1); - } - - add_argv(param_buffer); - param_len = 0; - } else { - /* regular character, copy to buffer */ - param_buffer[param_len++] = *curchar; - - if (param_len >= sizeof(param_buffer)) - xtables_error(PARAMETER_PROBLEM, - "Parameter too long!"); - } - } + add_param_to_argv(parsestart); DEBUGP("calling do_command4(%u, argv, &%s, handle):\n", newargc, curtable); -- cgit v1.2.3 From a624e0a1b2d075253b599ababd4ea1351ef42b2a Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 3 Aug 2012 10:41:40 +0200 Subject: include: add missing linux/netfilter_ipv4/ip_queue.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes compilation of libipq with headers from Linux kernel 3.5: In file included from libipq.c:34:0: ../include/libipq/libipq.h:33:43: fatal error: linux/netfilter_ipv4/ip_queue.h: No such file or directory ip_queue is gone since Linux kernel 3.5. However, you can still use new iptables versions with old Linux kernels. We have to keep libipq in this tree for a while (1.5-2 years should be OK). Reported-by: Arkadiusz MiÅ›kiewicz Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter_ipv4/ip_queue.h | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 include/linux/netfilter_ipv4/ip_queue.h diff --git a/include/linux/netfilter_ipv4/ip_queue.h b/include/linux/netfilter_ipv4/ip_queue.h new file mode 100644 index 00000000..a03507f4 --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_queue.h @@ -0,0 +1,72 @@ +/* + * This is a module which is used for queueing IPv4 packets and + * communicating with userspace via netlink. + * + * (C) 2000 James Morris, this code is GPL. + */ +#ifndef _IP_QUEUE_H +#define _IP_QUEUE_H + +#ifdef __KERNEL__ +#ifdef DEBUG_IPQ +#define QDEBUG(x...) printk(KERN_DEBUG ## x) +#else +#define QDEBUG(x...) +#endif /* DEBUG_IPQ */ +#else +#include +#endif /* ! __KERNEL__ */ + +/* Messages sent from kernel */ +typedef struct ipq_packet_msg { + unsigned long packet_id; /* ID of queued packet */ + unsigned long mark; /* Netfilter mark value */ + long timestamp_sec; /* Packet arrival time (seconds) */ + long timestamp_usec; /* Packet arrvial time (+useconds) */ + unsigned int hook; /* Netfilter hook we rode in on */ + char indev_name[IFNAMSIZ]; /* Name of incoming interface */ + char outdev_name[IFNAMSIZ]; /* Name of outgoing interface */ + __be16 hw_protocol; /* Hardware protocol (network order) */ + unsigned short hw_type; /* Hardware type */ + unsigned char hw_addrlen; /* Hardware address length */ + unsigned char hw_addr[8]; /* Hardware address */ + size_t data_len; /* Length of packet data */ + unsigned char payload[0]; /* Optional packet data */ +} ipq_packet_msg_t; + +/* Messages sent from userspace */ +typedef struct ipq_mode_msg { + unsigned char value; /* Requested mode */ + size_t range; /* Optional range of packet requested */ +} ipq_mode_msg_t; + +typedef struct ipq_verdict_msg { + unsigned int value; /* Verdict to hand to netfilter */ + unsigned long id; /* Packet ID for this verdict */ + size_t data_len; /* Length of replacement data */ + unsigned char payload[0]; /* Optional replacement packet */ +} ipq_verdict_msg_t; + +typedef struct ipq_peer_msg { + union { + ipq_verdict_msg_t verdict; + ipq_mode_msg_t mode; + } msg; +} ipq_peer_msg_t; + +/* Packet delivery modes */ +enum { + IPQ_COPY_NONE, /* Initial mode, packets are dropped */ + IPQ_COPY_META, /* Copy metadata */ + IPQ_COPY_PACKET /* Copy metadata + packet (range) */ +}; +#define IPQ_COPY_MAX IPQ_COPY_PACKET + +/* Types of messages */ +#define IPQM_BASE 0x10 /* standard netlink messages below this */ +#define IPQM_MODE (IPQM_BASE + 1) /* Mode request from peer */ +#define IPQM_VERDICT (IPQM_BASE + 2) /* Verdict from peer */ +#define IPQM_PACKET (IPQM_BASE + 3) /* Packet from kernel */ +#define IPQM_MAX (IPQM_BASE + 4) + +#endif /*_IP_QUEUE_H*/ -- cgit v1.2.3 From 8a988f6707719340114bfa3d85ea3e1c80fe6f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= Date: Tue, 7 Aug 2012 15:10:05 +0200 Subject: libip6t_frag: match any frag id by default If no --fragid option is given, the frag extension only matches fragments with a zero-valued "Identification" field. This behavior deviates from what other extensions do (they match all values in this case) and is unexpected, and therefore changed by this patch. Additionally, --fragid 0:4294967295 leads to no output on `iptables -S` because part of the code thinks that this would be the default, when it is not. So, default to match all frag values, such that iptables -S not outputting anything also becomes correct. Signed-off-by: Michal Kubecek Signed-off-by: Jan Engelhardt --- extensions/libip6t_frag.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c index d8bcaeee..023df627 100644 --- a/extensions/libip6t_frag.c +++ b/extensions/libip6t_frag.c @@ -41,6 +41,13 @@ static const struct xt_option_entry frag_opts[] = { }; #undef s +static void frag_init(struct xt_entry_match *m) +{ + struct ip6t_frag *fraginfo = (void *)m->data; + + fraginfo->ids[1] = ~0U; +} + static void frag_parse(struct xt_option_call *cb) { struct ip6t_frag *fraginfo = cb->data; @@ -173,6 +180,7 @@ static struct xtables_match frag_mt6_reg = { .size = XT_ALIGN(sizeof(struct ip6t_frag)), .userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)), .help = frag_help, + .init = frag_init, .print = frag_print, .save = frag_save, .x6_parse = frag_parse, -- cgit v1.2.3 From 3abf5cc5ac0c32eba2436567d25e175d7e0f42bc Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 20 Aug 2012 06:52:36 +0000 Subject: libxt_tcp: print space before, not after "flags:" tcp dpt:10flags: 0x17/0x02 ^^ Signed-off-by: Andreas Schwab Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_tcp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c index e849fa21..bbdec454 100644 --- a/extensions/libxt_tcp.c +++ b/extensions/libxt_tcp.c @@ -278,11 +278,10 @@ static void print_flags(uint8_t mask, uint8_t cmp, int invert, int numeric) { if (mask || invert) { - printf("flags:%s", invert ? "!" : ""); + printf(" flags:%s", invert ? "!" : ""); if (numeric) - printf(" 0x%02X/0x%02X", mask, cmp); + printf("0x%02X/0x%02X", mask, cmp); else { - printf(" "); print_tcpf(mask); printf("/"); print_tcpf(cmp); -- cgit v1.2.3 From 053a4fdf6536ca63ad640d0b75f54c3f4964ca2b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 31 Aug 2012 04:06:38 +0200 Subject: build: support for automake-1.12 automake-1.12 wants that AM_PROG_AR be used when LT_INIT is. Signed-off-by: Jan Engelhardt --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 179c2d82..861f5b3e 100644 --- a/configure.ac +++ b/configure.ac @@ -13,6 +13,7 @@ AM_INIT_AUTOMAKE([-Wall]) AC_PROG_CC AM_PROG_CC_C_O AC_DISABLE_STATIC +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AM_PROG_LIBTOOL AC_ARG_WITH([kernel], -- cgit v1.2.3 From df60a301bf24c3b3e37188d9da155b97fd6dc076 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 31 Aug 2012 03:59:07 +0200 Subject: build: separate AC variable replacements from xtables.h It was/is a bit annoying that modifying xtables.h.in causes configure to rerun. Split the @foo@ things into a separate file to bypass this. Signed-off-by: Jan Engelhardt --- .gitignore | 2 +- Makefile.am | 2 +- configure.ac | 2 +- include/Makefile.am | 2 +- include/xtables-version.h.in | 2 + include/xtables.h | 526 ++++++++++++++++++++++++++++++++++++++++++ include/xtables.h.in | 527 ------------------------------------------- 7 files changed, 532 insertions(+), 531 deletions(-) create mode 100644 include/xtables-version.h.in create mode 100644 include/xtables.h delete mode 100644 include/xtables.h.in diff --git a/.gitignore b/.gitignore index b7c3dfb8..fa86c482 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ Makefile Makefile.in -/include/xtables.h +/include/xtables-version.h /include/iptables/internal.h /aclocal.m4 diff --git a/Makefile.am b/Makefile.am index 4eb63ebe..6400ba41 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,4 +27,4 @@ tarball: rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION}; config.status: extensions/GNUmakefile.in \ - include/xtables.h.in include/iptables/internal.h.in + include/xtables-version.h.in include/iptables/internal.h.in diff --git a/configure.ac b/configure.ac index 861f5b3e..4060f901 100644 --- a/configure.ac +++ b/configure.ac @@ -127,5 +127,5 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile libiptc/Makefile libiptc/libiptc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc libxtables/Makefile utils/Makefile - include/xtables.h include/iptables/internal.h]) + include/xtables-version.h include/iptables/internal.h]) AC_OUTPUT diff --git a/include/Makefile.am b/include/Makefile.am index 6f7da598..e6951209 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,7 +1,7 @@ # -*- Makefile -*- include_HEADERS = -nobase_include_HEADERS = xtables.h +nobase_include_HEADERS = xtables.h xtables-version.h if ENABLE_LIBIPQ include_HEADERS += libipq/libipq.h diff --git a/include/xtables-version.h.in b/include/xtables-version.h.in new file mode 100644 index 00000000..cb13827c --- /dev/null +++ b/include/xtables-version.h.in @@ -0,0 +1,2 @@ +#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@" +#define XTABLES_VERSION_CODE @libxtables_vmajor@ diff --git a/include/xtables.h b/include/xtables.h new file mode 100644 index 00000000..3b15e67e --- /dev/null +++ b/include/xtables.h @@ -0,0 +1,526 @@ +#ifndef _XTABLES_H +#define _XTABLES_H + +/* + * Changing any structs/functions may incur a needed change + * in libxtables_vcurrent/vage too. + */ + +#include /* PF_* */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif +#ifndef IPPROTO_DCCP +#define IPPROTO_DCCP 33 +#endif +#ifndef IPPROTO_MH +# define IPPROTO_MH 135 +#endif +#ifndef IPPROTO_UDPLITE +#define IPPROTO_UDPLITE 136 +#endif + +#include + +struct in_addr; + +/* + * .size is here so that there is a somewhat reasonable check + * against the chosen .type. + */ +#define XTOPT_POINTER(stype, member) \ + .ptroff = offsetof(stype, member), \ + .size = sizeof(((stype *)NULL)->member) +#define XTOPT_TABLEEND {.name = NULL} + +/** + * Select the format the input has to conform to, as well as the target type + * (area pointed to with XTOPT_POINTER). Note that the storing is not always + * uniform. @cb->val will be populated with as much as there is space, i.e. + * exactly 2 items for ranges, but the target area can receive more values + * (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK). + * + * %XTTYPE_NONE: option takes no argument + * %XTTYPE_UINT*: standard integer + * %XTTYPE_UINT*RC: colon-separated range of standard integers + * %XTTYPE_DOUBLE: double-precision floating point number + * %XTTYPE_STRING: arbitrary string + * %XTTYPE_TOSMASK: 8-bit TOS value with optional mask + * %XTTYPE_MARKMASK32: 32-bit mark with optional mask + * %XTTYPE_SYSLOGLEVEL: syslog level by name or number + * %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr) + * %XTTYPE_HOSTMASK: one host or address, with an optional prefix length + * (ptr: union nf_inet_addr; only host portion is stored) + * %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t) + * %XTTYPE_PORT: 16-bit port name or number (supports %XTOPT_NBO) + * %XTTYPE_PORTRC: colon-separated port range (names acceptable), + * (supports %XTOPT_NBO) + * %XTTYPE_PLEN: prefix length + * %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr) + * %XTTYPE_ETHERMAC: Ethernet MAC address in hex form + */ +enum xt_option_type { + XTTYPE_NONE, + XTTYPE_UINT8, + XTTYPE_UINT16, + XTTYPE_UINT32, + XTTYPE_UINT64, + XTTYPE_UINT8RC, + XTTYPE_UINT16RC, + XTTYPE_UINT32RC, + XTTYPE_UINT64RC, + XTTYPE_DOUBLE, + XTTYPE_STRING, + XTTYPE_TOSMASK, + XTTYPE_MARKMASK32, + XTTYPE_SYSLOGLEVEL, + XTTYPE_HOST, + XTTYPE_HOSTMASK, + XTTYPE_PROTOCOL, + XTTYPE_PORT, + XTTYPE_PORTRC, + XTTYPE_PLEN, + XTTYPE_PLENMASK, + XTTYPE_ETHERMAC, +}; + +/** + * %XTOPT_INVERT: option is invertible (usable with !) + * %XTOPT_MAND: option is mandatory + * %XTOPT_MULTI: option may be specified multiple times + * %XTOPT_PUT: store value into memory at @ptroff + * %XTOPT_NBO: store value in network-byte order + * (only certain XTTYPEs recognize this) + */ +enum xt_option_flags { + XTOPT_INVERT = 1 << 0, + XTOPT_MAND = 1 << 1, + XTOPT_MULTI = 1 << 2, + XTOPT_PUT = 1 << 3, + XTOPT_NBO = 1 << 4, +}; + +/** + * @name: name of option + * @type: type of input and validation method, see %XTTYPE_* + * @id: unique number (within extension) for option, 0-31 + * @excl: bitmask of flags that cannot be used with this option + * @also: bitmask of flags that must be used with this option + * @flags: bitmask of option flags, see %XTOPT_* + * @ptroff: offset into private structure for member + * @size: size of the item pointed to by @ptroff; this is a safeguard + * @min: lowest allowed value (for singular integral types) + * @max: highest allowed value (for singular integral types) + */ +struct xt_option_entry { + const char *name; + enum xt_option_type type; + unsigned int id, excl, also, flags; + unsigned int ptroff; + size_t size; + unsigned int min, max; +}; + +/** + * @arg: input from command line + * @ext_name: name of extension currently being processed + * @entry: current option being processed + * @data: per-extension kernel data block + * @xflags: options of the extension that have been used + * @invert: whether option was used with ! + * @nvals: number of results in uXX_multi + * @val: parsed result + * @udata: per-extension private scratch area + * (cf. xtables_{match,target}->udata_size) + */ +struct xt_option_call { + const char *arg, *ext_name; + const struct xt_option_entry *entry; + void *data; + unsigned int xflags; + bool invert; + uint8_t nvals; + union { + uint8_t u8, u8_range[2], syslog_level, protocol; + uint16_t u16, u16_range[2], port, port_range[2]; + uint32_t u32, u32_range[2]; + uint64_t u64, u64_range[2]; + double dbl; + struct { + union nf_inet_addr haddr, hmask; + uint8_t hlen; + }; + struct { + uint8_t tos_value, tos_mask; + }; + struct { + uint32_t mark, mask; + }; + uint8_t ethermac[6]; + } val; + /* Wished for a world where the ones below were gone: */ + union { + struct xt_entry_match **match; + struct xt_entry_target **target; + }; + void *xt_entry; + void *udata; +}; + +/** + * @ext_name: name of extension currently being processed + * @data: per-extension (kernel) data block + * @udata: per-extension private scratch area + * (cf. xtables_{match,target}->udata_size) + * @xflags: options of the extension that have been used + */ +struct xt_fcheck_call { + const char *ext_name; + void *data, *udata; + unsigned int xflags; +}; + +/** + * A "linear"/linked-list based name<->id map, for files similar to + * /etc/iproute2/. + */ +struct xtables_lmap { + char *name; + int id; + struct xtables_lmap *next; +}; + +/* Include file for additions: new matches and targets. */ +struct xtables_match +{ + /* + * ABI/API version this module requires. Must be first member, + * as the rest of this struct may be subject to ABI changes. + */ + const char *version; + + struct xtables_match *next; + + const char *name; + + /* Revision of match (0 by default). */ + u_int8_t revision; + + u_int16_t family; + + /* Size of match data. */ + size_t size; + + /* Size of match data relevent for userspace comparison purposes */ + size_t userspacesize; + + /* Function which prints out usage message. */ + void (*help)(void); + + /* Initialize the match. */ + void (*init)(struct xt_entry_match *m); + + /* Function which parses command options; returns true if it + ate an option */ + /* entry is struct ipt_entry for example */ + int (*parse)(int c, char **argv, int invert, unsigned int *flags, + const void *entry, + struct xt_entry_match **match); + + /* Final check; exit if not ok. */ + void (*final_check)(unsigned int flags); + + /* Prints out the match iff non-NULL: put space at end */ + /* ip is struct ipt_ip * for example */ + void (*print)(const void *ip, + const struct xt_entry_match *match, int numeric); + + /* Saves the match info in parsable form to stdout. */ + /* ip is struct ipt_ip * for example */ + void (*save)(const void *ip, const struct xt_entry_match *match); + + /* Pointer to list of extra command-line options */ + const struct option *extra_opts; + + /* New parser */ + void (*x6_parse)(struct xt_option_call *); + void (*x6_fcheck)(struct xt_fcheck_call *); + const struct xt_option_entry *x6_options; + + /* Size of per-extension instance extra "global" scratch space */ + size_t udata_size; + + /* Ignore these men behind the curtain: */ + void *udata; + unsigned int option_offset; + struct xt_entry_match *m; + unsigned int mflags; + unsigned int loaded; /* simulate loading so options are merged properly */ +}; + +struct xtables_target +{ + /* + * ABI/API version this module requires. Must be first member, + * as the rest of this struct may be subject to ABI changes. + */ + const char *version; + + struct xtables_target *next; + + + const char *name; + + /* Revision of target (0 by default). */ + u_int8_t revision; + + u_int16_t family; + + + /* Size of target data. */ + size_t size; + + /* Size of target data relevent for userspace comparison purposes */ + size_t userspacesize; + + /* Function which prints out usage message. */ + void (*help)(void); + + /* Initialize the target. */ + void (*init)(struct xt_entry_target *t); + + /* Function which parses command options; returns true if it + ate an option */ + /* entry is struct ipt_entry for example */ + int (*parse)(int c, char **argv, int invert, unsigned int *flags, + const void *entry, + struct xt_entry_target **targetinfo); + + /* Final check; exit if not ok. */ + void (*final_check)(unsigned int flags); + + /* Prints out the target iff non-NULL: put space at end */ + void (*print)(const void *ip, + const struct xt_entry_target *target, int numeric); + + /* Saves the targinfo in parsable form to stdout. */ + void (*save)(const void *ip, + const struct xt_entry_target *target); + + /* Pointer to list of extra command-line options */ + const struct option *extra_opts; + + /* New parser */ + void (*x6_parse)(struct xt_option_call *); + void (*x6_fcheck)(struct xt_fcheck_call *); + const struct xt_option_entry *x6_options; + + size_t udata_size; + + /* Ignore these men behind the curtain: */ + void *udata; + unsigned int option_offset; + struct xt_entry_target *t; + unsigned int tflags; + unsigned int used; + unsigned int loaded; /* simulate loading so options are merged properly */ +}; + +struct xtables_rule_match { + struct xtables_rule_match *next; + struct xtables_match *match; + /* Multiple matches of the same type: the ones before + the current one are completed from parsing point of view */ + bool completed; +}; + +/** + * struct xtables_pprot - + * + * A few hardcoded protocols for 'all' and in case the user has no + * /etc/protocols. + */ +struct xtables_pprot { + const char *name; + u_int8_t num; +}; + +enum xtables_tryload { + XTF_DONT_LOAD, + XTF_DURING_LOAD, + XTF_TRY_LOAD, + XTF_LOAD_MUST_SUCCEED, +}; + +enum xtables_exittype { + OTHER_PROBLEM = 1, + PARAMETER_PROBLEM, + VERSION_PROBLEM, + RESOURCE_PROBLEM, + XTF_ONLY_ONCE, + XTF_NO_INVERT, + XTF_BAD_VALUE, + XTF_ONE_ACTION, +}; + +struct xtables_globals +{ + unsigned int option_offset; + const char *program_name, *program_version; + struct option *orig_opts; + struct option *opts; + void (*exit_err)(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); +}; + +#define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false} + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char *xtables_modprobe_program; +extern struct xtables_match *xtables_matches; +extern struct xtables_target *xtables_targets; + +extern void xtables_init(void); +extern void xtables_set_nfproto(uint8_t); +extern void *xtables_calloc(size_t, size_t); +extern void *xtables_malloc(size_t); +extern void *xtables_realloc(void *, size_t); + +extern int xtables_insmod(const char *, const char *, bool); +extern int xtables_load_ko(const char *, bool); +extern int xtables_set_params(struct xtables_globals *xtp); +extern void xtables_free_opts(int reset_offset); +extern struct option *xtables_merge_options(struct option *origopts, + struct option *oldopts, const struct option *newopts, + unsigned int *option_offset); + +extern int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto); +extern struct xtables_match *xtables_find_match(const char *name, + enum xtables_tryload, struct xtables_rule_match **match); +extern struct xtables_target *xtables_find_target(const char *name, + enum xtables_tryload); + +/* Your shared library should call one of these. */ +extern void xtables_register_match(struct xtables_match *me); +extern void xtables_register_matches(struct xtables_match *, unsigned int); +extern void xtables_register_target(struct xtables_target *me); +extern void xtables_register_targets(struct xtables_target *, unsigned int); + +extern bool xtables_strtoul(const char *, char **, uintmax_t *, + uintmax_t, uintmax_t); +extern bool xtables_strtoui(const char *, char **, unsigned int *, + unsigned int, unsigned int); +extern int xtables_service_to_port(const char *name, const char *proto); +extern u_int16_t xtables_parse_port(const char *port, const char *proto); +extern void +xtables_parse_interface(const char *arg, char *vianame, unsigned char *mask); + +/* this is a special 64bit data type that is 8-byte aligned */ +#define aligned_u64 u_int64_t __attribute__((aligned(8))) + +extern struct xtables_globals *xt_params; +#define xtables_error (xt_params->exit_err) + +extern void xtables_param_act(unsigned int, const char *, ...); + +extern const char *xtables_ipaddr_to_numeric(const struct in_addr *); +extern const char *xtables_ipaddr_to_anyname(const struct in_addr *); +extern const char *xtables_ipmask_to_numeric(const struct in_addr *); +extern struct in_addr *xtables_numeric_to_ipaddr(const char *); +extern struct in_addr *xtables_numeric_to_ipmask(const char *); +extern int xtables_ipmask_to_cidr(const struct in_addr *); +extern void xtables_ipparse_any(const char *, struct in_addr **, + struct in_addr *, unsigned int *); +extern void xtables_ipparse_multiple(const char *, struct in_addr **, + struct in_addr **, unsigned int *); + +extern struct in6_addr *xtables_numeric_to_ip6addr(const char *); +extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *); +extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *); +extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *); +extern int xtables_ip6mask_to_cidr(const struct in6_addr *); +extern void xtables_ip6parse_any(const char *, struct in6_addr **, + struct in6_addr *, unsigned int *); +extern void xtables_ip6parse_multiple(const char *, struct in6_addr **, + struct in6_addr **, unsigned int *); + +/** + * Print the specified value to standard output, quoting dangerous + * characters if required. + */ +extern void xtables_save_string(const char *value); + +#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) +# ifdef _INIT +# undef _init +# define _init _INIT +# endif + extern void init_extensions(void); + extern void init_extensions4(void); + extern void init_extensions6(void); +#else +# define _init __attribute__((constructor)) _INIT +#endif + +extern const struct xtables_pprot xtables_chain_protos[]; +extern u_int16_t xtables_parse_protocol(const char *s); + +/* kernel revision handling */ +extern int kernel_version; +extern void get_kernel_version(void); +#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) +#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF) +#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF) +#define LINUX_VERSION_PATCH(x) ( (x) & 0xFF) + +/* xtoptions.c */ +extern void xtables_option_metavalidate(const char *, + const struct xt_option_entry *); +extern struct option *xtables_options_xfrm(struct option *, struct option *, + const struct xt_option_entry *, + unsigned int *); +extern void xtables_option_parse(struct xt_option_call *); +extern void xtables_option_tpcall(unsigned int, char **, bool, + struct xtables_target *, void *); +extern void xtables_option_mpcall(unsigned int, char **, bool, + struct xtables_match *, void *); +extern void xtables_option_tfcall(struct xtables_target *); +extern void xtables_option_mfcall(struct xtables_match *); +extern void xtables_options_fcheck(const char *, unsigned int, + const struct xt_option_entry *); + +extern struct xtables_lmap *xtables_lmap_init(const char *); +extern void xtables_lmap_free(struct xtables_lmap *); +extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *); +extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int); + +#ifdef XTABLES_INTERNAL + +/* Shipped modules rely on this... */ + +# ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) +# endif + +extern void _init(void); + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _XTABLES_H */ diff --git a/include/xtables.h.in b/include/xtables.h.in deleted file mode 100644 index db69c03b..00000000 --- a/include/xtables.h.in +++ /dev/null @@ -1,527 +0,0 @@ -#ifndef _XTABLES_H -#define _XTABLES_H - -/* - * Changing any structs/functions may incur a needed change - * in libxtables_vcurrent/vage too. - */ - -#include /* PF_* */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef IPPROTO_SCTP -#define IPPROTO_SCTP 132 -#endif -#ifndef IPPROTO_DCCP -#define IPPROTO_DCCP 33 -#endif -#ifndef IPPROTO_MH -# define IPPROTO_MH 135 -#endif -#ifndef IPPROTO_UDPLITE -#define IPPROTO_UDPLITE 136 -#endif - -#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@" -#define XTABLES_VERSION_CODE @libxtables_vmajor@ - -struct in_addr; - -/* - * .size is here so that there is a somewhat reasonable check - * against the chosen .type. - */ -#define XTOPT_POINTER(stype, member) \ - .ptroff = offsetof(stype, member), \ - .size = sizeof(((stype *)NULL)->member) -#define XTOPT_TABLEEND {.name = NULL} - -/** - * Select the format the input has to conform to, as well as the target type - * (area pointed to with XTOPT_POINTER). Note that the storing is not always - * uniform. @cb->val will be populated with as much as there is space, i.e. - * exactly 2 items for ranges, but the target area can receive more values - * (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK). - * - * %XTTYPE_NONE: option takes no argument - * %XTTYPE_UINT*: standard integer - * %XTTYPE_UINT*RC: colon-separated range of standard integers - * %XTTYPE_DOUBLE: double-precision floating point number - * %XTTYPE_STRING: arbitrary string - * %XTTYPE_TOSMASK: 8-bit TOS value with optional mask - * %XTTYPE_MARKMASK32: 32-bit mark with optional mask - * %XTTYPE_SYSLOGLEVEL: syslog level by name or number - * %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr) - * %XTTYPE_HOSTMASK: one host or address, with an optional prefix length - * (ptr: union nf_inet_addr; only host portion is stored) - * %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t) - * %XTTYPE_PORT: 16-bit port name or number (supports %XTOPT_NBO) - * %XTTYPE_PORTRC: colon-separated port range (names acceptable), - * (supports %XTOPT_NBO) - * %XTTYPE_PLEN: prefix length - * %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr) - * %XTTYPE_ETHERMAC: Ethernet MAC address in hex form - */ -enum xt_option_type { - XTTYPE_NONE, - XTTYPE_UINT8, - XTTYPE_UINT16, - XTTYPE_UINT32, - XTTYPE_UINT64, - XTTYPE_UINT8RC, - XTTYPE_UINT16RC, - XTTYPE_UINT32RC, - XTTYPE_UINT64RC, - XTTYPE_DOUBLE, - XTTYPE_STRING, - XTTYPE_TOSMASK, - XTTYPE_MARKMASK32, - XTTYPE_SYSLOGLEVEL, - XTTYPE_HOST, - XTTYPE_HOSTMASK, - XTTYPE_PROTOCOL, - XTTYPE_PORT, - XTTYPE_PORTRC, - XTTYPE_PLEN, - XTTYPE_PLENMASK, - XTTYPE_ETHERMAC, -}; - -/** - * %XTOPT_INVERT: option is invertible (usable with !) - * %XTOPT_MAND: option is mandatory - * %XTOPT_MULTI: option may be specified multiple times - * %XTOPT_PUT: store value into memory at @ptroff - * %XTOPT_NBO: store value in network-byte order - * (only certain XTTYPEs recognize this) - */ -enum xt_option_flags { - XTOPT_INVERT = 1 << 0, - XTOPT_MAND = 1 << 1, - XTOPT_MULTI = 1 << 2, - XTOPT_PUT = 1 << 3, - XTOPT_NBO = 1 << 4, -}; - -/** - * @name: name of option - * @type: type of input and validation method, see %XTTYPE_* - * @id: unique number (within extension) for option, 0-31 - * @excl: bitmask of flags that cannot be used with this option - * @also: bitmask of flags that must be used with this option - * @flags: bitmask of option flags, see %XTOPT_* - * @ptroff: offset into private structure for member - * @size: size of the item pointed to by @ptroff; this is a safeguard - * @min: lowest allowed value (for singular integral types) - * @max: highest allowed value (for singular integral types) - */ -struct xt_option_entry { - const char *name; - enum xt_option_type type; - unsigned int id, excl, also, flags; - unsigned int ptroff; - size_t size; - unsigned int min, max; -}; - -/** - * @arg: input from command line - * @ext_name: name of extension currently being processed - * @entry: current option being processed - * @data: per-extension kernel data block - * @xflags: options of the extension that have been used - * @invert: whether option was used with ! - * @nvals: number of results in uXX_multi - * @val: parsed result - * @udata: per-extension private scratch area - * (cf. xtables_{match,target}->udata_size) - */ -struct xt_option_call { - const char *arg, *ext_name; - const struct xt_option_entry *entry; - void *data; - unsigned int xflags; - bool invert; - uint8_t nvals; - union { - uint8_t u8, u8_range[2], syslog_level, protocol; - uint16_t u16, u16_range[2], port, port_range[2]; - uint32_t u32, u32_range[2]; - uint64_t u64, u64_range[2]; - double dbl; - struct { - union nf_inet_addr haddr, hmask; - uint8_t hlen; - }; - struct { - uint8_t tos_value, tos_mask; - }; - struct { - uint32_t mark, mask; - }; - uint8_t ethermac[6]; - } val; - /* Wished for a world where the ones below were gone: */ - union { - struct xt_entry_match **match; - struct xt_entry_target **target; - }; - void *xt_entry; - void *udata; -}; - -/** - * @ext_name: name of extension currently being processed - * @data: per-extension (kernel) data block - * @udata: per-extension private scratch area - * (cf. xtables_{match,target}->udata_size) - * @xflags: options of the extension that have been used - */ -struct xt_fcheck_call { - const char *ext_name; - void *data, *udata; - unsigned int xflags; -}; - -/** - * A "linear"/linked-list based name<->id map, for files similar to - * /etc/iproute2/. - */ -struct xtables_lmap { - char *name; - int id; - struct xtables_lmap *next; -}; - -/* Include file for additions: new matches and targets. */ -struct xtables_match -{ - /* - * ABI/API version this module requires. Must be first member, - * as the rest of this struct may be subject to ABI changes. - */ - const char *version; - - struct xtables_match *next; - - const char *name; - - /* Revision of match (0 by default). */ - u_int8_t revision; - - u_int16_t family; - - /* Size of match data. */ - size_t size; - - /* Size of match data relevent for userspace comparison purposes */ - size_t userspacesize; - - /* Function which prints out usage message. */ - void (*help)(void); - - /* Initialize the match. */ - void (*init)(struct xt_entry_match *m); - - /* Function which parses command options; returns true if it - ate an option */ - /* entry is struct ipt_entry for example */ - int (*parse)(int c, char **argv, int invert, unsigned int *flags, - const void *entry, - struct xt_entry_match **match); - - /* Final check; exit if not ok. */ - void (*final_check)(unsigned int flags); - - /* Prints out the match iff non-NULL: put space at end */ - /* ip is struct ipt_ip * for example */ - void (*print)(const void *ip, - const struct xt_entry_match *match, int numeric); - - /* Saves the match info in parsable form to stdout. */ - /* ip is struct ipt_ip * for example */ - void (*save)(const void *ip, const struct xt_entry_match *match); - - /* Pointer to list of extra command-line options */ - const struct option *extra_opts; - - /* New parser */ - void (*x6_parse)(struct xt_option_call *); - void (*x6_fcheck)(struct xt_fcheck_call *); - const struct xt_option_entry *x6_options; - - /* Size of per-extension instance extra "global" scratch space */ - size_t udata_size; - - /* Ignore these men behind the curtain: */ - void *udata; - unsigned int option_offset; - struct xt_entry_match *m; - unsigned int mflags; - unsigned int loaded; /* simulate loading so options are merged properly */ -}; - -struct xtables_target -{ - /* - * ABI/API version this module requires. Must be first member, - * as the rest of this struct may be subject to ABI changes. - */ - const char *version; - - struct xtables_target *next; - - - const char *name; - - /* Revision of target (0 by default). */ - u_int8_t revision; - - u_int16_t family; - - - /* Size of target data. */ - size_t size; - - /* Size of target data relevent for userspace comparison purposes */ - size_t userspacesize; - - /* Function which prints out usage message. */ - void (*help)(void); - - /* Initialize the target. */ - void (*init)(struct xt_entry_target *t); - - /* Function which parses command options; returns true if it - ate an option */ - /* entry is struct ipt_entry for example */ - int (*parse)(int c, char **argv, int invert, unsigned int *flags, - const void *entry, - struct xt_entry_target **targetinfo); - - /* Final check; exit if not ok. */ - void (*final_check)(unsigned int flags); - - /* Prints out the target iff non-NULL: put space at end */ - void (*print)(const void *ip, - const struct xt_entry_target *target, int numeric); - - /* Saves the targinfo in parsable form to stdout. */ - void (*save)(const void *ip, - const struct xt_entry_target *target); - - /* Pointer to list of extra command-line options */ - const struct option *extra_opts; - - /* New parser */ - void (*x6_parse)(struct xt_option_call *); - void (*x6_fcheck)(struct xt_fcheck_call *); - const struct xt_option_entry *x6_options; - - size_t udata_size; - - /* Ignore these men behind the curtain: */ - void *udata; - unsigned int option_offset; - struct xt_entry_target *t; - unsigned int tflags; - unsigned int used; - unsigned int loaded; /* simulate loading so options are merged properly */ -}; - -struct xtables_rule_match { - struct xtables_rule_match *next; - struct xtables_match *match; - /* Multiple matches of the same type: the ones before - the current one are completed from parsing point of view */ - bool completed; -}; - -/** - * struct xtables_pprot - - * - * A few hardcoded protocols for 'all' and in case the user has no - * /etc/protocols. - */ -struct xtables_pprot { - const char *name; - u_int8_t num; -}; - -enum xtables_tryload { - XTF_DONT_LOAD, - XTF_DURING_LOAD, - XTF_TRY_LOAD, - XTF_LOAD_MUST_SUCCEED, -}; - -enum xtables_exittype { - OTHER_PROBLEM = 1, - PARAMETER_PROBLEM, - VERSION_PROBLEM, - RESOURCE_PROBLEM, - XTF_ONLY_ONCE, - XTF_NO_INVERT, - XTF_BAD_VALUE, - XTF_ONE_ACTION, -}; - -struct xtables_globals -{ - unsigned int option_offset; - const char *program_name, *program_version; - struct option *orig_opts; - struct option *opts; - void (*exit_err)(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); -}; - -#define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false} - -#ifdef __cplusplus -extern "C" { -#endif - -extern const char *xtables_modprobe_program; -extern struct xtables_match *xtables_matches; -extern struct xtables_target *xtables_targets; - -extern void xtables_init(void); -extern void xtables_set_nfproto(uint8_t); -extern void *xtables_calloc(size_t, size_t); -extern void *xtables_malloc(size_t); -extern void *xtables_realloc(void *, size_t); - -extern int xtables_insmod(const char *, const char *, bool); -extern int xtables_load_ko(const char *, bool); -extern int xtables_set_params(struct xtables_globals *xtp); -extern void xtables_free_opts(int reset_offset); -extern struct option *xtables_merge_options(struct option *origopts, - struct option *oldopts, const struct option *newopts, - unsigned int *option_offset); - -extern int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto); -extern struct xtables_match *xtables_find_match(const char *name, - enum xtables_tryload, struct xtables_rule_match **match); -extern struct xtables_target *xtables_find_target(const char *name, - enum xtables_tryload); - -/* Your shared library should call one of these. */ -extern void xtables_register_match(struct xtables_match *me); -extern void xtables_register_matches(struct xtables_match *, unsigned int); -extern void xtables_register_target(struct xtables_target *me); -extern void xtables_register_targets(struct xtables_target *, unsigned int); - -extern bool xtables_strtoul(const char *, char **, uintmax_t *, - uintmax_t, uintmax_t); -extern bool xtables_strtoui(const char *, char **, unsigned int *, - unsigned int, unsigned int); -extern int xtables_service_to_port(const char *name, const char *proto); -extern u_int16_t xtables_parse_port(const char *port, const char *proto); -extern void -xtables_parse_interface(const char *arg, char *vianame, unsigned char *mask); - -/* this is a special 64bit data type that is 8-byte aligned */ -#define aligned_u64 u_int64_t __attribute__((aligned(8))) - -extern struct xtables_globals *xt_params; -#define xtables_error (xt_params->exit_err) - -extern void xtables_param_act(unsigned int, const char *, ...); - -extern const char *xtables_ipaddr_to_numeric(const struct in_addr *); -extern const char *xtables_ipaddr_to_anyname(const struct in_addr *); -extern const char *xtables_ipmask_to_numeric(const struct in_addr *); -extern struct in_addr *xtables_numeric_to_ipaddr(const char *); -extern struct in_addr *xtables_numeric_to_ipmask(const char *); -extern int xtables_ipmask_to_cidr(const struct in_addr *); -extern void xtables_ipparse_any(const char *, struct in_addr **, - struct in_addr *, unsigned int *); -extern void xtables_ipparse_multiple(const char *, struct in_addr **, - struct in_addr **, unsigned int *); - -extern struct in6_addr *xtables_numeric_to_ip6addr(const char *); -extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *); -extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *); -extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *); -extern int xtables_ip6mask_to_cidr(const struct in6_addr *); -extern void xtables_ip6parse_any(const char *, struct in6_addr **, - struct in6_addr *, unsigned int *); -extern void xtables_ip6parse_multiple(const char *, struct in6_addr **, - struct in6_addr **, unsigned int *); - -/** - * Print the specified value to standard output, quoting dangerous - * characters if required. - */ -extern void xtables_save_string(const char *value); - -#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) -# ifdef _INIT -# undef _init -# define _init _INIT -# endif - extern void init_extensions(void); - extern void init_extensions4(void); - extern void init_extensions6(void); -#else -# define _init __attribute__((constructor)) _INIT -#endif - -extern const struct xtables_pprot xtables_chain_protos[]; -extern u_int16_t xtables_parse_protocol(const char *s); - -/* kernel revision handling */ -extern int kernel_version; -extern void get_kernel_version(void); -#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) -#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF) -#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF) -#define LINUX_VERSION_PATCH(x) ( (x) & 0xFF) - -/* xtoptions.c */ -extern void xtables_option_metavalidate(const char *, - const struct xt_option_entry *); -extern struct option *xtables_options_xfrm(struct option *, struct option *, - const struct xt_option_entry *, - unsigned int *); -extern void xtables_option_parse(struct xt_option_call *); -extern void xtables_option_tpcall(unsigned int, char **, bool, - struct xtables_target *, void *); -extern void xtables_option_mpcall(unsigned int, char **, bool, - struct xtables_match *, void *); -extern void xtables_option_tfcall(struct xtables_target *); -extern void xtables_option_mfcall(struct xtables_match *); -extern void xtables_options_fcheck(const char *, unsigned int, - const struct xt_option_entry *); - -extern struct xtables_lmap *xtables_lmap_init(const char *); -extern void xtables_lmap_free(struct xtables_lmap *); -extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *); -extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int); - -#ifdef XTABLES_INTERNAL - -/* Shipped modules rely on this... */ - -# ifndef ARRAY_SIZE -# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) -# endif - -extern void _init(void); - -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* _XTABLES_H */ -- cgit v1.2.3 From 067a9baf6dc82babe466078ab3c05354c7741271 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 6 Sep 2012 22:55:18 +0000 Subject: iptables: fix wrong error messages iptables -P INPUT iptables v1.4.15: -X requires a chain and a policy Try `iptables -h' or 'iptables --help' for more information. Note that it says -X when we have used -P. Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.c | 2 +- iptables/iptables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index b191d5df..7a16b974 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -85,7 +85,7 @@ #define CMD_CHECK 0x4000U #define NUMBER_OF_CMD 16 static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z', - 'Z', 'N', 'X', 'P', 'E', 'S', 'C' }; + 'N', 'X', 'P', 'E', 'S', 'Z', 'C' }; #define NUMBER_OF_OPT ARRAY_SIZE(optflags) static const char optflags[] diff --git a/iptables/iptables.c b/iptables/iptables.c index 03ac63b8..9e3d696a 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -81,7 +81,7 @@ #define CMD_CHECK 0x4000U #define NUMBER_OF_CMD 16 static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z', - 'Z', 'N', 'X', 'P', 'E', 'S', 'C' }; + 'N', 'X', 'P', 'E', 'S', 'Z', 'C' }; #define OPT_FRAGMENT 0x00800U #define NUMBER_OF_OPT ARRAY_SIZE(optflags) -- cgit v1.2.3 From 807e1f0e6ede73792337b595a99af21b01f8826e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 6 Sep 2012 22:55:19 +0000 Subject: extensions: libxt_addrtype: fix type in help message --limit-iface-out Match only on the packet's incoming device Note that it says "incoming" when it should say "outcoming" Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_addrtype.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_addrtype.c b/extensions/libxt_addrtype.c index 59072b35..e8a85456 100644 --- a/extensions/libxt_addrtype.c +++ b/extensions/libxt_addrtype.c @@ -60,7 +60,7 @@ static void addrtype_help_v1(void) " [!] --src-type type[,...] Match source address type\n" " [!] --dst-type type[,...] Match destination address type\n" " --limit-iface-in Match only on the packet's incoming device\n" -" --limit-iface-out Match only on the packet's incoming device\n" +" --limit-iface-out Match only on the packet's outgoing device\n" "\n" "Valid types: \n"); addrtype_help_types(); -- cgit v1.2.3 From e62f426c7ead7c0025d15860df97426db6509942 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:08 +0200 Subject: Convert the NAT targets to use the kernel supplied nf_nat.h header Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_DNAT.c | 36 +++---- extensions/libipt_MASQUERADE.c | 32 +++--- extensions/libipt_NETMAP.c | 18 ++-- extensions/libipt_REDIRECT.c | 34 +++--- extensions/libipt_SAME.c | 21 ++-- extensions/libipt_SNAT.c | 36 +++---- .../linux/netfilter/nf_conntrack_tuple_common.h | 27 +++++ include/linux/netfilter/nf_nat.h | 25 +++++ include/linux/netfilter_ipv4/ipt_SAME.h | 2 +- include/net/netfilter/nf_conntrack_tuple.h | 114 --------------------- include/net/netfilter/nf_nat.h | 55 ---------- 11 files changed, 144 insertions(+), 256 deletions(-) create mode 100644 include/linux/netfilter/nf_nat.h delete mode 100644 include/net/netfilter/nf_conntrack_tuple.h delete mode 100644 include/net/netfilter/nf_nat.h diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c index 466c9def..ff187999 100644 --- a/extensions/libipt_DNAT.c +++ b/extensions/libipt_DNAT.c @@ -6,7 +6,7 @@ #include /* get_kernel_version */ #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_DEST = 0, @@ -23,7 +23,7 @@ enum { struct ipt_natinfo { struct xt_entry_target t; - struct nf_nat_multi_range mr; + struct nf_nat_ipv4_multi_range_compat mr; }; static void DNAT_help(void) @@ -44,7 +44,7 @@ static const struct xt_option_entry DNAT_opts[] = { }; static struct ipt_natinfo * -append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) +append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range) { unsigned int size; @@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) static struct xt_entry_target * parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) { - struct nf_nat_range range; + struct nf_nat_ipv4_range range; char *arg, *colon, *dash, *error; const struct in_addr *ip; @@ -83,7 +83,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) xtables_error(PARAMETER_PROBLEM, "Need TCP, UDP, SCTP or DCCP with port specification"); - range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; port = atoi(colon+1); if (port <= 0 || port > 65535) @@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) *colon = '\0'; } - range.flags |= IP_NAT_RANGE_MAP_IPS; + range.flags |= NF_NAT_RANGE_MAP_IPS; dash = strchr(arg, '-'); if (colon && dash && dash > colon) dash = NULL; @@ -177,7 +177,7 @@ static void DNAT_parse(struct xt_option_call *cb) cb->xflags |= F_X_TO_DEST; break; case O_PERSISTENT: - info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; + info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT; break; } } @@ -185,15 +185,15 @@ static void DNAT_parse(struct xt_option_call *cb) static void DNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_DEST | F_RANDOM; - struct nf_nat_multi_range *mr = cb->data; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if ((cb->xflags & f) == f) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; } -static void print_range(const struct nf_nat_range *r) +static void print_range(const struct nf_nat_ipv4_range *r) { - if (r->flags & IP_NAT_RANGE_MAP_IPS) { + if (r->flags & NF_NAT_RANGE_MAP_IPS) { struct in_addr a; a.s_addr = r->min_ip; @@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r) printf("-%s", xtables_ipaddr_to_numeric(&a)); } } - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(":"); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) @@ -220,9 +220,9 @@ static void DNAT_print(const void *ip, const struct xt_entry_target *target, printf(" to:"); for (i = 0; i < info->mr.rangesize; i++) { print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } } @@ -235,9 +235,9 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target) for (i = 0; i < info->mr.rangesize; i++) { printf(" --to-destination "); print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } } @@ -246,8 +246,8 @@ static struct xtables_target dnat_tg_reg = { .name = "DNAT", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = DNAT_help, .x6_parse = DNAT_parse, .x6_fcheck = DNAT_fcheck, diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c index 7ba42dfd..ea074454 100644 --- a/extensions/libipt_MASQUERADE.c +++ b/extensions/libipt_MASQUERADE.c @@ -6,7 +6,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_PORTS = 0, @@ -31,7 +31,7 @@ static const struct xt_option_entry MASQUERADE_opts[] = { static void MASQUERADE_init(struct xt_entry_target *t) { - struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data; + struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data; /* Actually, it's 0, but it's ignored at the moment. */ mr->rangesize = 1; @@ -39,12 +39,12 @@ static void MASQUERADE_init(struct xt_entry_target *t) /* Parses ports */ static void -parse_ports(const char *arg, struct nf_nat_multi_range *mr) +parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr) { char *end; unsigned int port, maxport; - mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX)) xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); @@ -75,7 +75,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb) { const struct ipt_entry *entry = cb->xt_entry; int portok; - struct nf_nat_multi_range *mr = cb->data; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if (entry->ip.proto == IPPROTO_TCP || entry->ip.proto == IPPROTO_UDP @@ -95,7 +95,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb) parse_ports(cb->arg, mr); break; case O_RANDOM: - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; break; } } @@ -104,33 +104,33 @@ static void MASQUERADE_print(const void *ip, const struct xt_entry_target *target, int numeric) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" masq ports: "); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); } - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); } static void MASQUERADE_save(const void *ip, const struct xt_entry_target *target) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" --to-ports %hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); } - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); } @@ -138,8 +138,8 @@ static struct xtables_target masquerade_tg_reg = { .name = "MASQUERADE", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = MASQUERADE_help, .init = MASQUERADE_init, .x6_parse = MASQUERADE_parse, diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c index 5c4471a9..dee7b01b 100644 --- a/extensions/libipt_NETMAP.c +++ b/extensions/libipt_NETMAP.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define MODULENAME "NETMAP" @@ -45,7 +45,7 @@ netmask2bits(uint32_t netmask) static void NETMAP_init(struct xt_entry_target *t) { - struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data; + struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data; /* Actually, it's 0, but it's ignored at the moment. */ mr->rangesize = 1; @@ -53,11 +53,11 @@ static void NETMAP_init(struct xt_entry_target *t) static void NETMAP_parse(struct xt_option_call *cb) { - struct nf_nat_multi_range *mr = cb->data; - struct nf_nat_range *range = &mr->range[0]; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; + struct nf_nat_ipv4_range *range = &mr->range[0]; xtables_option_parse(cb); - range->flags |= IP_NAT_RANGE_MAP_IPS; + range->flags |= NF_NAT_RANGE_MAP_IPS; range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip; range->max_ip = range->min_ip | ~cb->val.hmask.ip; } @@ -65,8 +65,8 @@ static void NETMAP_parse(struct xt_option_call *cb) static void NETMAP_print(const void *ip, const struct xt_entry_target *target, int numeric) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; struct in_addr a; int bits; @@ -90,8 +90,8 @@ static struct xtables_target netmap_tg_reg = { .name = MODULENAME, .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = NETMAP_help, .init = NETMAP_init, .x6_parse = NETMAP_parse, diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c index e67360a0..610a9499 100644 --- a/extensions/libipt_REDIRECT.c +++ b/extensions/libipt_REDIRECT.c @@ -4,7 +4,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_PORTS = 0, @@ -30,7 +30,7 @@ static const struct xt_option_entry REDIRECT_opts[] = { static void REDIRECT_init(struct xt_entry_target *t) { - struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data; + struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data; /* Actually, it's 0, but it's ignored at the moment. */ mr->rangesize = 1; @@ -38,12 +38,12 @@ static void REDIRECT_init(struct xt_entry_target *t) /* Parses ports */ static void -parse_ports(const char *arg, struct nf_nat_multi_range *mr) +parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr) { char *end = ""; unsigned int port, maxport; - mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) && (port = xtables_service_to_port(arg, NULL)) == (unsigned)-1) @@ -75,7 +75,7 @@ parse_ports(const char *arg, struct nf_nat_multi_range *mr) static void REDIRECT_parse(struct xt_option_call *cb) { const struct ipt_entry *entry = cb->xt_entry; - struct nf_nat_multi_range *mr = (void *)(*cb->target)->data; + struct nf_nat_ipv4_multi_range_compat *mr = (void *)(*cb->target)->data; int portok; if (entry->ip.proto == IPPROTO_TCP @@ -95,11 +95,11 @@ static void REDIRECT_parse(struct xt_option_call *cb) "Need TCP, UDP, SCTP or DCCP with port specification"); parse_ports(cb->arg, mr); if (cb->xflags & F_RANDOM) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; break; case O_RANDOM: if (cb->xflags & F_TO_PORTS) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; break; } } @@ -107,30 +107,30 @@ static void REDIRECT_parse(struct xt_option_call *cb) static void REDIRECT_print(const void *ip, const struct xt_entry_target *target, int numeric) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" redir ports "); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); - if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); } } static void REDIRECT_save(const void *ip, const struct xt_entry_target *target) { - const struct nf_nat_multi_range *mr = (const void *)target->data; - const struct nf_nat_range *r = &mr->range[0]; + const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; + const struct nf_nat_ipv4_range *r = &mr->range[0]; - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(" --to-ports "); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) printf("-%hu", ntohs(r->max.tcp.port)); - if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); } } @@ -139,8 +139,8 @@ static struct xtables_target redirect_tg_reg = { .name = "REDIRECT", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = REDIRECT_help, .init = REDIRECT_init, .x6_parse = REDIRECT_parse, diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c index e603ef64..5d5bf630 100644 --- a/extensions/libipt_SAME.c +++ b/extensions/libipt_SAME.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include enum { @@ -37,7 +37,7 @@ static const struct xt_option_entry SAME_opts[] = { }; /* Parses range of IPs */ -static void parse_to(const char *orig_arg, struct nf_nat_range *range) +static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range) { char *dash, *arg; const struct in_addr *ip; @@ -45,7 +45,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range) arg = strdup(orig_arg); if (arg == NULL) xtables_error(RESOURCE_PROBLEM, "strdup"); - range->flags |= IP_NAT_RANGE_MAP_IPS; + range->flags |= NF_NAT_RANGE_MAP_IPS; dash = strchr(arg, '-'); if (dash) @@ -74,6 +74,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range) static void SAME_parse(struct xt_option_call *cb) { struct ipt_same_info *mr = cb->data; + unsigned int count; xtables_option_parse(cb); switch (cb->entry->id) { @@ -89,6 +90,10 @@ static void SAME_parse(struct xt_option_call *cb) case O_NODST: mr->info |= IPT_SAME_NODST; break; + case O_RANDOM: + for (count=0; count < mr->rangesize; count++) + mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; } } @@ -100,7 +105,7 @@ static void SAME_fcheck(struct xt_fcheck_call *cb) if ((cb->xflags & f) == f) for (count = 0; count < mr->rangesize; ++count) - mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM; } static void SAME_print(const void *ip, const struct xt_entry_target *target, @@ -113,7 +118,7 @@ static void SAME_print(const void *ip, const struct xt_entry_target *target, printf(" same:"); for (count = 0; count < mr->rangesize; count++) { - const struct nf_nat_range *r = &mr->range[count]; + const struct nf_nat_ipv4_range *r = &mr->range[count]; struct in_addr a; a.s_addr = r->min_ip; @@ -123,7 +128,7 @@ static void SAME_print(const void *ip, const struct xt_entry_target *target, if (r->min_ip != r->max_ip) printf("-%s", xtables_ipaddr_to_numeric(&a)); - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) random_selection = 1; } @@ -141,7 +146,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target) int random_selection = 0; for (count = 0; count < mr->rangesize; count++) { - const struct nf_nat_range *r = &mr->range[count]; + const struct nf_nat_ipv4_range *r = &mr->range[count]; struct in_addr a; a.s_addr = r->min_ip; @@ -150,7 +155,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target) if (r->min_ip != r->max_ip) printf("-%s", xtables_ipaddr_to_numeric(&a)); - if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) random_selection = 1; } diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index c8cb26df..1a24f3d8 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -6,7 +6,7 @@ #include #include /* INT_MAX in ip_tables.h */ #include -#include +#include enum { O_TO_SRC = 0, @@ -23,7 +23,7 @@ enum { struct ipt_natinfo { struct xt_entry_target t; - struct nf_nat_multi_range mr; + struct nf_nat_ipv4_multi_range_compat mr; }; static void SNAT_help(void) @@ -44,7 +44,7 @@ static const struct xt_option_entry SNAT_opts[] = { }; static struct ipt_natinfo * -append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) +append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range) { unsigned int size; @@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) static struct xt_entry_target * parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) { - struct nf_nat_range range; + struct nf_nat_ipv4_range range; char *arg, *colon, *dash, *error; const struct in_addr *ip; @@ -83,7 +83,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) xtables_error(PARAMETER_PROBLEM, "Need TCP, UDP, SCTP or DCCP with port specification"); - range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; port = atoi(colon+1); if (port <= 0 || port > 65535) @@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) *colon = '\0'; } - range.flags |= IP_NAT_RANGE_MAP_IPS; + range.flags |= NF_NAT_RANGE_MAP_IPS; dash = strchr(arg, '-'); if (colon && dash && dash > colon) dash = NULL; @@ -177,7 +177,7 @@ static void SNAT_parse(struct xt_option_call *cb) cb->xflags |= F_X_TO_SRC; break; case O_PERSISTENT: - info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; + info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT; break; } } @@ -185,15 +185,15 @@ static void SNAT_parse(struct xt_option_call *cb) static void SNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_SRC | F_RANDOM; - struct nf_nat_multi_range *mr = cb->data; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if ((cb->xflags & f) == f) - mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; } -static void print_range(const struct nf_nat_range *r) +static void print_range(const struct nf_nat_ipv4_range *r) { - if (r->flags & IP_NAT_RANGE_MAP_IPS) { + if (r->flags & NF_NAT_RANGE_MAP_IPS) { struct in_addr a; a.s_addr = r->min_ip; @@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r) printf("-%s", xtables_ipaddr_to_numeric(&a)); } } - if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { printf(":"); printf("%hu", ntohs(r->min.tcp.port)); if (r->max.tcp.port != r->min.tcp.port) @@ -220,9 +220,9 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, printf(" to:"); for (i = 0; i < info->mr.rangesize; i++) { print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } } @@ -235,9 +235,9 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) for (i = 0; i < info->mr.rangesize; i++) { printf(" --to-source "); print_range(&info->mr.range[i]); - if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM) + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); - if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT) + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } } @@ -246,8 +246,8 @@ static struct xtables_target snat_tg_reg = { .name = "SNAT", .version = XTABLES_VERSION, .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), - .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), + .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), .help = SNAT_help, .x6_parse = SNAT_parse, .x6_fcheck = SNAT_fcheck, diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h index 2ea22b01..2f6bbc5b 100644 --- a/include/linux/netfilter/nf_conntrack_tuple_common.h +++ b/include/linux/netfilter/nf_conntrack_tuple_common.h @@ -7,6 +7,33 @@ enum ip_conntrack_dir { IP_CT_DIR_MAX }; +/* The protocol-specific manipulable parts of the tuple: always in + * network order + */ +union nf_conntrack_man_proto { + /* Add other protocols here. */ + __be16 all; + + struct { + __be16 port; + } tcp; + struct { + __be16 port; + } udp; + struct { + __be16 id; + } icmp; + struct { + __be16 port; + } dccp; + struct { + __be16 port; + } sctp; + struct { + __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */ + } gre; +}; + #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) #endif /* _NF_CONNTRACK_TUPLE_COMMON_H */ diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h new file mode 100644 index 00000000..8df2d137 --- /dev/null +++ b/include/linux/netfilter/nf_nat.h @@ -0,0 +1,25 @@ +#ifndef _NETFILTER_NF_NAT_H +#define _NETFILTER_NF_NAT_H + +#include +#include + +#define NF_NAT_RANGE_MAP_IPS 1 +#define NF_NAT_RANGE_PROTO_SPECIFIED 2 +#define NF_NAT_RANGE_PROTO_RANDOM 4 +#define NF_NAT_RANGE_PERSISTENT 8 + +struct nf_nat_ipv4_range { + unsigned int flags; + __be32 min_ip; + __be32 max_ip; + union nf_conntrack_man_proto min; + union nf_conntrack_man_proto max; +}; + +struct nf_nat_ipv4_multi_range_compat { + unsigned int rangesize; + struct nf_nat_ipv4_range range[1]; +}; + +#endif /* _NETFILTER_NF_NAT_H */ diff --git a/include/linux/netfilter_ipv4/ipt_SAME.h b/include/linux/netfilter_ipv4/ipt_SAME.h index 5bca7826..a8551671 100644 --- a/include/linux/netfilter_ipv4/ipt_SAME.h +++ b/include/linux/netfilter_ipv4/ipt_SAME.h @@ -14,7 +14,7 @@ struct ipt_same_info { __u32 *iparray; /* hangs off end. */ - struct nf_nat_range range[IPT_SAME_MAX_RANGE]; + struct nf_nat_ipv4_range range[IPT_SAME_MAX_RANGE]; }; #endif /*_IPT_SAME_H*/ diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h deleted file mode 100644 index c40e0b40..00000000 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ /dev/null @@ -1,114 +0,0 @@ -/* This file was manually copied from the Linux kernel source - * and manually stripped from __KERNEL__ sections and unused functions. - */ - -/* - * Definitions and Declarations for tuple. - * - * 16 Dec 2003: Yasuyuki Kozakai @USAGI - * - generalize L3 protocol dependent part. - * - * Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h - */ - -#ifndef _NF_CONNTRACK_TUPLE_H -#define _NF_CONNTRACK_TUPLE_H - -#include -#include - -/* A `tuple' is a structure containing the information to uniquely - identify a connection. ie. if two packets have the same tuple, they - are in the same connection; if not, they are not. - - We divide the structure along "manipulatable" and - "non-manipulatable" lines, for the benefit of the NAT code. -*/ - -#define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all) - -/* The protocol-specific manipulable parts of the tuple: always in - network order! */ -union nf_conntrack_man_proto -{ - /* Add other protocols here. */ - __be16 all; - - struct { - __be16 port; - } tcp; - struct { - __be16 port; - } udp; - struct { - __be16 id; - } icmp; - struct { - __be16 port; - } dccp; - struct { - __be16 port; - } sctp; - struct { - __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */ - } gre; -}; - -/* The manipulable part of the tuple. */ -struct nf_conntrack_man -{ - union nf_inet_addr u3; - union nf_conntrack_man_proto u; - /* Layer 3 protocol */ - u_int16_t l3num; -}; - -/* This contains the information to distinguish a connection. */ -struct nf_conntrack_tuple -{ - struct nf_conntrack_man src; - - /* These are the parts of the tuple which are fixed. */ - struct { - union nf_inet_addr u3; - union { - /* Add other protocols here. */ - __be16 all; - - struct { - __be16 port; - } tcp; - struct { - __be16 port; - } udp; - struct { - u_int8_t type, code; - } icmp; - struct { - __be16 port; - } dccp; - struct { - __be16 port; - } sctp; - struct { - __be16 key; - } gre; - } u; - - /* The protocol. */ - u_int8_t protonum; - - /* The direction (for tuplehash) */ - u_int8_t dir; - } dst; -}; - -struct nf_conntrack_tuple_mask -{ - struct { - union nf_inet_addr u3; - union nf_conntrack_man_proto u; - } src; -}; - -#endif /* _NF_CONNTRACK_TUPLE_H */ diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h deleted file mode 100644 index c3e2060c..00000000 --- a/include/net/netfilter/nf_nat.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _NF_NAT_H -#define _NF_NAT_H -#include -#include - -#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16 - -enum nf_nat_manip_type -{ - IP_NAT_MANIP_SRC, - IP_NAT_MANIP_DST -}; - -/* SRC manip occurs POST_ROUTING or LOCAL_IN */ -#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \ - (hooknum) != NF_INET_LOCAL_IN) - -#define IP_NAT_RANGE_MAP_IPS 1 -#define IP_NAT_RANGE_PROTO_SPECIFIED 2 -#define IP_NAT_RANGE_PROTO_RANDOM 4 -#define IP_NAT_RANGE_PERSISTENT 8 - -/* NAT sequence number modifications */ -struct nf_nat_seq { - /* position of the last TCP sequence number modification (if any) */ - u_int32_t correction_pos; - - /* sequence number offset before and after last modification */ - int16_t offset_before, offset_after; -}; - -/* Single range specification. */ -struct nf_nat_range -{ - /* Set to OR of flags above. */ - unsigned int flags; - - /* Inclusive: network order. */ - __be32 min_ip, max_ip; - - /* Inclusive: network order */ - union nf_conntrack_man_proto min, max; -}; - -/* For backwards compat: don't use in modern code. */ -struct nf_nat_multi_range_compat -{ - unsigned int rangesize; /* Must be 1. */ - - /* hangs off end. */ - struct nf_nat_range range[1]; -}; - -#define nf_nat_multi_range nf_nat_multi_range_compat -#endif -- cgit v1.2.3 From 0e37f00980eb6b4fc2c5f979cc5fa83c0fff9d30 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:10 +0200 Subject: extensions: add IPv6 MASQUERADE extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_MASQUERADE.c | 150 ++++++++++++++++++++++++++++++++++++++ extensions/libip6t_MASQUERADE.man | 30 ++++++++ include/linux/netfilter/nf_nat.h | 8 ++ 3 files changed, 188 insertions(+) create mode 100644 extensions/libip6t_MASQUERADE.c create mode 100644 extensions/libip6t_MASQUERADE.man diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c new file mode 100644 index 00000000..eb9213ef --- /dev/null +++ b/extensions/libip6t_MASQUERADE.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_PORTS = 0, + O_RANDOM, +}; + +static void MASQUERADE_help(void) +{ + printf( +"MASQUERADE target options:\n" +" --to-ports [-]\n" +" Port (range) to map to.\n" +" --random\n" +" Randomize source port.\n"); +} + +static const struct xt_option_entry MASQUERADE_opts[] = { + {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Parses ports */ +static void +parse_ports(const char *arg, struct nf_nat_range *r) +{ + char *end; + unsigned int port, maxport; + + r->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX)) + xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); + + switch (*end) { + case '\0': + r->min_proto.tcp.port + = r->max_proto.tcp.port + = htons(port); + return; + case '-': + if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX)) + break; + + if (maxport < port) + break; + + r->min_proto.tcp.port = htons(port); + r->max_proto.tcp.port = htons(maxport); + return; + default: + break; + } + xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); +} + +static void MASQUERADE_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *r = cb->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP || + entry->ipv6.proto == IPPROTO_UDP || + entry->ipv6.proto == IPPROTO_SCTP || + entry->ipv6.proto == IPPROTO_DCCP || + entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_PORTS: + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + parse_ports(cb->arg, r); + break; + case O_RANDOM: + r->flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; + } +} + +static void +MASQUERADE_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *r = (const void *)target->data; + + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" masq ports: "); + printf("%hu", ntohs(r->min_proto.tcp.port)); + if (r->max_proto.tcp.port != r->min_proto.tcp.port) + printf("-%hu", ntohs(r->max_proto.tcp.port)); + } + + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); +} + +static void +MASQUERADE_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *r = (const void *)target->data; + + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" --to-ports %hu", ntohs(r->min_proto.tcp.port)); + if (r->max_proto.tcp.port != r->min_proto.tcp.port) + printf("-%hu", ntohs(r->max_proto.tcp.port)); + } + + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); +} + +static struct xtables_target masquerade_tg_reg = { + .name = "MASQUERADE", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = MASQUERADE_help, + .x6_parse = MASQUERADE_parse, + .print = MASQUERADE_print, + .save = MASQUERADE_save, + .x6_options = MASQUERADE_opts, +}; + +void _init(void) +{ + xtables_register_target(&masquerade_tg_reg); +} diff --git a/extensions/libip6t_MASQUERADE.man b/extensions/libip6t_MASQUERADE.man new file mode 100644 index 00000000..c63d826b --- /dev/null +++ b/extensions/libip6t_MASQUERADE.man @@ -0,0 +1,30 @@ +This target is only valid in the +.B nat +table, in the +.B POSTROUTING +chain. It should only be used with dynamically assigned IPv6 (dialup) +connections: if you have a static IP address, you should use the SNAT +target. Masquerading is equivalent to specifying a mapping to the IP +address of the interface the packet is going out, but also has the +effect that connections are +.I forgotten +when the interface goes down. This is the correct behavior when the +next dialup is unlikely to have the same interface address (and hence +any established connections are lost anyway). +.TP +\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP] +This specifies a range of source ports to use, overriding the default +.B SNAT +source port-selection heuristics (see above). This is only valid +if the rule also specifies +\fB\-p tcp\fP +or +\fB\-p udp\fP. +.TP +\fB\-\-random\fP +Randomize source port mapping +If option +\fB\-\-random\fP +is used then port mapping will be randomized. +.RS +.PP diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h index 8df2d137..bf0cc373 100644 --- a/include/linux/netfilter/nf_nat.h +++ b/include/linux/netfilter/nf_nat.h @@ -22,4 +22,12 @@ struct nf_nat_ipv4_multi_range_compat { struct nf_nat_ipv4_range range[1]; }; +struct nf_nat_range { + unsigned int flags; + union nf_inet_addr min_addr; + union nf_inet_addr max_addr; + union nf_conntrack_man_proto min_proto; + union nf_conntrack_man_proto max_proto; +}; + #endif /* _NETFILTER_NF_NAT_H */ -- cgit v1.2.3 From 3672111649732be657cb7566178b7d2618ba6ec5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:11 +0200 Subject: extensions: add IPv6 SNAT extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_SNAT.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 extensions/libip6t_SNAT.c diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c new file mode 100644 index 00000000..307be70e --- /dev/null +++ b/extensions/libip6t_SNAT.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_SRC = 0, + O_RANDOM, + O_PERSISTENT, + O_X_TO_SRC, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, + F_X_TO_SRC = 1 << O_X_TO_SRC, +}; + +static void SNAT_help(void) +{ + printf( +"SNAT target options:\n" +" --to-source [[-]][:port[-port]]\n" +" Address to map source to.\n" +"[--random] [--persistent]\n"); +} + +static const struct xt_option_entry SNAT_opts[] = { + {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_MULTI}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Ranges expected in network order. */ +static void +parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) +{ + char *arg, *start, *end = NULL, *colon = NULL, *dash, *error; + const struct in6_addr *ip; + + arg = strdup(orig_arg); + if (arg == NULL) + xtables_error(RESOURCE_PROBLEM, "strdup"); + + start = strchr(arg, '['); + if (start == NULL) + start = arg; + else { + start++; + end = strchr(start, ']'); + if (end == NULL) + xtables_error(PARAMETER_PROBLEM, + "Invalid address format"); + + *end = '\0'; + colon = strchr(end + 1, ':'); + } + + if (colon) { + int port; + + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + + range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + port = atoi(colon+1); + if (port <= 0 || port > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", colon+1); + + error = strchr(colon+1, ':'); + if (error) + xtables_error(PARAMETER_PROBLEM, + "Invalid port:port syntax - use dash\n"); + + dash = strchr(colon, '-'); + if (!dash) { + range->min_proto.tcp.port + = range->max_proto.tcp.port + = htons(port); + } else { + int maxport; + + maxport = atoi(dash + 1); + if (maxport <= 0 || maxport > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", dash+1); + if (maxport < port) + /* People are stupid. */ + xtables_error(PARAMETER_PROBLEM, + "Port range `%s' funky\n", colon+1); + range->min_proto.tcp.port = htons(port); + range->max_proto.tcp.port = htons(maxport); + } + /* Starts with a colon? No IP info...*/ + if (colon == arg) { + free(arg); + return; + } + *colon = '\0'; + } + + range->flags |= NF_NAT_RANGE_MAP_IPS; + dash = strchr(start, '-'); + if (colon && dash && dash > colon) + dash = NULL; + + if (dash) + *dash = '\0'; + + ip = xtables_numeric_to_ip6addr(start); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + start); + range->min_addr.in6 = *ip; + if (dash) { + ip = xtables_numeric_to_ip6addr(dash + 1); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + dash+1); + range->max_addr.in6 = *ip; + } else + range->max_addr = range->min_addr; + + free(arg); + return; +} + +static void SNAT_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *range = cb->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP || + entry->ipv6.proto == IPPROTO_UDP || + entry->ipv6.proto == IPPROTO_SCTP || + entry->ipv6.proto == IPPROTO_DCCP || + entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_SRC: + if (cb->xflags & F_X_TO_SRC) { + if (!kernel_version) + get_kernel_version(); + if (kernel_version > LINUX_VERSION(2, 6, 10)) + xtables_error(PARAMETER_PROBLEM, + "SNAT: Multiple --to-source not supported"); + } + parse_to(cb->arg, portok, range); + break; + case O_PERSISTENT: + range->flags |= NF_NAT_RANGE_PERSISTENT; + break; + } +} + +static void SNAT_fcheck(struct xt_fcheck_call *cb) +{ + static const unsigned int f = F_TO_SRC | F_RANDOM; + struct nf_nat_range *range = cb->data; + + if ((cb->xflags & f) == f) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM; +} + +static void print_range(const struct nf_nat_range *range) +{ + if (range->flags & NF_NAT_RANGE_MAP_IPS) { + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("["); + printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6)); + if (memcmp(&range->min_addr, &range->max_addr, + sizeof(range->min_addr))) + printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6)); + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("]"); + } + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(":"); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + } +} + +static void SNAT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" to:"); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" persistent"); +} + +static void SNAT_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" --to-source "); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" --persistent"); +} + +static struct xtables_target snat_tg_reg = { + .name = "SNAT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .revision = 1, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = SNAT_help, + .x6_parse = SNAT_parse, + .x6_fcheck = SNAT_fcheck, + .print = SNAT_print, + .save = SNAT_save, + .x6_options = SNAT_opts, +}; + +void _init(void) +{ + xtables_register_target(&snat_tg_reg); +} -- cgit v1.2.3 From 9caf63581907860a1a0acee970b9f50d41b6a8ba Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:12 +0200 Subject: extensions: add IPv6 DNAT target Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNAT.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 extensions/libip6t_DNAT.c diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c new file mode 100644 index 00000000..a5969c36 --- /dev/null +++ b/extensions/libip6t_DNAT.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_DEST = 0, + O_RANDOM, + O_PERSISTENT, + O_X_TO_DEST, + F_TO_DEST = 1 << O_TO_DEST, + F_RANDOM = 1 << O_RANDOM, + F_X_TO_DEST = 1 << O_X_TO_DEST, +}; + +static void DNAT_help(void) +{ + printf( +"DNAT target options:\n" +" --to-dest [[-]][:port[-port]]\n" +" Address to map source to.\n" +"[--random] [--persistent]\n"); +} + +static const struct xt_option_entry DNAT_opts[] = { + {.name = "to-dest", .id = O_TO_DEST, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_MULTI}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Ranges expected in network order. */ +static void +parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) +{ + char *arg, *start, *end = NULL, *colon = NULL, *dash, *error; + const struct in6_addr *ip; + + arg = strdup(orig_arg); + if (arg == NULL) + xtables_error(RESOURCE_PROBLEM, "strdup"); + + start = strchr(arg, '['); + if (start == NULL) + start = arg; + else { + start++; + end = strchr(start, ']'); + if (end == NULL) + xtables_error(PARAMETER_PROBLEM, + "Invalid address format"); + + *end = '\0'; + colon = strchr(end + 1, ':'); + } + + if (colon) { + int port; + + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + + range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + port = atoi(colon+1); + if (port <= 0 || port > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", colon+1); + + error = strchr(colon+1, ':'); + if (error) + xtables_error(PARAMETER_PROBLEM, + "Invalid port:port syntax - use dash\n"); + + dash = strchr(colon, '-'); + if (!dash) { + range->min_proto.tcp.port + = range->max_proto.tcp.port + = htons(port); + } else { + int maxport; + + maxport = atoi(dash + 1); + if (maxport <= 0 || maxport > 65535) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", dash+1); + if (maxport < port) + /* People are stupid. */ + xtables_error(PARAMETER_PROBLEM, + "Port range `%s' funky\n", colon+1); + range->min_proto.tcp.port = htons(port); + range->max_proto.tcp.port = htons(maxport); + } + /* Starts with a colon? No IP info...*/ + if (colon == arg) { + free(arg); + return; + } + *colon = '\0'; + } + + range->flags |= NF_NAT_RANGE_MAP_IPS; + dash = strchr(start, '-'); + if (colon && dash && dash > colon) + dash = NULL; + + if (dash) + *dash = '\0'; + + ip = xtables_numeric_to_ip6addr(start); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + start); + range->min_addr.in6 = *ip; + if (dash) { + ip = xtables_numeric_to_ip6addr(dash + 1); + if (!ip) + xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", + dash+1); + range->max_addr.in6 = *ip; + } else + range->max_addr = range->min_addr; + + free(arg); + return; +} + +static void DNAT_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *range = cb->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP || + entry->ipv6.proto == IPPROTO_UDP || + entry->ipv6.proto == IPPROTO_SCTP || + entry->ipv6.proto == IPPROTO_DCCP || + entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_DEST: + if (cb->xflags & F_X_TO_DEST) { + if (!kernel_version) + get_kernel_version(); + if (kernel_version > LINUX_VERSION(2, 6, 10)) + xtables_error(PARAMETER_PROBLEM, + "DNAT: Multiple --to-source not supported"); + } + parse_to(cb->arg, portok, range); + break; + case O_PERSISTENT: + range->flags |= NF_NAT_RANGE_PERSISTENT; + break; + } +} + +static void DNAT_fcheck(struct xt_fcheck_call *cb) +{ + static const unsigned int f = F_TO_DEST | F_RANDOM; + struct nf_nat_range *mr = cb->data; + + if ((cb->xflags & f) == f) + mr->flags |= NF_NAT_RANGE_PROTO_RANDOM; +} + +static void print_range(const struct nf_nat_range *range) +{ + if (range->flags & NF_NAT_RANGE_MAP_IPS) { + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("["); + printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6)); + if (memcmp(&range->min_addr, &range->max_addr, + sizeof(range->min_addr))) + printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6)); + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) + printf("]"); + } + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(":"); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + } +} + +static void DNAT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" to:"); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" persistent"); +} + +static void DNAT_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *range = (const void *)target->data; + + printf(" --to-source "); + print_range(range); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" --persistent"); +} + +static struct xtables_target snat_tg_reg = { + .name = "DNAT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .revision = 1, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = DNAT_help, + .x6_parse = DNAT_parse, + .x6_fcheck = DNAT_fcheck, + .print = DNAT_print, + .save = DNAT_save, + .x6_options = DNAT_opts, +}; + +void _init(void) +{ + xtables_register_target(&snat_tg_reg); +} -- cgit v1.2.3 From 5eca41982d29bc25b241692d03b09b953e7a908a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:14 +0200 Subject: extensions: add IPv6 REDIRECT extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_REDIRECT.c | 151 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 extensions/libip6t_REDIRECT.c diff --git a/extensions/libip6t_REDIRECT.c b/extensions/libip6t_REDIRECT.c new file mode 100644 index 00000000..1724aa67 --- /dev/null +++ b/extensions/libip6t_REDIRECT.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include /* INT_MAX in ip_tables.h */ +#include +#include + +enum { + O_TO_PORTS = 0, + O_RANDOM, + F_TO_PORTS = 1 << O_TO_PORTS, + F_RANDOM = 1 << O_RANDOM, +}; + +static void REDIRECT_help(void) +{ + printf( +"REDIRECT target options:\n" +" --to-ports [-]\n" +" Port (range) to map to.\n" +" [--random]\n"); +} + +static const struct xt_option_entry REDIRECT_opts[] = { + {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +/* Parses ports */ +static void +parse_ports(const char *arg, struct nf_nat_range *range) +{ + char *end = ""; + unsigned int port, maxport; + + range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; + + if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) && + (port = xtables_service_to_port(arg, NULL)) == (unsigned)-1) + xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg); + + switch (*end) { + case '\0': + range->min_proto.tcp.port + = range->max_proto.tcp.port + = htons(port); + return; + case '-': + if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) && + (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1) + break; + + if (maxport < port) + break; + + range->min_proto.tcp.port = htons(port); + range->max_proto.tcp.port = htons(maxport); + return; + default: + break; + } + xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg); +} + +static void REDIRECT_parse(struct xt_option_call *cb) +{ + const struct ip6t_entry *entry = cb->xt_entry; + struct nf_nat_range *range = (void *)(*cb->target)->data; + int portok; + + if (entry->ipv6.proto == IPPROTO_TCP + || entry->ipv6.proto == IPPROTO_UDP + || entry->ipv6.proto == IPPROTO_SCTP + || entry->ipv6.proto == IPPROTO_DCCP + || entry->ipv6.proto == IPPROTO_ICMP) + portok = 1; + else + portok = 0; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_PORTS: + if (!portok) + xtables_error(PARAMETER_PROBLEM, + "Need TCP, UDP, SCTP or DCCP with port specification"); + parse_ports(cb->arg, range); + if (cb->xflags & F_RANDOM) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; + case O_RANDOM: + if (cb->xflags & F_TO_PORTS) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM; + break; + } +} + +static void REDIRECT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *range = (const void *)target->data; + + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" redir ports "); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" random"); + } +} + +static void REDIRECT_save(const void *ip, const struct xt_entry_target *target) +{ + const struct nf_nat_range *range = (const void *)target->data; + + if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { + printf(" --to-ports "); + printf("%hu", ntohs(range->min_proto.tcp.port)); + if (range->max_proto.tcp.port != range->min_proto.tcp.port) + printf("-%hu", ntohs(range->max_proto.tcp.port)); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + printf(" --random"); + } +} + +static struct xtables_target redirect_tg_reg = { + .name = "REDIRECT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = REDIRECT_help, + .x6_parse = REDIRECT_parse, + .print = REDIRECT_print, + .save = REDIRECT_save, + .x6_options = REDIRECT_opts, +}; + +void _init(void) +{ + xtables_register_target(&redirect_tg_reg); +} -- cgit v1.2.3 From 5f896fd9432d2c16d17550b943f4b9a782bffe04 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:16 +0200 Subject: extensions: add IPv6 NETMAP extension Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/GNUmakefile.in | 2 +- extensions/libip6t_NETMAP.c | 93 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 extensions/libip6t_NETMAP.c diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 218dc3ad..2492d184 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -97,10 +97,10 @@ lib%.oo: ${srcdir}/lib%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD +ip6t_NETMAP_LIBADD = -lip6tc xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm - # # Static bits # diff --git a/extensions/libip6t_NETMAP.c b/extensions/libip6t_NETMAP.c new file mode 100644 index 00000000..d14dece3 --- /dev/null +++ b/extensions/libip6t_NETMAP.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT + * funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULENAME "NETMAP" + +enum { + O_TO = 0, +}; + +static const struct xt_option_entry NETMAP_opts[] = { + {.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND}, + XTOPT_TABLEEND, +}; + +static void NETMAP_help(void) +{ + printf(MODULENAME" target options:\n" + " --%s address[/mask]\n" + " Network address to map to.\n\n", + NETMAP_opts[0].name); +} + +static void NETMAP_parse(struct xt_option_call *cb) +{ + struct nf_nat_range *range = cb->data; + unsigned int i; + + xtables_option_parse(cb); + range->flags |= NF_NAT_RANGE_MAP_IPS; + for (i = 0; i < 4; i++) { + range->min_addr.ip6[i] = cb->val.haddr.ip6[i] & + cb->val.hmask.ip6[i]; + range->max_addr.ip6[i] = range->min_addr.ip6[i] | + ~cb->val.hmask.ip6[i]; + } +} + +static void NETMAP_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct nf_nat_range *r = (const void *)target->data; + struct in6_addr a; + unsigned int i; + int bits; + + a = r->min_addr.in6; + printf("%s", xtables_ip6addr_to_numeric(&a)); + for (i = 0; i < 4; i++) + a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]); + bits = ipv6_prefix_length(&a); + if (bits < 0) + printf("/%s", xtables_ip6addr_to_numeric(&a)); + else + printf("/%d", bits); +} + +static void NETMAP_save(const void *ip, const struct xt_entry_target *target) +{ + printf(" --%s ", NETMAP_opts[0].name); + NETMAP_print(ip, target, 0); +} + +static struct xtables_target netmap_tg_reg = { + .name = MODULENAME, + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct nf_nat_range)), + .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), + .help = NETMAP_help, + .x6_parse = NETMAP_parse, + .print = NETMAP_print, + .save = NETMAP_save, + .x6_options = NETMAP_opts, +}; + +void _init(void) +{ + xtables_register_target(&netmap_tg_reg); +} -- cgit v1.2.3 From 1871796877956ee68a39092c6fc3678e5a9d1d88 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 22 Aug 2012 12:27:17 +0200 Subject: extensions: add NPT extension Add extensions for the SNPT and DNPT stateless IPv6-to-IPv6 Network Prefix Translation targets. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNPT.c | 71 +++++++++++++++++++++++++++++++++ extensions/libip6t_SNPT.c | 71 +++++++++++++++++++++++++++++++++ include/linux/netfilter_ipv6/ip6t_NPT.h | 16 ++++++++ 3 files changed, 158 insertions(+) create mode 100644 extensions/libip6t_DNPT.c create mode 100644 extensions/libip6t_SNPT.c create mode 100644 include/linux/netfilter_ipv6/ip6t_NPT.h diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c new file mode 100644 index 00000000..9e4dc5cf --- /dev/null +++ b/extensions/libip6t_DNPT.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +enum { + O_SRC_PFX = 1 << 0, + O_DST_PFX = 1 << 1, +}; + +static const struct xt_option_entry SNPT_options[] = { + { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { } +}; + +static void SNPT_help(void) +{ + printf("SNPT target options:" + "\n" + " --src-pfx prefix/length\n" + " --dst-pfx prefix/length\n" + "\n"); +} + +static void SNPT_parse(struct xt_option_call *cb) +{ + struct ip6t_npt_tginfo *npt = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SRC_PFX: + npt->src_pfx = cb->val.haddr; + npt->src_pfx_len = cb->val.hlen; + break; + case O_DST_PFX: + npt->dst_pfx = cb->val.haddr; + npt->dst_pfx_len = cb->val.hlen; + break; + } +} + +static void SNPT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct ip6t_npt_tginfo *npt = (const void *)target->data; + + printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), + npt->src_pfx_len); + printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), + npt->dst_pfx_len); +} + +static struct xtables_target snpt_tg_reg = { + .name = "DNPT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)), + .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment), + .help = SNPT_help, + .x6_parse = SNPT_parse, + .print = SNPT_print, + .x6_options = SNPT_options, +}; + +void _init(void) +{ + xtables_register_target(&snpt_tg_reg); +} diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c new file mode 100644 index 00000000..26a86c56 --- /dev/null +++ b/extensions/libip6t_SNPT.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +enum { + O_SRC_PFX = 1 << 0, + O_DST_PFX = 1 << 1, +}; + +static const struct xt_option_entry SNPT_options[] = { + { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND }, + { } +}; + +static void SNPT_help(void) +{ + printf("SNPT target options:" + "\n" + " --src-pfx prefix/length\n" + " --dst-pfx prefix/length\n" + "\n"); +} + +static void SNPT_parse(struct xt_option_call *cb) +{ + struct ip6t_npt_tginfo *npt = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SRC_PFX: + npt->src_pfx = cb->val.haddr; + npt->src_pfx_len = cb->val.hlen; + break; + case O_DST_PFX: + npt->dst_pfx = cb->val.haddr; + npt->dst_pfx_len = cb->val.hlen; + break; + } +} + +static void SNPT_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct ip6t_npt_tginfo *npt = (const void *)target->data; + + printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), + npt->src_pfx_len); + printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), + npt->dst_pfx_len); +} + +static struct xtables_target snpt_tg_reg = { + .name = "SNPT", + .version = XTABLES_VERSION, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)), + .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment), + .help = SNPT_help, + .x6_parse = SNPT_parse, + .print = SNPT_print, + .x6_options = SNPT_options, +}; + +void _init(void) +{ + xtables_register_target(&snpt_tg_reg); +} diff --git a/include/linux/netfilter_ipv6/ip6t_NPT.h b/include/linux/netfilter_ipv6/ip6t_NPT.h new file mode 100644 index 00000000..f7633554 --- /dev/null +++ b/include/linux/netfilter_ipv6/ip6t_NPT.h @@ -0,0 +1,16 @@ +#ifndef __NETFILTER_IP6T_NPT +#define __NETFILTER_IP6T_NPT + +#include +#include + +struct ip6t_npt_tginfo { + union nf_inet_addr src_pfx; + union nf_inet_addr dst_pfx; + __u8 src_pfx_len; + __u8 dst_pfx_len; + /* Used internally by the kernel */ + __sum16 adjustment; +}; + +#endif /* __NETFILTER_IP6T_NPT */ -- cgit v1.2.3 From 33710a5773df0e9fabdec7a2ebdd3c4e206a6a09 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 10 Sep 2012 15:04:49 +0200 Subject: build: have `make clean` remove dep files too While changing branches, one can hit errors like: make[2]: *** CC libipt_CLUSTERIP.oo No hay ninguna regla para construir el objetivo `../include/net/netfilter/nf_nat.h', necesario para `libipt_DNAT.oo'. Alto. Pablo thinks dep files should be removed on `make clean`, and I concur. (JFI, Note that native automake would not clear its ".deps" directory.) Keep the "distclean: clean" line to keep invocations by automake from the parent directory working. Reported-by: Pablo Neira Ayuso --- extensions/GNUmakefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 218dc3ad..4a8ff49d 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -77,9 +77,9 @@ install: ${targets_install} clean: rm -f *.o *.oo *.so *.a {matches,targets}[46].man initext.c initext4.c initext6.c; + rm -f .*.d .*.dd; distclean: clean - rm -f .*.d .*.dd; init%.o: init%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<; -- cgit v1.2.3 From d637ead63658d741501974c381889b3857073308 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 21 Sep 2012 20:42:15 +0200 Subject: New set match revision with --return-nomatch flag support --- extensions/libxt_set.c | 98 ++++++++++++++++++++++++++++++++++ extensions/libxt_set.man | 6 +++ include/linux/netfilter/ipset/ip_set.h | 2 + 3 files changed, 106 insertions(+) diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c index 77e3f07e..e0111568 100644 --- a/extensions/libxt_set.c +++ b/extensions/libxt_set.c @@ -205,6 +205,90 @@ set_save_v1(const void *ip, const struct xt_entry_match *match) print_match("--match-set", &info->match_set); } +/* Revision 2 */ +static void +set_help_v2(void) +{ + printf("set match options:\n" + " [!] --match-set name flags [--return-nomatch]\n" + " 'name' is the set name from to match,\n" + " 'flags' are the comma separated list of\n" + " 'src' and 'dst' specifications.\n"); +} + +static const struct option set_opts_v2[] = { + {.name = "match-set", .has_arg = true, .val = '1'}, + {.name = "set", .has_arg = true, .val = '2'}, + {.name = "return-nomatch", .has_arg = false, .val = '3'}, + XT_GETOPT_TABLEEND, +}; + +static int +set_parse_v2(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct xt_set_info_match_v1 *myinfo = + (struct xt_set_info_match_v1 *) (*match)->data; + struct xt_set_info *info = &myinfo->match_set; + + switch (c) { + case '3': + info->flags |= IPSET_RETURN_NOMATCH; + break; + case '2': + fprintf(stderr, + "--set option deprecated, please use --match-set\n"); + case '1': /* --match-set [, */ + if (info->dim) + xtables_error(PARAMETER_PROBLEM, + "--match-set can be specified only once"); + if (invert) + info->flags |= IPSET_INV_MATCH; + + if (!argv[optind] + || argv[optind][0] == '-' + || argv[optind][0] == '!') + xtables_error(PARAMETER_PROBLEM, + "--match-set requires two args."); + + if (strlen(optarg) > IPSET_MAXNAMELEN - 1) + xtables_error(PARAMETER_PROBLEM, + "setname `%s' too long, max %d characters.", + optarg, IPSET_MAXNAMELEN - 1); + + get_set_byname(optarg, info); + parse_dirs(argv[optind], info); + DEBUGP("parse: set index %u\n", info->index); + optind++; + + *flags = 1; + break; + } + + return 1; +} + +/* Prints out the matchinfo. */ +static void +set_print_v2(const void *ip, const struct xt_entry_match *match, int numeric) +{ + const struct xt_set_info_match_v1 *info = (const void *)match->data; + + print_match("match-set", &info->match_set); + if (info->match_set.flags & IPSET_RETURN_NOMATCH) + printf(" return-nomatch"); +} + +static void +set_save_v2(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_set_info_match_v1 *info = (const void *)match->data; + + print_match("--match-set", &info->match_set); + if (info->match_set.flags & IPSET_RETURN_NOMATCH) + printf(" --return-nomatch"); +} + static struct xtables_match set_mt_reg[] = { { .name = "set", @@ -234,6 +318,20 @@ static struct xtables_match set_mt_reg[] = { .save = set_save_v1, .extra_opts = set_opts_v0, }, + { + .name = "set", + .revision = 2, + .version = XTABLES_VERSION, + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), + .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), + .help = set_help_v2, + .parse = set_parse_v2, + .final_check = set_check_v0, + .print = set_print_v2, + .save = set_save_v2, + .extra_opts = set_opts_v2, + }, }; void _init(void) diff --git a/extensions/libxt_set.man b/extensions/libxt_set.man index 1ad90859..ac60f148 100644 --- a/extensions/libxt_set.man +++ b/extensions/libxt_set.man @@ -14,6 +14,12 @@ address and destination port pair can be found in the specified set. If the set type of the specified set is single dimension (for example ipmap), then the command will match packets for which the source address can be found in the specified set. +.TP +\fB\-\-return\-\-nomatch\fP +If the \fB\-\-return\-\-nomatch\fP option is specified and the set type +supports the \fBnomatch\fP flag, then the matching is reversed: a match +with an element flagged with \fBnomatch\fP returns \fBtrue\fP, while a +match with a plain element returns \fBfalse\fP. .PP The option \fB\-\-match\-set\fP can be replaced by \fB\-\-set\fP if that does not clash with an option of other extensions. diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index 79cb0779..fff191d6 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -186,6 +186,7 @@ enum ip_set_dim { * If changed, new revision of iptables match/target is required. */ IPSET_DIM_MAX = 6, + IPSET_BIT_RETURN_NOMATCH = 7, }; /* Option flags for kernel operations */ @@ -194,6 +195,7 @@ enum ip_set_kopt { IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), + IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH), }; -- cgit v1.2.3 From 954b76c317f641b7faf33cc26931d45585cc0dea Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 27 Sep 2012 21:36:35 +0200 Subject: libxtables: consolidate preference logic Alias support will require testing for more conditions, so move the revision comparison code into a separate function where it can be shared between matches and targets. Signed-off-by: Jan Engelhardt --- libxtables/xtables.c | 69 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index d8185796..7f0d3ccb 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -862,14 +862,58 @@ void xtables_register_match(struct xtables_match *me) xtables_pending_matches = me; } +/** + * Compare two actions for their preference + * @a: one action + * @b: another + * + * Like strcmp, returns a negative number if @a is less preferred than @b, + * positive number if @a is more preferred than @b, or zero if equally + * preferred. + */ +static int +xtables_mt_prefer(unsigned int a_rev, unsigned int a_fam, + unsigned int b_rev, unsigned int b_fam) +{ + /* Higher revision ranks higher. */ + if (a_rev < b_rev) + return -1; + if (a_rev > b_rev) + return 1; + + /* NFPROTO_ ranks higher than NFPROTO_UNSPEC. */ + if (a_fam == NFPROTO_UNSPEC && b_fam != NFPROTO_UNSPEC) + return -1; + if (a_fam != NFPROTO_UNSPEC && b_fam == NFPROTO_UNSPEC) + return 1; + + /* Must be the same thing. */ + return 0; +} + +static int xtables_match_prefer(const struct xtables_match *a, + const struct xtables_match *b) +{ + return xtables_mt_prefer(a->revision, a->family, + b->revision, b->family); +} + +static int xtables_target_prefer(const struct xtables_target *a, + const struct xtables_target *b) +{ + return xtables_mt_prefer(a->revision, a->family, + b->revision, b->family); +} + static void xtables_fully_register_pending_match(struct xtables_match *me) { struct xtables_match **i, *old; + int compare; old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); if (old) { - if (old->revision == me->revision && - old->family == me->family) { + compare = xtables_match_prefer(old, me); + if (compare == 0) { fprintf(stderr, "%s: match `%s' already registered.\n", xt_params->program_name, me->name); @@ -877,18 +921,14 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) } /* Now we have two (or more) options, check compatibility. */ - if (compatible_match_revision(old->name, old->revision) - && old->revision > me->revision) + if (compare > 0 && + compatible_match_revision(old->name, old->revision)) return; /* See if new match can be used. */ if (!compatible_match_revision(me->name, me->revision)) return; - /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ - if (old->revision == me->revision && me->family == AF_UNSPEC) - return; - /* Delete old one. */ for (i = &xtables_matches; *i!=old; i = &(*i)->next); *i = old->next; @@ -962,13 +1002,14 @@ void xtables_register_target(struct xtables_target *me) static void xtables_fully_register_pending_target(struct xtables_target *me) { struct xtables_target *old; + int compare; old = xtables_find_target(me->name, XTF_DURING_LOAD); if (old) { struct xtables_target **i; - if (old->revision == me->revision && - old->family == me->family) { + compare = xtables_target_prefer(old, me); + if (compare == 0) { fprintf(stderr, "%s: target `%s' already registered.\n", xt_params->program_name, me->name); @@ -976,18 +1017,14 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) } /* Now we have two (or more) options, check compatibility. */ - if (compatible_target_revision(old->name, old->revision) - && old->revision > me->revision) + if (compare > 0 && + compatible_target_revision(old->name, old->revision)) return; /* See if new target can be used. */ if (!compatible_target_revision(me->name, me->revision)) return; - /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ - if (old->revision == me->revision && me->family == AF_UNSPEC) - return; - /* Delete old one. */ for (i = &xtables_targets; *i!=old; i = &(*i)->next); *i = old->next; -- cgit v1.2.3 From cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adf Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 4 Sep 2012 05:24:47 +0200 Subject: iptables: support for target aliases This patch allows for target names listed on the command line to be rewritten to new names and revisions. As before, we will pick a revision that is supported by the kernel - now including real_name in the search. This gives us the possibility to test for many action names. Signed-off-by: Jan Engelhardt --- configure.ac | 4 ++-- include/xtables.h | 3 +++ iptables/ip6tables.c | 7 ++++++- iptables/iptables.c | 8 +++++++- libxtables/xtables.c | 32 +++++++++++++++++++++++++------- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 4060f901..adda50e4 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ AC_INIT([iptables], [1.4.15]) # See libtool.info "Libtool's versioning system" -libxtables_vcurrent=8 -libxtables_vage=1 +libxtables_vcurrent=9 +libxtables_vage=0 AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/include/xtables.h b/include/xtables.h index 3b15e67e..7bdc331c 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -282,6 +282,9 @@ struct xtables_target const char *name; + /* Real target behind this, if any. */ + const char *real_name; + /* Revision of target (0 by default). */ u_int8_t revision; diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index b191d5df..752cf033 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1286,8 +1286,13 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - strcpy(cs->target->t->u.user.name, cs->jumpto); + strcpy(cs->target->t->u.user.name, cs->target->real_name); cs->target->t->u.user.revision = cs->target->revision; + if (cs->target->real_name != cs->target->name) + fprintf(stderr, "WARNING: The %s target is obsolete. " + "Use %s instead.\n", + cs->jumpto, cs->target->real_name); + xs_init_target(cs->target); if (cs->target->x6_options != NULL) opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts, diff --git a/iptables/iptables.c b/iptables/iptables.c index 03ac63b8..a237e93c 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1295,8 +1295,14 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - strcpy(cs->target->t->u.user.name, cs->jumpto); + strcpy(cs->target->t->u.user.name, cs->target->real_name); cs->target->t->u.user.revision = cs->target->revision; + if (cs->target->real_name != cs->target->name) + /* Alias support for userspace side */ + fprintf(stderr, "WARNING: The %s target is obsolete. " + "Use %s instead.\n", + cs->jumpto, cs->target->real_name); + xs_init_target(cs->target); if (cs->target->x6_options != NULL) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 7f0d3ccb..a2b24c5a 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -872,9 +872,18 @@ void xtables_register_match(struct xtables_match *me) * preferred. */ static int -xtables_mt_prefer(unsigned int a_rev, unsigned int a_fam, - unsigned int b_rev, unsigned int b_fam) +xtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam, + bool b_alias, unsigned int b_rev, unsigned int b_fam) { + /* + * Alias ranks higher than no alias. + * (We want the new action to be used whenever possible.) + */ + if (!a_alias && b_alias) + return -1; + if (a_alias && !b_alias) + return 1; + /* Higher revision ranks higher. */ if (a_rev < b_rev) return -1; @@ -894,14 +903,21 @@ xtables_mt_prefer(unsigned int a_rev, unsigned int a_fam, static int xtables_match_prefer(const struct xtables_match *a, const struct xtables_match *b) { - return xtables_mt_prefer(a->revision, a->family, - b->revision, b->family); + return xtables_mt_prefer(false, a->revision, a->family, + false, b->revision, b->family); } static int xtables_target_prefer(const struct xtables_target *a, const struct xtables_target *b) { - return xtables_mt_prefer(a->revision, a->family, + /* + * Note that if x->real_name==NULL, it will be set to x->name in + * xtables_register_*; the direct pointer comparison here is therefore + * legitimate to detect an alias. + */ + return xtables_mt_prefer(a->name != a->real_name, + a->revision, a->family, + b->name != b->real_name, b->revision, b->family); } @@ -985,6 +1001,8 @@ void xtables_register_target(struct xtables_target *me) exit(1); } + if (me->real_name == NULL) + me->real_name = me->name; if (me->x6_options != NULL) xtables_option_metavalidate(me->name, me->x6_options); if (me->extra_opts != NULL) @@ -1018,11 +1036,11 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) /* Now we have two (or more) options, check compatibility. */ if (compare > 0 && - compatible_target_revision(old->name, old->revision)) + compatible_target_revision(old->real_name, old->revision)) return; /* See if new target can be used. */ - if (!compatible_target_revision(me->name, me->revision)) + if (!compatible_target_revision(me->real_name, me->revision)) return; /* Delete old one. */ -- cgit v1.2.3 From 50f19190a60ff7d69e88406a71a2f27e09008566 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 4 Sep 2012 05:38:48 +0200 Subject: libxt_NOTRACK: replace as an alias to CT --notrack Note that we do not need any print/save functions for the alias entries, since the real CT entry will handle this. Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 4 ++++ extensions/libxt_CT.c | 40 ++++++++++++++++++++++++++++++++++++++++ extensions/libxt_NOTRACK.c | 15 --------------- 3 files changed, 44 insertions(+), 15 deletions(-) delete mode 100644 extensions/libxt_NOTRACK.c diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 218dc3ad..b6a5cb40 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -39,6 +39,7 @@ endif # Wildcard module list # pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c))) +pfx_build_mod += NOTRACK @ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c))) @ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c))) pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod}) @@ -96,6 +97,9 @@ lib%.so: lib%.oo lib%.oo: ${srcdir}/lib%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; +libxt_NOTRACK.so: libxt_CT.so + ln -fs $< $@ + # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index 27a20e2e..a576a953 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -248,6 +248,20 @@ static void ct_save_v1(const void *ip, const struct xt_entry_target *target) printf(" --zone %u", info->zone); } +static void notrack_ct0_tg_init(struct xt_entry_target *target) +{ + struct xt_ct_target_info *info = (void *)target->data; + + info->flags = XT_CT_NOTRACK; +} + +static void notrack_ct1_tg_init(struct xt_entry_target *target) +{ + struct xt_ct_target_info_v1 *info = (void *)target->data; + + info->flags = XT_CT_NOTRACK; +} + static struct xtables_target ct_target_reg[] = { { .family = NFPROTO_UNSPEC, @@ -274,6 +288,32 @@ static struct xtables_target ct_target_reg[] = { .x6_parse = ct_parse_v1, .x6_options = ct_opts_v1, }, + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", + .real_name = "CT", + .revision = 0, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), + .userspacesize = offsetof(struct xt_ct_target_info, ct), + .init = notrack_ct0_tg_init, + }, + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", + .real_name = "CT", + .revision = 1, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), + .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), + .init = notrack_ct1_tg_init, + }, + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", + .revision = 0, + .version = XTABLES_VERSION, + }, }; void _init(void) diff --git a/extensions/libxt_NOTRACK.c b/extensions/libxt_NOTRACK.c deleted file mode 100644 index ca587002..00000000 --- a/extensions/libxt_NOTRACK.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Shared library add-on to iptables to add NOTRACK target support. */ -#include - -static struct xtables_target notrack_target = { - .family = NFPROTO_UNSPEC, - .name = "NOTRACK", - .version = XTABLES_VERSION, - .size = XT_ALIGN(0), - .userspacesize = XT_ALIGN(0), -}; - -void _init(void) -{ - xtables_register_target(¬rack_target); -} -- cgit v1.2.3 From c436dad7cfdd80ca4a05ceed556c39babc266f55 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 27 Sep 2012 23:48:25 +0200 Subject: iptables: support for match aliases This patch allows for match names listed on the command line to be rewritten to new names and revisions, like we did for targets before. Signed-off-by: Jan Engelhardt --- include/xtables.h | 1 + iptables/ip6tables.c | 6 +++++- iptables/iptables.c | 6 +++++- libxtables/xtables.c | 12 ++++++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/xtables.h b/include/xtables.h index 7bdc331c..2cc1a028 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -213,6 +213,7 @@ struct xtables_match struct xtables_match *next; const char *name; + const char *real_name; /* Revision of match (0 by default). */ u_int8_t revision; diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 752cf033..f93bfb33 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1319,8 +1319,12 @@ static void command_match(struct iptables_command_state *cs) size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); + strcpy(m->m->u.user.name, m->real_name); m->m->u.user.revision = m->revision; + if (m->real_name != m->name) + fprintf(stderr, "WARNING: The %s match is obsolete. " + "Use %s instead.\n", m->name, m->real_name); + xs_init_match(m); if (m == m->next) return; diff --git a/iptables/iptables.c b/iptables/iptables.c index a237e93c..5786bfdd 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1330,8 +1330,12 @@ static void command_match(struct iptables_command_state *cs) size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); + strcpy(m->m->u.user.name, m->real_name); m->m->u.user.revision = m->revision; + if (m->real_name != m->name) + fprintf(stderr, "WARNING: The %s match is obsolete. " + "Use %s instead.\n", m->name, m->real_name); + xs_init_match(m); if (m == m->next) return; diff --git a/libxtables/xtables.c b/libxtables/xtables.c index a2b24c5a..82c3643b 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -848,6 +848,8 @@ void xtables_register_match(struct xtables_match *me) exit(1); } + if (me->real_name == NULL) + me->real_name = me->name; if (me->x6_options != NULL) xtables_option_metavalidate(me->name, me->x6_options); if (me->extra_opts != NULL) @@ -903,8 +905,10 @@ xtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam, static int xtables_match_prefer(const struct xtables_match *a, const struct xtables_match *b) { - return xtables_mt_prefer(false, a->revision, a->family, - false, b->revision, b->family); + return xtables_mt_prefer(a->name != a->real_name, + a->revision, a->family, + b->name != b->real_name, + b->revision, b->family); } static int xtables_target_prefer(const struct xtables_target *a, @@ -938,11 +942,11 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) /* Now we have two (or more) options, check compatibility. */ if (compare > 0 && - compatible_match_revision(old->name, old->revision)) + compatible_match_revision(old->real_name, old->revision)) return; /* See if new match can be used. */ - if (!compatible_match_revision(me->name, me->revision)) + if (!compatible_match_revision(me->real_name, me->revision)) return; /* Delete old one. */ -- cgit v1.2.3 From 0d701631625898ac33fb53c67ed2b529668fe0d7 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 28 Sep 2012 00:12:42 +0200 Subject: libxt_state: replace as an alias to xt_conntrack Signed-off-by: Jan Engelhardt --- extensions/GNUmakefile.in | 4 +- extensions/libxt_conntrack.c | 191 +++++++++++++++++++++++++++++++++++++++++++ extensions/libxt_state.c | 137 ------------------------------- 3 files changed, 194 insertions(+), 138 deletions(-) delete mode 100644 extensions/libxt_state.c diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index b6a5cb40..0e7907e9 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -39,7 +39,7 @@ endif # Wildcard module list # pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c))) -pfx_build_mod += NOTRACK +pfx_build_mod += NOTRACK state @ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c))) @ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c))) pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod}) @@ -99,6 +99,8 @@ lib%.oo: ${srcdir}/lib%.c libxt_NOTRACK.so: libxt_CT.so ln -fs $< $@ +libxt_state.so: libxt_conntrack.so + ln -fs $< $@ # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD xt_RATEEST_LIBADD = -lm diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index fff69f8a..c37f14d2 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -13,7 +13,11 @@ #include #include #include +#include #include +#ifndef XT_STATE_UNTRACKED +#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) +#endif struct ip_conntrack_old_tuple { struct { @@ -1003,6 +1007,144 @@ conntrack1_mt6_save(const void *ip, const struct xt_entry_match *match) conntrack_dump(&up, "--", NFPROTO_IPV6, true, false); } +static void +state_help(void) +{ + printf( +"state match options:\n" +" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n" +" State(s) to match\n"); +} + +static const struct xt_option_entry state_opts[] = { + {.name = "state", .id = O_CTSTATE, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, +}; + +static unsigned int +state_parse_state(const char *state, size_t len) +{ + if (strncasecmp(state, "INVALID", len) == 0) + return XT_STATE_INVALID; + else if (strncasecmp(state, "NEW", len) == 0) + return XT_STATE_BIT(IP_CT_NEW); + else if (strncasecmp(state, "ESTABLISHED", len) == 0) + return XT_STATE_BIT(IP_CT_ESTABLISHED); + else if (strncasecmp(state, "RELATED", len) == 0) + return XT_STATE_BIT(IP_CT_RELATED); + else if (strncasecmp(state, "UNTRACKED", len) == 0) + return XT_STATE_UNTRACKED; + return 0; +} + +static unsigned int +state_parse_states(const char *arg) +{ + const char *comma; + unsigned int mask = 0, flag; + + while ((comma = strchr(arg, ',')) != NULL) { + if (comma == arg) + goto badstate; + flag = state_parse_state(arg, comma-arg); + if (flag == 0) + goto badstate; + mask |= flag; + arg = comma+1; + } + if (!*arg) + xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of " + "states with no spaces, e.g. " + "ESTABLISHED,RELATED"); + if (strlen(arg) == 0) + goto badstate; + flag = state_parse_state(arg, strlen(arg)); + if (flag == 0) + goto badstate; + mask |= flag; + return mask; + badstate: + xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); +} + +static void state_parse(struct xt_option_call *cb) +{ + struct xt_state_info *sinfo = cb->data; + + xtables_option_parse(cb); + sinfo->statemask = state_parse_states(cb->arg); + if (cb->invert) + sinfo->statemask = ~sinfo->statemask; +} + +static void state_ct1_parse(struct xt_option_call *cb) +{ + struct xt_conntrack_mtinfo1 *sinfo = cb->data; + + xtables_option_parse(cb); + sinfo->match_flags = XT_CONNTRACK_STATE; + sinfo->state_mask = state_parse_states(cb->arg); + if (cb->invert) + sinfo->invert_flags |= XT_CONNTRACK_STATE; +} + +static void state_ct23_parse(struct xt_option_call *cb) +{ + struct xt_conntrack_mtinfo3 *sinfo = cb->data; + + xtables_option_parse(cb); + sinfo->match_flags = XT_CONNTRACK_STATE; + sinfo->state_mask = state_parse_states(cb->arg); + if (cb->invert) + sinfo->invert_flags |= XT_CONNTRACK_STATE; +} + +static void state_print_state(unsigned int statemask) +{ + const char *sep = ""; + + if (statemask & XT_STATE_INVALID) { + printf("%sINVALID", sep); + sep = ","; + } + if (statemask & XT_STATE_BIT(IP_CT_NEW)) { + printf("%sNEW", sep); + sep = ","; + } + if (statemask & XT_STATE_BIT(IP_CT_RELATED)) { + printf("%sRELATED", sep); + sep = ","; + } + if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) { + printf("%sESTABLISHED", sep); + sep = ","; + } + if (statemask & XT_STATE_UNTRACKED) { + printf("%sUNTRACKED", sep); + sep = ","; + } +} + +static void +state_print(const void *ip, + const struct xt_entry_match *match, + int numeric) +{ + const struct xt_state_info *sinfo = (const void *)match->data; + + printf(" state "); + state_print_state(sinfo->statemask); +} + +static void state_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_state_info *sinfo = (const void *)match->data; + + printf(" --state "); + state_print_state(sinfo->statemask); +} + static struct xtables_match conntrack_mt_reg[] = { { .version = XTABLES_VERSION, @@ -1102,6 +1244,55 @@ static struct xtables_match conntrack_mt_reg[] = { .save = conntrack3_mt6_save, .x6_options = conntrack3_mt_opts, }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .real_name = "conntrack", + .revision = 1, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), + .help = state_help, + .x6_parse = state_ct1_parse, + .x6_options = state_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .real_name = "conntrack", + .revision = 2, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), + .help = state_help, + .x6_parse = state_ct23_parse, + .x6_options = state_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .real_name = "conntrack", + .revision = 3, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .help = state_help, + .x6_parse = state_ct23_parse, + .x6_options = state_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .revision = 0, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_state_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)), + .help = state_help, + .print = state_print, + .save = state_save, + .x6_parse = state_parse, + .x6_options = state_opts, + }, }; void _init(void) diff --git a/extensions/libxt_state.c b/extensions/libxt_state.c deleted file mode 100644 index eff444c8..00000000 --- a/extensions/libxt_state.c +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include -#include -#include -#include - -#ifndef XT_STATE_UNTRACKED -#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) -#endif - -enum { - O_STATE = 0, -}; - -static void -state_help(void) -{ - printf( -"state match options:\n" -" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n" -" State(s) to match\n"); -} - -static const struct xt_option_entry state_opts[] = { - {.name = "state", .id = O_STATE, .type = XTTYPE_STRING, - .flags = XTOPT_MAND | XTOPT_INVERT}, - XTOPT_TABLEEND, -}; - -static int -state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo) -{ - if (strncasecmp(state, "INVALID", len) == 0) - sinfo->statemask |= XT_STATE_INVALID; - else if (strncasecmp(state, "NEW", len) == 0) - sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW); - else if (strncasecmp(state, "ESTABLISHED", len) == 0) - sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED); - else if (strncasecmp(state, "RELATED", len) == 0) - sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED); - else if (strncasecmp(state, "UNTRACKED", len) == 0) - sinfo->statemask |= XT_STATE_UNTRACKED; - else - return 0; - return 1; -} - -static void -state_parse_states(const char *arg, struct xt_state_info *sinfo) -{ - const char *comma; - - while ((comma = strchr(arg, ',')) != NULL) { - if (comma == arg || !state_parse_state(arg, comma-arg, sinfo)) - xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); - arg = comma+1; - } - if (!*arg) - xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of " - "states with no spaces, e.g. " - "ESTABLISHED,RELATED"); - if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo)) - xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); -} - -static void state_parse(struct xt_option_call *cb) -{ - struct xt_state_info *sinfo = cb->data; - - xtables_option_parse(cb); - state_parse_states(cb->arg, sinfo); - if (cb->invert) - sinfo->statemask = ~sinfo->statemask; -} - -static void state_print_state(unsigned int statemask) -{ - const char *sep = ""; - - if (statemask & XT_STATE_INVALID) { - printf("%sINVALID", sep); - sep = ","; - } - if (statemask & XT_STATE_BIT(IP_CT_NEW)) { - printf("%sNEW", sep); - sep = ","; - } - if (statemask & XT_STATE_BIT(IP_CT_RELATED)) { - printf("%sRELATED", sep); - sep = ","; - } - if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) { - printf("%sESTABLISHED", sep); - sep = ","; - } - if (statemask & XT_STATE_UNTRACKED) { - printf("%sUNTRACKED", sep); - sep = ","; - } -} - -static void -state_print(const void *ip, - const struct xt_entry_match *match, - int numeric) -{ - const struct xt_state_info *sinfo = (const void *)match->data; - - printf(" state "); - state_print_state(sinfo->statemask); -} - -static void state_save(const void *ip, const struct xt_entry_match *match) -{ - const struct xt_state_info *sinfo = (const void *)match->data; - - printf(" --state "); - state_print_state(sinfo->statemask); -} - -static struct xtables_match state_match = { - .family = NFPROTO_UNSPEC, - .name = "state", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_state_info)), - .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)), - .help = state_help, - .print = state_print, - .save = state_save, - .x6_parse = state_parse, - .x6_options = state_opts, -}; - -void _init(void) -{ - xtables_register_match(&state_match); -} -- cgit v1.2.3 From 9517bbf5b805df874dcc452dfeb2cc36a7bf1500 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 28 Sep 2012 09:57:56 +0200 Subject: doc: clean up interpunction in state list for xt_conntrack Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.man | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/libxt_conntrack.man b/extensions/libxt_conntrack.man index c397f742..c0cd24fe 100644 --- a/extensions/libxt_conntrack.man +++ b/extensions/libxt_conntrack.man @@ -42,22 +42,22 @@ specified at all, matches packets in both directions. States for \fB\-\-ctstate\fP: .TP \fBINVALID\fP -meaning that the packet is associated with no known connection +The packet is associated with no known connection. .TP \fBNEW\fP -meaning that the packet has started a new connection, or otherwise associated -with a connection which has not seen packets in both directions, and +The packet has started a new connection, or otherwise associated +with a connection which has not seen packets in both directions. .TP \fBESTABLISHED\fP -meaning that the packet is associated with a connection which has seen packets -in both directions, +The packet is associated with a connection which has seen packets +in both directions. .TP \fBRELATED\fP -meaning that the packet is starting a new connection, but is associated with an +The packet is starting a new connection, but is associated with an existing connection, such as an FTP data transfer, or an ICMP error. .TP \fBUNTRACKED\fP -meaning that the packet is not tracked at all, which happens if you use +The packet is not tracked at all, which happens if you use the NOTRACK target in raw table. .TP \fBSNAT\fP @@ -74,7 +74,7 @@ Statuses for \fB\-\-ctstatus\fP: None of the below. .TP \fBEXPECTED\fP -This is an expected connection (i.e. a conntrack helper set it up) +This is an expected connection (i.e. a conntrack helper set it up). .TP \fBSEEN_REPLY\fP Conntrack has seen packets in both directions. -- cgit v1.2.3 From 4496801821c01e3934996b40e0012ddcb969a8df Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 28 Sep 2012 10:43:06 +0200 Subject: doc: deduplicate extension descriptions into a new manpage iptables.8 and ip6tables.8 had pretty much the same content, with a few protocol-specific deviations here and there. Not only did that bloat the manpages, but it also made it harder to spot differences. Separate out the extension descriptions into a new manpage, which conveniently features differences next to one another (cf. REJECT). Signed-off-by: Jan Engelhardt --- extensions/.gitignore | 4 ++-- extensions/GNUmakefile.in | 35 +++++++++++++++-------------------- iptables/.gitignore | 1 + iptables/Makefile.am | 16 +++++++++++----- iptables/ip6tables.8.in | 20 +++----------------- iptables/iptables-extensions.8.in | 27 +++++++++++++++++++++++++++ iptables/iptables.8.in | 22 ++++------------------ 7 files changed, 63 insertions(+), 62 deletions(-) create mode 100644 iptables/iptables-extensions.8.in diff --git a/extensions/.gitignore b/extensions/.gitignore index 2e74faf7..b1260f0b 100644 --- a/extensions/.gitignore +++ b/extensions/.gitignore @@ -5,5 +5,5 @@ /GNUmakefile /initext.c /initext?.c -/matches?.man -/targets?.man +/matches.man +/targets.man diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 0e7907e9..2e0921e4 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -56,9 +56,7 @@ pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod}) # # Building blocks # -targets := libext.a libext4.a libext6.a \ - matches4.man matches6.man \ - targets4.man targets6.man +targets := libext.a libext4.a libext6.a matches.man targets.man targets_install := @ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs} @ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs} @@ -77,7 +75,7 @@ install: ${targets_install} if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi; clean: - rm -f *.o *.oo *.so *.a {matches,targets}[46].man initext.c initext4.c initext6.c; + rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c; distclean: clean rm -f .*.d .*.dd; @@ -202,30 +200,27 @@ man_run = \ ${AM_VERBOSE_GEN} \ for ext in $(sort ${1}); do \ f="${srcdir}/libxt_$$ext.man"; \ - cf="${srcdir}/libxt_$$ext.c"; \ - if [ -f "$$f" ] && grep -Eq "$(3)|NFPROTO_UNSPEC" "$$cf"; then \ + if [ -f "$$f" ]; then \ echo -e "\t+ $$f" >&2; \ echo ".SS $$ext"; \ cat "$$f" || exit $$?; \ - continue; \ fi; \ - f="${srcdir}/lib$(2)t_$$ext.man"; \ + f="${srcdir}/libip6t_$$ext.man"; \ if [ -f "$$f" ]; then \ echo -e "\t+ $$f" >&2; \ - echo ".SS $$ext"; \ + echo ".SS $$ext (IPv6-specific)"; \ + cat "$$f" || exit $$?; \ + fi; \ + f="${srcdir}/libipt_$$ext.man"; \ + if [ -f "$$f" ]; then \ + echo -e "\t+ $$f" >&2; \ + echo ".SS $$ext (IPv4-specific)"; \ cat "$$f" || exit $$?; \ - continue; \ fi; \ done >$@; -matches4.man: .initext.dd .initext4.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4) - -matches6.man: .initext.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6) - -targets4.man: .initext.dd .initext4.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4) +matches.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) + $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod})) -targets6.man: .initext.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6) +targets.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) + $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod})) diff --git a/iptables/.gitignore b/iptables/.gitignore index 5a089376..4fc63aa4 100644 --- a/iptables/.gitignore +++ b/iptables/.gitignore @@ -5,6 +5,7 @@ /ip6tables-static /iptables /iptables.8 +/iptables-extensions.8 /iptables-save /iptables-restore /iptables-static diff --git a/iptables/Makefile.am b/iptables/Makefile.am index bdd4da11..61e78db9 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -27,7 +27,7 @@ xtables_multi_LDADD += ../libxtables/libxtables.la -lm sbin_PROGRAMS = xtables-multi man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \ iptables-xml.1 ip6tables.8 ip6tables-restore.8 \ - ip6tables-save.8 + ip6tables-save.8 iptables-extensions.8 CLEANFILES = iptables.8 ip6tables.8 vx_bin_links = iptables-xml @@ -38,11 +38,17 @@ if ENABLE_IPV6 v6_sbin_links = ip6tables ip6tables-restore ip6tables-save endif -iptables.8: ${srcdir}/iptables.8.in ../extensions/matches4.man ../extensions/targets4.man - ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches4.man' -e '/@TARGET@/ r ../extensions/targets4.man' $< >$@; +iptables.8: ${srcdir}/iptables.8.in + ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@; -ip6tables.8: ${srcdir}/ip6tables.8.in ../extensions/matches6.man ../extensions/targets6.man - ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches6.man' -e '/@TARGET@/ r ../extensions/targets6.man' $< >$@; +ip6tables.8: ${srcdir}/ip6tables.8.in + ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@; + +iptables-extensions.8: ${srcdir}/iptables-extensions.8.in ../extensions/matches.man ../extensions/targets.man + ${AM_VERBOSE_GEN} sed -e \ + 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' \ + -e '/@MATCH@/ r ../extensions/matches.man' \ + -e '/@TARGET@/ r ../extensions/targets.man' $< >$@; pkgconfig_DATA = xtables.pc diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 65f38646..edd092d7 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -362,23 +362,8 @@ When adding or inserting rules into a chain, use \fIcommand\fP to load any necessary modules (targets, match extensions, etc). .SH MATCH EXTENSIONS .PP -ip6tables can use extended packet matching modules -with the \fB\-m\fP or \fB\-\-match\fP -options, followed by the matching module name; after these, various -extra command line options become available, depending on the specific -module. You can specify multiple extended match modules in one line, -and you can use the \fB\-h\fP or \fB\-\-help\fP -options after the module has been specified to receive help specific -to that module. -.PP -If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an -unknown option is encountered, ip6tables will try load a match module of the -same name as the protocol, to try making the option available. -.\" @MATCH@ -.SH TARGET EXTENSIONS -ip6tables can use extended target modules: the following are included -in the standard distribution. -.\" @TARGET@ +iptables can use extended packet matching and target modules. +A list of these is available in the \fBiptables\-extensions\fP(8) manpage. .SH DIAGNOSTICS Various error messages are printed to standard error. The exit code is 0 for correct functioning. Errors which appear to be caused by @@ -405,6 +390,7 @@ There are several other changes in ip6tables. \fBip6tables\-save\fP(8), \fBip6tables\-restore\fP(8), \fBiptables\fP(8), +\fBiptables\-extensions\fP(8), \fBiptables\-save\fP(8), \fBiptables\-restore\fP(8), \fBlibipq\fP(3). diff --git a/iptables/iptables-extensions.8.in b/iptables/iptables-extensions.8.in new file mode 100644 index 00000000..e02c81fb --- /dev/null +++ b/iptables/iptables-extensions.8.in @@ -0,0 +1,27 @@ +.TH iptables-extensions 8 "" "@PACKAGE_AND_VERSION@" "@PACKAGE_AND_VERSION@" +.SH NAME +iptables-extensions \(em list of extensions in the standard iptables distribution +.SH SYNOPSIS +\fBip6tables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]] +[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...] +.PP +\fBiptables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]] +[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...] +.SH MATCH EXTENSIONS +iptables can use extended packet matching modules +with the \fB\-m\fP or \fB\-\-match\fP +options, followed by the matching module name; after these, various +extra command line options become available, depending on the specific +module. You can specify multiple extended match modules in one line, +and you can use the \fB\-h\fP or \fB\-\-help\fP +options after the module has been specified to receive help specific +to that module. +.PP +If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an +unknown option is encountered, iptables will try load a match module of the +same name as the protocol, to try making the option available. +.\" @MATCH@ +.SH TARGET EXTENSIONS +iptables can use extended target modules: the following are included +in the standard distribution. +.\" @TARGET@ diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 59d6e040..48eb2fa1 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -355,25 +355,10 @@ corresponding to that rule's position in the chain. \fB\-\-modprobe=\fP\fIcommand\fP When adding or inserting rules into a chain, use \fIcommand\fP to load any necessary modules (targets, match extensions, etc). -.SH MATCH EXTENSIONS +.SH MATCH AND TARGET EXTENSIONS .PP -iptables can use extended packet matching modules -with the \fB\-m\fP or \fB\-\-match\fP -options, followed by the matching module name; after these, various -extra command line options become available, depending on the specific -module. You can specify multiple extended match modules in one line, -and you can use the \fB\-h\fP or \fB\-\-help\fP -options after the module has been specified to receive help specific -to that module. -.PP -If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an -unknown option is encountered, iptables will try load a match module of the -same name as the protocol, to try making the option available. -.\" @MATCH@ -.SH TARGET EXTENSIONS -iptables can use extended target modules: the following are included -in the standard distribution. -.\" @TARGET@ +iptables can use extended packet matching and target modules. +A list of these is available in the \fBiptables\-extensions\fP(8) manpage. .SH DIAGNOSTICS Various error messages are printed to standard error. The exit code is 0 for correct functioning. Errors which appear to be caused by @@ -410,6 +395,7 @@ There are several other changes in iptables. .SH SEE ALSO \fBiptables\-save\fP(8), \fBiptables\-restore\fP(8), +\fBiptables\-extensions\fP(8), \fBip6tables\fP(8), \fBip6tables\-save\fP(8), \fBip6tables\-restore\fP(8), -- cgit v1.2.3 From faeaf11536f605ebb733d4d5f5ec2ca074d3f247 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 28 Sep 2012 10:52:32 +0200 Subject: doc: trim "state" manpage and reference conntrack instead The module is practically obsolete, so just pinpoint to the replacement in short order. Signed-off-by: Jan Engelhardt --- extensions/libxt_HMARK.man | 2 +- extensions/libxt_state.man | 28 ++++++---------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man index 0b418842..e7b5426d 100644 --- a/extensions/libxt_HMARK.man +++ b/extensions/libxt_HMARK.man @@ -52,7 +52,7 @@ A 32 bit random custom value to feed hash calculation. .PP \fIExamples:\fP .PP -iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW +iptables \-t mangle \-A PREROUTING \-m conntrack \-\-ctstate NEW \-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark-offset 10000 \-\-hmark\-mod 10 \-\-hmark\-rnd 0xfeedcafe .PP diff --git a/extensions/libxt_state.man b/extensions/libxt_state.man index 37d095bc..bd60468f 100644 --- a/extensions/libxt_state.man +++ b/extensions/libxt_state.man @@ -1,24 +1,8 @@ -This module, when combined with connection tracking, allows access to -the connection tracking state for this packet. +The "state" module is an obsolete version of "conntrack". +"state" allows access to the connection tracking state for this packet. .TP [\fB!\fP] \fB\-\-state\fP \fIstate\fP -Where state is a comma separated list of the connection states to -match. Possible states are -.B INVALID -meaning that the packet could not be identified for some reason which -includes running out of memory and ICMP errors which don't correspond to any -known connection, -.B ESTABLISHED -meaning that the packet is associated with a connection which has seen -packets in both directions, -.B NEW -meaning that the packet has started a new connection, or otherwise -associated with a connection which has not seen packets in both -directions, and -.B RELATED -meaning that the packet is starting a new connection, but is -associated with an existing connection, such as an FTP data transfer, -or an ICMP error. -.B UNTRACKED -meaning that the packet is not tracked at all, which happens if you use -the NOTRACK target in raw table. +Where state is a comma separated list of the connection states to match. Only a +subset of the states unterstood by "conntrack" are recognized: \fBINVALID\fP, +\fBESTABLISHED\fP, \fBNEW\fP, \fBRELATED\fP or \fBUNTRACKED\fP. For their +description, see the "conntrack" heading in this manpage. -- cgit v1.2.3 From d97d546ba4540a28b14fcbf75176df345caee954 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 28 Sep 2012 10:54:47 +0200 Subject: doc: have NOTRACK manpage point to CT instead The module is obsolete, so point to CT --notrack instead. Signed-off-by: Jan Engelhardt --- extensions/libxt_NOTRACK.man | 6 ++---- extensions/libxt_conntrack.man | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/extensions/libxt_NOTRACK.man b/extensions/libxt_NOTRACK.man index c2cdf5a6..633b965e 100644 --- a/extensions/libxt_NOTRACK.man +++ b/extensions/libxt_NOTRACK.man @@ -1,5 +1,3 @@ This target disables connection tracking for all packets matching that rule. -.PP -It can only be used in the -.B raw -table. +It is obsoleted by \-j CT \-\-notrack. Like CT, NOTRACK can only be used in +the \fBraw\fP table. diff --git a/extensions/libxt_conntrack.man b/extensions/libxt_conntrack.man index c0cd24fe..15fd1ddf 100644 --- a/extensions/libxt_conntrack.man +++ b/extensions/libxt_conntrack.man @@ -57,8 +57,8 @@ The packet is starting a new connection, but is associated with an existing connection, such as an FTP data transfer, or an ICMP error. .TP \fBUNTRACKED\fP -The packet is not tracked at all, which happens if you use -the NOTRACK target in raw table. +The packet is not tracked at all, which happens if you explicitly untrack it +by using \-j CT \-\-notrack in the raw table. .TP \fBSNAT\fP A virtual state, matching if the original source address differs from the reply -- cgit v1.2.3 From 7b5ba43ae48c1310e5a615cf9485c1d42f486467 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 28 Sep 2012 10:57:45 +0200 Subject: doc: mention iptables-apply in the SEE ALSO sections References: http://bugs.debian.org/660748 Signed-off-by: Jan Engelhardt --- iptables/ip6tables.8.in | 1 + iptables/iptables-apply.8 | 2 +- iptables/iptables.8.in | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index edd092d7..078bcacd 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -390,6 +390,7 @@ There are several other changes in ip6tables. \fBip6tables\-save\fP(8), \fBip6tables\-restore\fP(8), \fBiptables\fP(8), +\fBiptables\-apply\fP(8), \fBiptables\-extensions\fP(8), \fBiptables\-save\fP(8), \fBiptables\-restore\fP(8), diff --git a/iptables/iptables-apply.8 b/iptables/iptables-apply.8 index 8208fd0f..66eaf57a 100644 --- a/iptables/iptables-apply.8 +++ b/iptables/iptables-apply.8 @@ -18,7 +18,7 @@ connection, the user will not be able to answer affirmatively. In this case, the script rolls back to the previous ruleset after the timeout expired. The timeout can be set with \fB\-t\fP. .PP -When called as ip6tables\-apply, the script will use +When called as \fBip6tables\-apply\fP, the script will use ip6tables\-save/\-restore instead. .SH OPTIONS .TP diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 48eb2fa1..d6b409d0 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -393,6 +393,7 @@ seen previously. So the following options are handled differently: .fi There are several other changes in iptables. .SH SEE ALSO +\fBiptables\-apply\fP(8), \fBiptables\-save\fP(8), \fBiptables\-restore\fP(8), \fBiptables\-extensions\fP(8), -- cgit v1.2.3 From 8d8896a3833292d091ee5a028f3461083bb956bd Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 17 Sep 2012 00:23:08 +0000 Subject: libxt_time: add support to ignore day transition Currently, if you want to do something like: "match Monday, starting 23:00, for two hours" You need two rules, one for Mon 23:00 to 0:00 and one for Tue 0:00-1:00. The rule --weekdays Mo --timestart 23:00 --timestop 01:00 looks correct, but it will first match on monday from midnight to 1 a.m. and then again for another hour from 23:00 onwards. This permits userspace to explicitly ignore the day transition and match for a single, continuous time period instead. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_time.c | 20 ++++++++++++++++++++ extensions/libxt_time.man | 12 ++++++++++++ include/linux/netfilter/xt_time.h | 1 + 3 files changed, 33 insertions(+) diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c index 44c05b8f..9c5bda88 100644 --- a/extensions/libxt_time.c +++ b/extensions/libxt_time.c @@ -22,6 +22,7 @@ enum { O_DATE_STOP, O_TIME_START, O_TIME_STOP, + O_TIME_CONTIGUOUS, O_MONTHDAYS, O_WEEKDAYS, O_LOCAL_TZ, @@ -30,6 +31,7 @@ enum { F_LOCAL_TZ = 1 << O_LOCAL_TZ, F_UTC = 1 << O_UTC, F_KERNEL_TZ = 1 << O_KERNEL_TZ, + F_TIME_CONTIGUOUS = 1 << O_TIME_CONTIGUOUS, }; static const char *const week_days[] = { @@ -41,6 +43,7 @@ static const struct xt_option_entry time_opts[] = { {.name = "datestop", .id = O_DATE_STOP, .type = XTTYPE_STRING}, {.name = "timestart", .id = O_TIME_START, .type = XTTYPE_STRING}, {.name = "timestop", .id = O_TIME_STOP, .type = XTTYPE_STRING}, + {.name = "contiguous", .id = O_TIME_CONTIGUOUS, .type = XTTYPE_NONE}, {.name = "weekdays", .id = O_WEEKDAYS, .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, {.name = "monthdays", .id = O_MONTHDAYS, .type = XTTYPE_STRING, @@ -273,6 +276,9 @@ static void time_parse(struct xt_option_call *cb) case O_TIME_STOP: info->daytime_stop = time_parse_minutes(cb->arg); break; + case O_TIME_CONTIGUOUS: + info->flags |= XT_TIME_CONTIGUOUS; + break; case O_LOCAL_TZ: fprintf(stderr, "WARNING: --localtz is being replaced by " "--kerneltz, since \"local\" is ambiguous. Note the " @@ -403,6 +409,8 @@ static void time_print(const void *ip, const struct xt_entry_match *match, } if (!(info->flags & XT_TIME_LOCAL_TZ)) printf(" UTC"); + if (info->flags & XT_TIME_CONTIGUOUS) + printf(" contiguous"); } static void time_save(const void *ip, const struct xt_entry_match *match) @@ -429,6 +437,17 @@ static void time_save(const void *ip, const struct xt_entry_match *match) time_print_date(info->date_stop, "--datestop"); if (info->flags & XT_TIME_LOCAL_TZ) printf(" --kerneltz"); + if (info->flags & XT_TIME_CONTIGUOUS) + printf(" --contiguous"); +} + +static void time_check(struct xt_fcheck_call *cb) +{ + const struct xt_time_info *info = (const void *) cb->data; + if ((cb->xflags & F_TIME_CONTIGUOUS) && + info->daytime_start < info->daytime_stop) + xtables_error(PARAMETER_PROBLEM, + "time: --contiguous only makes sense when stoptime is smaller than starttime"); } static struct xtables_match time_match = { @@ -442,6 +461,7 @@ static struct xtables_match time_match = { .print = time_print, .save = time_save, .x6_parse = time_parse, + .x6_fcheck = time_check, .x6_options = time_opts, }; diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man index 1d677b94..4c0cae06 100644 --- a/extensions/libxt_time.man +++ b/extensions/libxt_time.man @@ -30,6 +30,10 @@ Only match on the given weekdays. Possible values are \fBMon\fP, \fBTue\fP, to \fB7\fP, respectively. You may also use two-character variants (\fBMo\fP, \fBTu\fP, etc.). .TP +\fB\-\-contiguous\fP +When \fB\-\-timestop\fP is smaller than \fB\-\-timestart\fP value, match +this as a single time period instead distinct intervals. See EXAMPLES. +.TP \fB\-\-kerneltz\fP Use the kernel timezone instead of UTC to determine whether a packet meets the time regulations. @@ -84,3 +88,11 @@ The fourth Friday in the month: (Note that this exploits a certain mathematical property. It is not possible to say "fourth Thursday OR fourth Friday" in one rule. It is possible with multiple rules, though.) +.PP +Matching across days might not do what is expected. For instance, +.IP +\-m time \-\-weekdays Mo \-\-timestart 23:00 \-\-timestop 01:00 +Will match Monday, for one hour from midnight to 1 a.m., and then +again for another hour from 23:00 onwards. If this is unwanted, e.g. if you +would like 'match for two hours from Montay 23:00 onwards' you need to also specify +the \-\-contiguous option in the example above. diff --git a/include/linux/netfilter/xt_time.h b/include/linux/netfilter/xt_time.h index 7c37fac5..a21d5bf8 100644 --- a/include/linux/netfilter/xt_time.h +++ b/include/linux/netfilter/xt_time.h @@ -16,6 +16,7 @@ struct xt_time_info { enum { /* Match against local time (instead of UTC) */ XT_TIME_LOCAL_TZ = 1 << 0, + XT_TIME_CONTIGUOUS = 1 << 1, /* Shortcuts */ XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE, -- cgit v1.2.3 From 3fdf783ec78e7a7bffb2cd48d5bc6b3264b00dd2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 7 Oct 2012 23:56:43 +0200 Subject: bump version to 1.4.16 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index adda50e4..67bcd72b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.15]) +AC_INIT([iptables], [1.4.16]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=9 -- cgit v1.2.3 From 2aaa7ec29059027756f076c4767b4fa034ebd166 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 8 Oct 2012 00:55:43 +0200 Subject: iptables: fix standard target This regression was added by: commit cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adf Author: Jan Engelhardt Date: Tue Sep 4 05:24:47 2012 +0200 iptables: support for target aliase The result is that: iptables -I INPUT -j ACCEPT says: iptables: No chain/target/match by that name. This also breaks iptables-restore, of course. Jan, you'll have to explain me how you have tested this. Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.c | 5 ++++- iptables/iptables.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 36612161..faddb71b 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1286,7 +1286,10 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - strcpy(cs->target->t->u.user.name, cs->target->real_name); + if (cs->target->real_name != NULL) + strcpy(cs->target->t->u.user.name, cs->jumpto); + else + strcpy(cs->target->t->u.user.name, cs->target->real_name); cs->target->t->u.user.revision = cs->target->revision; if (cs->target->real_name != cs->target->name) fprintf(stderr, "WARNING: The %s target is obsolete. " diff --git a/iptables/iptables.c b/iptables/iptables.c index e935f651..96cea64d 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1295,7 +1295,10 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - strcpy(cs->target->t->u.user.name, cs->target->real_name); + if (cs->target->real_name != NULL) + strcpy(cs->target->t->u.user.name, cs->jumpto); + else + strcpy(cs->target->t->u.user.name, cs->target->real_name); cs->target->t->u.user.revision = cs->target->revision; if (cs->target->real_name != cs->target->name) /* Alias support for userspace side */ -- cgit v1.2.3 From 4bdc1edf49dedd20519f2eaea95466400f627dd5 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 8 Oct 2012 00:59:40 +0200 Subject: bump version to 1.4.16.1 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 67bcd72b..50729505 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.16]) +AC_INIT([iptables], [1.4.16.1]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=9 -- cgit v1.2.3 From dd43527cb6bdf3d469100850ca10dcd2fb761304 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 7 Oct 2012 14:32:36 +0000 Subject: iptables: restore NOTRACK functionality, target aliasing Commit v1.4.16-1-g2aaa7ec is testing for real_name (not) being NULL which was always false (true). real_name was never NULL, so cs->jumpto would always be used, which rendered -j NOTRACK unusable, since the chosen real name.revision is for example NOTRACK.1, which does not exist at the kernel side. # ./iptables/xtables-multi main4 -t raw -A foo -j NOTRACK dbg: Using NOTRACK.1 WARNING: The NOTRACK target is obsolete. Use CT instead. iptables: Protocol wrong type for socket. To reasonably support the extra-special verdict names, make it so that real_name remains NULL when an extension defined no alias, which we can then use to determine whether the user entered an alias name (which needs to be followed) or not. [ I have mangled this patch to remove a comment unnecessarily large. BTW, this patch gets this very close to the initial target aliasing proposal --pablo ] Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.c | 17 ++++++++++------- iptables/iptables.c | 19 +++++++++++-------- libxtables/xtables.c | 26 ++++++++++++++------------ 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index faddb71b..0e11a9e1 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1286,15 +1286,15 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - if (cs->target->real_name != NULL) + if (cs->target->real_name == NULL) { strcpy(cs->target->t->u.user.name, cs->jumpto); - else + } else { strcpy(cs->target->t->u.user.name, cs->target->real_name); - cs->target->t->u.user.revision = cs->target->revision; - if (cs->target->real_name != cs->target->name) fprintf(stderr, "WARNING: The %s target is obsolete. " "Use %s instead.\n", cs->jumpto, cs->target->real_name); + } + cs->target->t->u.user.revision = cs->target->revision; xs_init_target(cs->target); if (cs->target->x6_options != NULL) @@ -1322,11 +1322,14 @@ static void command_match(struct iptables_command_state *cs) size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->real_name); - m->m->u.user.revision = m->revision; - if (m->real_name != m->name) + if (m->real_name == NULL) { + strcpy(m->m->u.user.name, m->name); + } else { + strcpy(m->m->u.user.name, m->real_name); fprintf(stderr, "WARNING: The %s match is obsolete. " "Use %s instead.\n", m->name, m->real_name); + } + m->m->u.user.revision = m->revision; xs_init_match(m); if (m == m->next) diff --git a/iptables/iptables.c b/iptables/iptables.c index 96cea64d..f765cf98 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1295,16 +1295,16 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - if (cs->target->real_name != NULL) + if (cs->target->real_name == NULL) { strcpy(cs->target->t->u.user.name, cs->jumpto); - else - strcpy(cs->target->t->u.user.name, cs->target->real_name); - cs->target->t->u.user.revision = cs->target->revision; - if (cs->target->real_name != cs->target->name) + } else { /* Alias support for userspace side */ + strcpy(cs->target->t->u.user.name, cs->target->real_name); fprintf(stderr, "WARNING: The %s target is obsolete. " "Use %s instead.\n", cs->jumpto, cs->target->real_name); + } + cs->target->t->u.user.revision = cs->target->revision; xs_init_target(cs->target); @@ -1333,11 +1333,14 @@ static void command_match(struct iptables_command_state *cs) size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->real_name); - m->m->u.user.revision = m->revision; - if (m->real_name != m->name) + if (m->real_name == NULL) { + strcpy(m->m->u.user.name, m->name); + } else { + strcpy(m->m->u.user.name, m->real_name); fprintf(stderr, "WARNING: The %s match is obsolete. " "Use %s instead.\n", m->name, m->real_name); + } + m->m->u.user.revision = m->revision; xs_init_match(m); if (m == m->next) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 82c3643b..4c912860 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -848,8 +848,6 @@ void xtables_register_match(struct xtables_match *me) exit(1); } - if (me->real_name == NULL) - me->real_name = me->name; if (me->x6_options != NULL) xtables_option_metavalidate(me->name, me->x6_options); if (me->extra_opts != NULL) @@ -905,9 +903,9 @@ xtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam, static int xtables_match_prefer(const struct xtables_match *a, const struct xtables_match *b) { - return xtables_mt_prefer(a->name != a->real_name, + return xtables_mt_prefer(a->real_name != NULL, a->revision, a->family, - b->name != b->real_name, + b->real_name != NULL, b->revision, b->family); } @@ -919,15 +917,16 @@ static int xtables_target_prefer(const struct xtables_target *a, * xtables_register_*; the direct pointer comparison here is therefore * legitimate to detect an alias. */ - return xtables_mt_prefer(a->name != a->real_name, + return xtables_mt_prefer(a->real_name != NULL, a->revision, a->family, - b->name != b->real_name, + b->real_name != NULL, b->revision, b->family); } static void xtables_fully_register_pending_match(struct xtables_match *me) { struct xtables_match **i, *old; + const char *rn; int compare; old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); @@ -941,12 +940,14 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) } /* Now we have two (or more) options, check compatibility. */ + rn = (old->real_name != NULL) ? old->real_name : old->name; if (compare > 0 && - compatible_match_revision(old->real_name, old->revision)) + compatible_match_revision(rn, old->revision)) return; /* See if new match can be used. */ - if (!compatible_match_revision(me->real_name, me->revision)) + rn = (me->real_name != NULL) ? me->real_name : me->name; + if (!compatible_match_revision(rn, me->revision)) return; /* Delete old one. */ @@ -1005,8 +1006,6 @@ void xtables_register_target(struct xtables_target *me) exit(1); } - if (me->real_name == NULL) - me->real_name = me->name; if (me->x6_options != NULL) xtables_option_metavalidate(me->name, me->x6_options); if (me->extra_opts != NULL) @@ -1024,6 +1023,7 @@ void xtables_register_target(struct xtables_target *me) static void xtables_fully_register_pending_target(struct xtables_target *me) { struct xtables_target *old; + const char *rn; int compare; old = xtables_find_target(me->name, XTF_DURING_LOAD); @@ -1039,12 +1039,14 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) } /* Now we have two (or more) options, check compatibility. */ + rn = (old->real_name != NULL) ? old->real_name : old->name; if (compare > 0 && - compatible_target_revision(old->real_name, old->revision)) + compatible_target_revision(rn, old->revision)) return; /* See if new target can be used. */ - if (!compatible_target_revision(me->real_name, me->revision)) + rn = (me->real_name != NULL) ? me->real_name : me->name; + if (!compatible_target_revision(rn, me->revision)) return; /* Delete old one. */ -- cgit v1.2.3 From c1a150c98fc94858a440550f0cb347a6060ebb30 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 8 Oct 2012 10:09:04 +0200 Subject: bump version to 1.4.16.2 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 50729505..1af483c3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.16.1]) +AC_INIT([iptables], [1.4.16.2]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=9 -- cgit v1.2.3 From 269655d54e22f3a36250bb2c4639dddd102258c6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 8 Oct 2012 12:04:56 +0000 Subject: build: remove symlink-only extensions from static object list $ ./configure --enable-static --disable-shared --enable-ipv4 --enable-ipv6 && make [...] make[3]: *** No rule to make target "libxt_NOTRACK.o", needed by "libext.a". Stop. Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- extensions/GNUmakefile.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 8b38df91..1cef239c 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -39,7 +39,7 @@ endif # Wildcard module list # pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c))) -pfx_build_mod += NOTRACK state +pfx_symlinks := NOTRACK state @ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c))) @ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c))) pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod}) @@ -48,7 +48,7 @@ pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod}) pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod}) pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod}) pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod}) -pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod}) +pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod} ${pfx_symlinks}) pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod}) pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod}) @@ -220,7 +220,7 @@ man_run = \ done >$@; matches.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod})) + $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks})) targets.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod})) + $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks})) -- cgit v1.2.3 From 9921f2b9a241750e4730fc7d486687c6a32779f4 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 10 Oct 2012 00:35:14 +0000 Subject: build: resolve compile abort in libxt_limit on RHEL5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libxt_limit.c: In function 'print_rate': libxt_limit.c:124: error: 'INFINITY' undeclared (first use in this function) The default mode of glibc-2.15's sets "-D_POSIX_C_SOURCE=200809L", and therefore "-D_ISOC99_SOURCE". However, on þe olde RHEL 5's glibc-2.5, it only has "-D_POSIX_C_SOURCE=200112L". Explicitly draw in the definition of INFINITY by always defining _ISOC99_SOURCE. By doing this, we are moving off of the default set, so _BSD_SOURCE also needs to be explicitly set to get at IFNAMSIZ that is used in xt_hashlimit.h. Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_hashlimit.c | 2 ++ extensions/libxt_limit.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index 831345b7..c5b8d779 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -10,6 +10,8 @@ * * Error corections by nmalykh@bilim.com (22.01.2005) */ +#define _BSD_SOURCE 1 +#define _ISOC99_SOURCE 1 #include #include #include diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c index 023500cf..f75ef2f8 100644 --- a/extensions/libxt_limit.c +++ b/extensions/libxt_limit.c @@ -3,6 +3,8 @@ * Jérôme de Vivie * Hervé Eychenne */ +#define _BSD_SOURCE 1 +#define _ISOC99_SOURCE 1 #include #include #include -- cgit v1.2.3 From 3e6fa55d5e28c93f417afeae7a7d4f349ddffcf4 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 18 Oct 2012 10:50:00 +0200 Subject: bump iptables to 1.4.16.3 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1af483c3..c3b253a6 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.16.2]) +AC_INIT([iptables], [1.4.16.3]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=9 -- cgit v1.2.3 From a46a5698027aa48e27e3cc2d54bb8bbafb10e7da Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Mon, 19 Nov 2012 11:40:40 +0100 Subject: extensions: libxt_statistic: Fix save output Suppressing '--packet 0' in save output resulted in restore failure. This patch includes '--packet 0' in save output while continuing to suppress it in print output. Signed-off-by: Tom Eastep Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_statistic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_statistic.c b/extensions/libxt_statistic.c index 12a83dd8..c23805fb 100644 --- a/extensions/libxt_statistic.c +++ b/extensions/libxt_statistic.c @@ -107,7 +107,7 @@ static void print_match(const struct xt_statistic_info *info, char *prefix) (info->flags & XT_STATISTIC_INVERT) ? " !" : "", prefix, info->u.nth.every + 1); - if (info->u.nth.packet) + if (info->u.nth.packet || *prefix) printf(" %spacket %u", prefix, info->u.nth.packet); break; } -- cgit v1.2.3 From e4415c6cdc9d298a43871b77e6bcda71a42cea2d Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Thu, 6 Dec 2012 19:06:28 +0100 Subject: Manpage update: matches are evaluated in the order they are specified. Fixes bugzilla id 797. --- iptables/iptables-extensions.8.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iptables/iptables-extensions.8.in b/iptables/iptables-extensions.8.in index e02c81fb..9ec3fb0b 100644 --- a/iptables/iptables-extensions.8.in +++ b/iptables/iptables-extensions.8.in @@ -15,7 +15,8 @@ extra command line options become available, depending on the specific module. You can specify multiple extended match modules in one line, and you can use the \fB\-h\fP or \fB\-\-help\fP options after the module has been specified to receive help specific -to that module. +to that module. The extended match modules are evaluated in the order +they are specified in the rule. .PP If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an unknown option is encountered, iptables will try load a match module of the -- cgit v1.2.3 From eec83c7ce4351359cae797840d63cf4ef2809c95 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 25 Dec 2012 13:38:36 +0100 Subject: bump version to 1.4.17 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c3b253a6..ba616ab9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.16.3]) +AC_INIT([iptables], [1.4.17]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=9 -- cgit v1.2.3 From 68e77a26111ee6b8f10c735a76891a7de6d57ee6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 1 Jan 2013 22:47:51 +0000 Subject: build: resolve link failure for ip6t_NETMAP Link stage of libip6t_NETMAP failed since recently. CCLD libip6t_NETMAP.so /usr/lib64/gcc/x86_64-suse-linux/4.7/../../../../x86_64-suse-linux/bin/ld: cannot find -lip6tc libip6t_NETMAP.c uses the "ipv6_prefix_length" function from libip6tc.so; "-lip6tc" is used in the Makefile, but, the directory to it is not specified. Why does the link succeed for some people? Because /usr/lib(64)/libip6tc.so satisfies -lip6tc, but not all environments, especially those without iptables development files, have that file, hence this link error can happen. By suggestion of Mike Frysinger, this patch uses libtool to produce and link the plugins. Signed-off-by: Jan Engelhardt Acked-by: Mike Frysinger Signed-off-by: Pablo Neira Ayuso --- extensions/GNUmakefile.in | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index e71e3ff9..adad4d68 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -33,6 +33,7 @@ AM_VERBOSE_CXX = @echo " CXX " $@; AM_VERBOSE_CXXLD = @echo " CXXLD " $@; AM_VERBOSE_AR = @echo " AR " $@; AM_VERBOSE_GEN = @echo " GEN " $@; +AM_VERBOSE_NULL = @ endif # @@ -75,7 +76,7 @@ install: ${targets_install} if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi; clean: - rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c; + rm -f *.la *.o *.lo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c; rm -f .*.d .*.dd; distclean: clean @@ -89,19 +90,22 @@ init%.o: init%.c # # Shared libraries # -lib%.so: lib%.oo - ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD}; +lib%.so: lib%.la + ${AM_VERBOSE_NULL} ln -fs .libs/$@ $@ -lib%.oo: ${srcdir}/lib%.c - ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; +lib%.la: lib%.lo + ${AM_VERBOSE_CCLD} ../libtool ${AM_LIBTOOL_SILENT} --tag=CC --mode=link ${CCLD} ${AM_LDFLAGS} -module ${LDFLAGS} -o $@ $< ../libxtables/libxtables.la ${$*_LIBADD} -rpath ${xtlibdir} + +lib%.lo: ${srcdir}/lib%.c + ${AM_VERBOSE_CC} ../libtool ${AM_LIBTOOL_SILENT} --tag=CC --mode=compile ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $< libxt_NOTRACK.so: libxt_CT.so - ln -fs $< $@ + ${AM_VERBOSE_GEN} ln -fs $< $@ libxt_state.so: libxt_conntrack.so - ln -fs $< $@ + ${AM_VERBOSE_GEN} ln -fs $< $@ # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD -ip6t_NETMAP_LIBADD = -lip6tc +ip6t_NETMAP_LIBADD = ../libiptc/libip6tc.la xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm -- cgit v1.2.3 From 7b04e3ef3a6ffccb23de83ef3b2d8f5aeaaa09e5 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Wed, 2 Jan 2013 06:03:49 +0000 Subject: extensions: libip6t_DNPT: fix wording in DNPT target replaces SNPT by DNPT. This fixes broken help message that points to SNPT. Signed-off-by: Ulrich Weber Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNPT.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c index 9e4dc5cf..7439816c 100644 --- a/extensions/libip6t_DNPT.c +++ b/extensions/libip6t_DNPT.c @@ -8,7 +8,7 @@ enum { O_DST_PFX = 1 << 1, }; -static const struct xt_option_entry SNPT_options[] = { +static const struct xt_option_entry DNPT_options[] = { { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK, .flags = XTOPT_MAND }, { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK, @@ -16,16 +16,16 @@ static const struct xt_option_entry SNPT_options[] = { { } }; -static void SNPT_help(void) +static void DNPT_help(void) { - printf("SNPT target options:" + printf("DNPT target options:" "\n" " --src-pfx prefix/length\n" " --dst-pfx prefix/length\n" "\n"); } -static void SNPT_parse(struct xt_option_call *cb) +static void DNPT_parse(struct xt_option_call *cb) { struct ip6t_npt_tginfo *npt = cb->data; @@ -42,7 +42,7 @@ static void SNPT_parse(struct xt_option_call *cb) } } -static void SNPT_print(const void *ip, const struct xt_entry_target *target, +static void DNPT_print(const void *ip, const struct xt_entry_target *target, int numeric) { const struct ip6t_npt_tginfo *npt = (const void *)target->data; @@ -59,10 +59,10 @@ static struct xtables_target snpt_tg_reg = { .family = NFPROTO_IPV6, .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)), .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment), - .help = SNPT_help, - .x6_parse = SNPT_parse, - .print = SNPT_print, - .x6_options = SNPT_options, + .help = DNPT_help, + .x6_parse = DNPT_parse, + .print = DNPT_print, + .x6_options = DNPT_options, }; void _init(void) -- cgit v1.2.3 From 92f05a2f38e6c6bc6c69880358c41ac17bd31298 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Thu, 3 Jan 2013 00:39:58 +0000 Subject: extension: libip6t_DNAT: allow port DNAT without address correct parsing of IPv6 port NAT without address NAT, assume one colon as port information. Allows: * address only: -j DNAT --to affe::1 -j DNAT --to [affe::1] * port only -j DNAT --to :80 -j DNAT --to :80-110 -j DNAT --to []:80 -j DNAT --to []:80-110 * address and port -j DNAT --to [affe::1]:80 -j DNAT --to [affe::1]:80-110 Signed-off-by: Ulrich Weber Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNAT.c | 11 ++++++++--- extensions/libip6t_SNAT.c | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c index a5969c36..1bba37e2 100644 --- a/extensions/libip6t_DNAT.c +++ b/extensions/libip6t_DNAT.c @@ -54,8 +54,13 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) xtables_error(RESOURCE_PROBLEM, "strdup"); start = strchr(arg, '['); - if (start == NULL) + if (start == NULL) { start = arg; + /* Lets assume one colon is port information. Otherwise its an IPv6 address */ + colon = strchr(arg, ':'); + if (colon && strchr(colon+1, ':')) + colon = NULL; + } else { start++; end = strchr(start, ']'); @@ -105,8 +110,8 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) range->min_proto.tcp.port = htons(port); range->max_proto.tcp.port = htons(maxport); } - /* Starts with a colon? No IP info...*/ - if (colon == arg) { + /* Starts with colon or [] colon? No IP info...*/ + if (colon == arg || colon == arg+2) { free(arg); return; } diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c index 307be70e..7382ad06 100644 --- a/extensions/libip6t_SNAT.c +++ b/extensions/libip6t_SNAT.c @@ -54,8 +54,13 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) xtables_error(RESOURCE_PROBLEM, "strdup"); start = strchr(arg, '['); - if (start == NULL) + if (start == NULL) { start = arg; + /* Lets assume one colon is port information. Otherwise its an IPv6 address */ + colon = strchr(arg, ':'); + if (colon && strchr(colon+1, ':')) + colon = NULL; + } else { start++; end = strchr(start, ']'); @@ -105,8 +110,8 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range) range->min_proto.tcp.port = htons(port); range->max_proto.tcp.port = htons(maxport); } - /* Starts with a colon? No IP info...*/ - if (colon == arg) { + /* Starts with colon or [] colon? No IP info...*/ + if (colon == arg || colon == arg+2) { free(arg); return; } -- cgit v1.2.3 From ff338552d318b49e07662fd7648fdb11e3c42bc9 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Thu, 3 Jan 2013 00:41:38 +0000 Subject: extensions: libip6t_DNAT: set IPv6 DNAT --to-destination as in IPv4 and fixes DNAT_save Signed-off-by: Ulrich Weber Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNAT.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c index 1bba37e2..eaa6bf1e 100644 --- a/extensions/libip6t_DNAT.c +++ b/extensions/libip6t_DNAT.c @@ -29,13 +29,13 @@ static void DNAT_help(void) { printf( "DNAT target options:\n" -" --to-dest [[-]][:port[-port]]\n" -" Address to map source to.\n" +" --to-destination [[-]][:port[-port]]\n" +" Address to map destination to.\n" "[--random] [--persistent]\n"); } static const struct xt_option_entry DNAT_opts[] = { - {.name = "to-dest", .id = O_TO_DEST, .type = XTTYPE_STRING, + {.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING, .flags = XTOPT_MAND | XTOPT_MULTI}, {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, @@ -167,7 +167,7 @@ static void DNAT_parse(struct xt_option_call *cb) get_kernel_version(); if (kernel_version > LINUX_VERSION(2, 6, 10)) xtables_error(PARAMETER_PROBLEM, - "DNAT: Multiple --to-source not supported"); + "DNAT: Multiple --to-destination not supported"); } parse_to(cb->arg, portok, range); break; @@ -223,7 +223,7 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target) { const struct nf_nat_range *range = (const void *)target->data; - printf(" --to-source "); + printf(" --to-destination "); print_range(range); if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); -- cgit v1.2.3 From 31da96d07b8abb35297201000f7f752019258cf6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 29 Oct 2012 10:22:43 +0100 Subject: iptables: remove unused leftover definitions Signed-off-by: Pablo Neira Ayuso --- iptables/iptables.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/iptables/iptables.c b/iptables/iptables.c index f765cf98..760cb162 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -186,22 +186,6 @@ static const int inverse_for_options[NUMBER_OF_OPT] = #define prog_name iptables_globals.program_name #define prog_vers iptables_globals.program_version -/* Primitive headers... */ -/* defined in netinet/in.h */ -#if 0 -#ifndef IPPROTO_ESP -#define IPPROTO_ESP 50 -#endif -#ifndef IPPROTO_AH -#define IPPROTO_AH 51 -#endif -#endif - -enum { - IPT_DOTTED_ADDR = 0, - IPT_DOTTED_MASK -}; - static void __attribute__((noreturn)) exit_tryhelp(int status) { -- cgit v1.2.3 From d1e7922a587a239e16e0dbe654e63f76e1375e49 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 4 Jan 2013 20:27:11 +0100 Subject: libxtables: add xtables_rule_matches_free This function is shared by iptables and ip6tables. Signed-off-by: Pablo Neira Ayuso --- configure.ac | 4 ++-- include/xtables.h | 2 ++ iptables/ip6tables.c | 23 +---------------------- iptables/iptables.c | 23 +---------------------- libxtables/xtables.c | 22 ++++++++++++++++++++++ 5 files changed, 28 insertions(+), 46 deletions(-) diff --git a/configure.ac b/configure.ac index ba616ab9..ffd088c2 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ AC_INIT([iptables], [1.4.17]) # See libtool.info "Libtool's versioning system" -libxtables_vcurrent=9 -libxtables_vage=0 +libxtables_vcurrent=10 +libxtables_vage=1 AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/include/xtables.h b/include/xtables.h index 2cc1a028..add76ae5 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -417,6 +417,8 @@ extern struct xtables_match *xtables_find_match(const char *name, extern struct xtables_target *xtables_find_target(const char *name, enum xtables_tryload); +extern void xtables_rule_matches_free(struct xtables_rule_match **matches); + /* Your shared library should call one of these. */ extern void xtables_register_match(struct xtables_match *me); extern void xtables_register_matches(struct xtables_match *, unsigned int); diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 0e11a9e1..e9e753a5 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1249,27 +1249,6 @@ generate_entry(const struct ip6t_entry *fw, return e; } -static void clear_rule_matches(struct xtables_rule_match **matches) -{ - struct xtables_rule_match *matchp, *tmp; - - for (matchp = *matches; matchp;) { - tmp = matchp->next; - if (matchp->match->m) { - free(matchp->match->m); - matchp->match->m = NULL; - } - if (matchp->match == matchp->match->next) { - free(matchp->match); - matchp->match = NULL; - } - free(matchp); - matchp = tmp; - } - - *matches = NULL; -} - static void command_jump(struct iptables_command_state *cs) { size_t size; @@ -1963,7 +1942,7 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle if (verbose > 1) dump_entries6(*handle); - clear_rule_matches(&cs.matches); + xtables_rule_matches_free(&cs.matches); if (e != NULL) { free(e); diff --git a/iptables/iptables.c b/iptables/iptables.c index 760cb162..7cc82518 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1241,27 +1241,6 @@ generate_entry(const struct ipt_entry *fw, return e; } -static void clear_rule_matches(struct xtables_rule_match **matches) -{ - struct xtables_rule_match *matchp, *tmp; - - for (matchp = *matches; matchp;) { - tmp = matchp->next; - if (matchp->match->m) { - free(matchp->match->m); - matchp->match->m = NULL; - } - if (matchp->match == matchp->match->next) { - free(matchp->match); - matchp->match = NULL; - } - free(matchp); - matchp = tmp; - } - - *matches = NULL; -} - static void command_jump(struct iptables_command_state *cs) { size_t size; @@ -1963,7 +1942,7 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle if (verbose > 1) dump_entries(*handle); - clear_rule_matches(&cs.matches); + xtables_rule_matches_free(&cs.matches); if (e != NULL) { free(e); diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 4c912860..da174e20 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -1075,6 +1075,28 @@ void xtables_register_targets(struct xtables_target *target, unsigned int n) } while (n > 0); } +/* receives a list of xtables_rule_match, release them */ +void xtables_rule_matches_free(struct xtables_rule_match **matches) +{ + struct xtables_rule_match *matchp, *tmp; + + for (matchp = *matches; matchp;) { + tmp = matchp->next; + if (matchp->match->m) { + free(matchp->match->m); + matchp->match->m = NULL; + } + if (matchp->match == matchp->match->next) { + free(matchp->match); + matchp->match = NULL; + } + free(matchp); + matchp = tmp; + } + + *matches = NULL; +} + /** * xtables_param_act - act on condition * @status: a constant from enum xtables_exittype -- cgit v1.2.3 From 2f655ede64e07a861e3ec50150f572ed98755013 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 29 Oct 2012 10:49:42 +0100 Subject: libxtables: add xtables_print_num This function is used both by iptables and ip6tables, and refactorize to avoid longer than 80-chars per column lines of code. Signed-off-by: Pablo Neira Ayuso --- include/xtables.h | 16 ++++++++++++++++ iptables/ip6tables.c | 48 ++++-------------------------------------------- iptables/iptables.c | 49 ++++--------------------------------------------- libxtables/xtables.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 89 deletions(-) diff --git a/include/xtables.h b/include/xtables.h index add76ae5..75de958e 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -469,6 +469,22 @@ extern void xtables_ip6parse_multiple(const char *, struct in6_addr **, */ extern void xtables_save_string(const char *value); +#define FMT_NUMERIC 0x0001 +#define FMT_NOCOUNTS 0x0002 +#define FMT_KILOMEGAGIGA 0x0004 +#define FMT_OPTIONS 0x0008 +#define FMT_NOTABLE 0x0010 +#define FMT_NOTARGET 0x0020 +#define FMT_VIA 0x0040 +#define FMT_NONEWLINE 0x0080 +#define FMT_LINENUMBERS 0x0100 + +#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \ + | FMT_NUMERIC | FMT_NOTABLE) +#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab)) + +extern void xtables_print_num(uint64_t number, unsigned int format); + #if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) # ifdef _INIT # undef _init diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index e9e753a5..556647f8 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -52,21 +52,6 @@ #define FALSE 0 #endif -#define FMT_NUMERIC 0x0001 -#define FMT_NOCOUNTS 0x0002 -#define FMT_KILOMEGAGIGA 0x0004 -#define FMT_OPTIONS 0x0008 -#define FMT_NOTABLE 0x0010 -#define FMT_NOTARGET 0x0020 -#define FMT_VIA 0x0040 -#define FMT_NONEWLINE 0x0080 -#define FMT_LINENUMBERS 0x0100 - -#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \ - | FMT_NUMERIC | FMT_NOTABLE) -#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab)) - - #define CMD_NONE 0x0000U #define CMD_INSERT 0x0001U #define CMD_DELETE 0x0002U @@ -442,31 +427,6 @@ set_option(unsigned int *options, unsigned int option, uint8_t *invflg, } } -static void -print_num(uint64_t number, unsigned int format) -{ - if (format & FMT_KILOMEGAGIGA) { - if (number > 99999) { - number = (number + 500) / 1000; - if (number > 9999) { - number = (number + 500) / 1000; - if (number > 9999) { - number = (number + 500) / 1000; - if (number > 9999) { - number = (number + 500) / 1000; - printf(FMT("%4lluT ","%lluT "), (unsigned long long)number); - } - else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number); - } - else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number); - } else - printf(FMT("%4lluK ","%lluK "), (unsigned long long)number); - } else - printf(FMT("%5llu ","%llu "), (unsigned long long)number); - } else - printf(FMT("%8llu ","%llu "), (unsigned long long)number); -} - static void print_header(unsigned int format, const char *chain, struct xtc_handle *handle) @@ -478,9 +438,9 @@ print_header(unsigned int format, const char *chain, struct xtc_handle *handle) printf(" (policy %s", pol); if (!(format & FMT_NOCOUNTS)) { fputc(' ', stdout); - print_num(counters.pcnt, (format|FMT_NOTABLE)); + xtables_print_num(counters.pcnt, (format|FMT_NOTABLE)); fputs("packets, ", stdout); - print_num(counters.bcnt, (format|FMT_NOTABLE)); + xtables_print_num(counters.bcnt, (format|FMT_NOTABLE)); fputs("bytes", stdout); } printf(")\n"); @@ -563,8 +523,8 @@ print_firewall(const struct ip6t_entry *fw, printf(FMT("%-4u ", "%u "), num); if (!(format & FMT_NOCOUNTS)) { - print_num(fw->counters.pcnt, format); - print_num(fw->counters.bcnt, format); + xtables_print_num(fw->counters.pcnt, format); + xtables_print_num(fw->counters.bcnt, format); } if (!(format & FMT_NOTARGET)) diff --git a/iptables/iptables.c b/iptables/iptables.c index 7cc82518..00e3f016 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -48,21 +48,6 @@ #define FALSE 0 #endif -#define FMT_NUMERIC 0x0001 -#define FMT_NOCOUNTS 0x0002 -#define FMT_KILOMEGAGIGA 0x0004 -#define FMT_OPTIONS 0x0008 -#define FMT_NOTABLE 0x0010 -#define FMT_NOTARGET 0x0020 -#define FMT_VIA 0x0040 -#define FMT_NONEWLINE 0x0080 -#define FMT_LINENUMBERS 0x0100 - -#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \ - | FMT_NUMERIC | FMT_NOTABLE) -#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab)) - - #define CMD_NONE 0x0000U #define CMD_INSERT 0x0001U #define CMD_DELETE 0x0002U @@ -428,32 +413,6 @@ set_option(unsigned int *options, unsigned int option, uint8_t *invflg, } } -static void -print_num(uint64_t number, unsigned int format) -{ - if (format & FMT_KILOMEGAGIGA) { - if (number > 99999) { - number = (number + 500) / 1000; - if (number > 9999) { - number = (number + 500) / 1000; - if (number > 9999) { - number = (number + 500) / 1000; - if (number > 9999) { - number = (number + 500) / 1000; - printf(FMT("%4lluT ","%lluT "), (unsigned long long)number); - } - else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number); - } - else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number); - } else - printf(FMT("%4lluK ","%lluK "), (unsigned long long)number); - } else - printf(FMT("%5llu ","%llu "), (unsigned long long)number); - } else - printf(FMT("%8llu ","%llu "), (unsigned long long)number); -} - - static void print_header(unsigned int format, const char *chain, struct xtc_handle *handle) { @@ -464,9 +423,9 @@ print_header(unsigned int format, const char *chain, struct xtc_handle *handle) printf(" (policy %s", pol); if (!(format & FMT_NOCOUNTS)) { fputc(' ', stdout); - print_num(counters.pcnt, (format|FMT_NOTABLE)); + xtables_print_num(counters.pcnt, (format|FMT_NOTABLE)); fputs("packets, ", stdout); - print_num(counters.bcnt, (format|FMT_NOTABLE)); + xtables_print_num(counters.bcnt, (format|FMT_NOTABLE)); fputs("bytes", stdout); } printf(")\n"); @@ -551,8 +510,8 @@ print_firewall(const struct ipt_entry *fw, printf(FMT("%-4u ", "%u "), num); if (!(format & FMT_NOCOUNTS)) { - print_num(fw->counters.pcnt, format); - print_num(fw->counters.bcnt, format); + xtables_print_num(fw->counters.pcnt, format); + xtables_print_num(fw->counters.bcnt, format); } if (!(format & FMT_NOTARGET)) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index da174e20..009ab911 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -1912,6 +1912,35 @@ xtables_parse_protocol(const char *s) return -1; } +void xtables_print_num(uint64_t number, unsigned int format) +{ + if (!(format & FMT_KILOMEGAGIGA)) { + printf(FMT("%8llu ","%llu "), (unsigned long long)number); + return; + } + if (number <= 99999) { + printf(FMT("%5llu ","%llu "), (unsigned long long)number); + return; + } + number = (number + 500) / 1000; + if (number <= 9999) { + printf(FMT("%4lluK ","%lluK "), (unsigned long long)number); + return; + } + number = (number + 500) / 1000; + if (number <= 9999) { + printf(FMT("%4lluM ","%lluM "), (unsigned long long)number); + return; + } + number = (number + 500) / 1000; + if (number <= 9999) { + printf(FMT("%4lluG ","%lluG "), (unsigned long long)number); + return; + } + number = (number + 500) / 1000; + printf(FMT("%4lluT ","%lluT "), (unsigned long long)number); +} + int kernel_version; void get_kernel_version(void) -- cgit v1.2.3 From 0824e7d5e9d80988a49a1699adb0d3c17f792b4c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:18 +0000 Subject: doc: fixup omissions in ip6tables-restore.8 Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.8 | 6 ++++-- iptables/iptables-restore.8 | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index 59a3b2e5..a4eadb1e 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -21,7 +21,7 @@ .SH NAME ip6tables-restore \(em Restore IPv6 Tables .SH SYNOPSIS -\fBip6tables\-restore\fP [\fB\-c\fP] [\fB\-n\fP] +\fBip6tables\-restore\fP [\fB\-c\fP] [\fB\-n\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B ip6tables-restore @@ -32,7 +32,9 @@ I/O redirection provided by your shell to read from a file restore the values of all packet and byte counters .TP \fB\-n\fR, \fB\-\-noflush\fR -don't flush the previous contents of the table. If not specified, +don't flush the previous contents of the table. If not specified, +\fBip6tables-restore\fP flushes (deletes) all previous contents of the +respective table. .TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. diff --git a/iptables/iptables-restore.8 b/iptables/iptables-restore.8 index 0dd20cb1..5d1866f3 100644 --- a/iptables/iptables-restore.8 +++ b/iptables/iptables-restore.8 @@ -34,7 +34,7 @@ restore the values of all packet and byte counters \fB\-n\fR, \fB\-\-noflush\fR don't flush the previous contents of the table. If not specified, .B iptables-restore -flushes (deletes) all previous contents of the respective IP Table. +flushes (deletes) all previous contents of the respective table. .TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. -- cgit v1.2.3 From 3dc75984739fd080eb522b638c535164f401b181 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:19 +0000 Subject: doc: document iptables-restore's -t option References: http://bugs.debian.org/644221 Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.8 | 5 ++++- iptables/iptables-restore.8 | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index a4eadb1e..90048655 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -21,7 +21,7 @@ .SH NAME ip6tables-restore \(em Restore IPv6 Tables .SH SYNOPSIS -\fBip6tables\-restore\fP [\fB\-c\fP] [\fB\-n\fP] [\fB\-T\fP \fIname\fP] +\fBip6tables\-restore\fP [\fB\-cnt\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B ip6tables-restore @@ -36,6 +36,9 @@ don't flush the previous contents of the table. If not specified, \fBip6tables-restore\fP flushes (deletes) all previous contents of the respective table. .TP +\fB\-t\fP, \fB\-\-test\fP +Only parse and construct the ruleset, but do not commit it. +.TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. .B ip6tables-restore diff --git a/iptables/iptables-restore.8 b/iptables/iptables-restore.8 index 5d1866f3..23be50f6 100644 --- a/iptables/iptables-restore.8 +++ b/iptables/iptables-restore.8 @@ -21,7 +21,7 @@ .SH NAME iptables-restore \(em Restore IP Tables .SH SYNOPSIS -\fBiptables\-restore\fP [\fB\-c\fP] [\fB\-n\fP] [\fB\-T\fP \fIname\fP] +\fBiptables\-restore\fP [\fB\-cnt\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B iptables-restore @@ -36,6 +36,9 @@ don't flush the previous contents of the table. If not specified, .B iptables-restore flushes (deletes) all previous contents of the respective table. .TP +\fB\-t\fP, \fB\-\-test\fP +Only parse and construct the ruleset, but do not commit it. +.TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. .SH BUGS -- cgit v1.2.3 From 2815a5d5a0e1bd6319bf09a9009f3722f9167b78 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:20 +0000 Subject: doc: document iptables-restore's -v option References: http://bugs.debian.org/644221 Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.8 | 5 ++++- iptables/iptables-restore.8 | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index 90048655..519b77a1 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -21,7 +21,7 @@ .SH NAME ip6tables-restore \(em Restore IPv6 Tables .SH SYNOPSIS -\fBip6tables\-restore\fP [\fB\-cnt\fP] [\fB\-T\fP \fIname\fP] +\fBip6tables\-restore\fP [\fB\-cntv\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B ip6tables-restore @@ -39,6 +39,9 @@ respective table. \fB\-t\fP, \fB\-\-test\fP Only parse and construct the ruleset, but do not commit it. .TP +\fB\-v\fP, \fB\-\-verbose\fP +Print additional debug info during ruleset processing. +.TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. .B ip6tables-restore diff --git a/iptables/iptables-restore.8 b/iptables/iptables-restore.8 index 23be50f6..46ca5d3c 100644 --- a/iptables/iptables-restore.8 +++ b/iptables/iptables-restore.8 @@ -21,7 +21,7 @@ .SH NAME iptables-restore \(em Restore IP Tables .SH SYNOPSIS -\fBiptables\-restore\fP [\fB\-cnt\fP] [\fB\-T\fP \fIname\fP] +\fBiptables\-restore\fP [\fB\-cntv\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B iptables-restore @@ -39,6 +39,9 @@ flushes (deletes) all previous contents of the respective table. \fB\-t\fP, \fB\-\-test\fP Only parse and construct the ruleset, but do not commit it. .TP +\fB\-v\fP, \fB\-\-verbose\fP +Print additional debug info during ruleset processing. +.TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. .SH BUGS -- cgit v1.2.3 From 8c46901ff57856a215c426a50a2fcfe365a3af34 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:21 +0000 Subject: doc: document iptables-restore's -M option References: http://bugs.debian.org/644221 Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.8 | 7 ++++++- iptables/iptables-restore.8 | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index 519b77a1..53ea7907 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -21,7 +21,8 @@ .SH NAME ip6tables-restore \(em Restore IPv6 Tables .SH SYNOPSIS -\fBip6tables\-restore\fP [\fB\-cntv\fP] [\fB\-T\fP \fIname\fP] +\fBip6tables\-restore\fP [\fB\-cntv\fP] [\fB\-M\fP \fImodprobe\fP] +[\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B ip6tables-restore @@ -42,6 +43,10 @@ Only parse and construct the ruleset, but do not commit it. \fB\-v\fP, \fB\-\-verbose\fP Print additional debug info during ruleset processing. .TP +\fB\-M\fP, \fB\-\-modprobe\fP \fImodprobe_program\fP +Specify the path to the modprobe program. By default, ip6tables-restore will +inspect /proc/sys/kernel/modprobe to determine the executable's path. +.TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. .B ip6tables-restore diff --git a/iptables/iptables-restore.8 b/iptables/iptables-restore.8 index 46ca5d3c..005f4237 100644 --- a/iptables/iptables-restore.8 +++ b/iptables/iptables-restore.8 @@ -21,7 +21,8 @@ .SH NAME iptables-restore \(em Restore IP Tables .SH SYNOPSIS -\fBiptables\-restore\fP [\fB\-cntv\fP] [\fB\-T\fP \fIname\fP] +\fBiptables\-restore\fP [\fB\-cntv\fP] [\fB\-M\fP \fImodprobe\fP] +[\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP .B iptables-restore @@ -42,6 +43,10 @@ Only parse and construct the ruleset, but do not commit it. \fB\-v\fP, \fB\-\-verbose\fP Print additional debug info during ruleset processing. .TP +\fB\-M\fP, \fB\-\-modprobe\fP \fImodprobe_program\fP +Specify the path to the modprobe program. By default, iptables-restore will +inspect /proc/sys/kernel/modprobe to determine the executable's path. +.TP \fB\-T\fP, \fB\-\-table\fP \fIname\fP Restore only the named table even if the input stream contains other ones. .SH BUGS -- cgit v1.2.3 From 9ae4dd4d017c85f28b524c3b5b3be4960b3ed245 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:22 +0000 Subject: doc: document iptables-restore's -h option References: http://bugs.debian.org/644221 Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables-restore.8 | 5 ++++- iptables/iptables-restore.8 | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables-restore.8 b/iptables/ip6tables-restore.8 index 53ea7907..dbe19daf 100644 --- a/iptables/ip6tables-restore.8 +++ b/iptables/ip6tables-restore.8 @@ -21,7 +21,7 @@ .SH NAME ip6tables-restore \(em Restore IPv6 Tables .SH SYNOPSIS -\fBip6tables\-restore\fP [\fB\-cntv\fP] [\fB\-M\fP \fImodprobe\fP] +\fBip6tables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP @@ -32,6 +32,9 @@ I/O redirection provided by your shell to read from a file \fB\-c\fR, \fB\-\-counters\fR restore the values of all packet and byte counters .TP +\fB\-h\fP, \fB\-\-help\fP +Print a short option summary. +.TP \fB\-n\fR, \fB\-\-noflush\fR don't flush the previous contents of the table. If not specified, \fBip6tables-restore\fP flushes (deletes) all previous contents of the diff --git a/iptables/iptables-restore.8 b/iptables/iptables-restore.8 index 005f4237..2b1d102c 100644 --- a/iptables/iptables-restore.8 +++ b/iptables/iptables-restore.8 @@ -21,7 +21,7 @@ .SH NAME iptables-restore \(em Restore IP Tables .SH SYNOPSIS -\fBiptables\-restore\fP [\fB\-cntv\fP] [\fB\-M\fP \fImodprobe\fP] +\fBiptables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP] [\fB\-T\fP \fIname\fP] .SH DESCRIPTION .PP @@ -32,6 +32,9 @@ I/O redirection provided by your shell to read from a file \fB\-c\fR, \fB\-\-counters\fR restore the values of all packet and byte counters .TP +\fB\-h\fP, \fB\-\-help\fP +Print a short option summary. +.TP \fB\-n\fR, \fB\-\-noflush\fR don't flush the previous contents of the table. If not specified, .B iptables-restore -- cgit v1.2.3 From 85346f6e406207f85550f1b7b4f61b22a8e38fbb Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:23 +0000 Subject: doc: name the supported log levels for ipt_LOG Leonardo Ferreira da Silva Boiko lets it be known that syslogd.conf may not exist on certain systems. Referencing that manpage is not a good idea in any case, I believe, since the strings that are accepted are defined by iptables and not a syslog implementation. References: http://bugs.debian.org/567564 Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_LOG.man | 5 ++++- extensions/libipt_LOG.man | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/extensions/libip6t_LOG.man b/extensions/libip6t_LOG.man index b7803fed..0a486404 100644 --- a/extensions/libip6t_LOG.man +++ b/extensions/libip6t_LOG.man @@ -11,7 +11,10 @@ separate rules with the same matching criteria, first using target LOG then DROP (or REJECT). .TP \fB\-\-log\-level\fP \fIlevel\fP -Level of logging (numeric or see \fIsyslog.conf\fP(5)). +Level of logging, which can be (system-specific) numeric or a mnemonic. +Possible values are (in decreasing order of priority): \fBemerg\fP, +\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP +or \fBdebug\fP. .TP \fB\-\-log\-prefix\fP \fIprefix\fP Prefix log messages with the specified prefix; up to 29 letters long, diff --git a/extensions/libipt_LOG.man b/extensions/libipt_LOG.man index 47c35e0e..f2574f88 100644 --- a/extensions/libipt_LOG.man +++ b/extensions/libipt_LOG.man @@ -11,7 +11,10 @@ separate rules with the same matching criteria, first using target LOG then DROP (or REJECT). .TP \fB\-\-log\-level\fP \fIlevel\fP -Level of logging (numeric or see \fIsyslog.conf\fP(5)). +Level of logging, which can be (system-specific) numeric or a mnemonic. +Possible values are (in decreasing order of priority): \fBemerg\fP, +\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP +or \fBdebug\fP. .TP \fB\-\-log\-prefix\fP \fIprefix\fP Prefix log messages with the specified prefix; up to 29 letters long, -- cgit v1.2.3 From db1414ece88a798ac3f8878875ec3393a917871f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:27 +0000 Subject: doc: mention -m in the manpage Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.8.in | 7 +++++++ iptables/iptables.8.in | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 078bcacd..8f04b31c 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -281,6 +281,13 @@ See the description of the \fB\-s\fP (source) flag for a detailed description of the syntax. The flag \fB\-\-dst\fP is an alias for this option. .TP +\fB\-m\fP, \fB\-\-match\fP \fImatch\fP +Specifies a match to use, that is, an extension module that tests for a +specific property. The set of matches make up the condition under which a +target is invoked. Matches are evaluated first to last as specified on the +command line and work in short-circuit fashion, i.e. if one extension yields +false, evaluation will stop. +.TP \fB\-j\fP, \fB\-\-jump\fP \fItarget\fP This specifies the target of the rule; i.e., what to do if the packet matches it. The target can be a user-defined chain (other than the diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index d6b409d0..8d657647 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -277,6 +277,13 @@ See the description of the \fB\-s\fP (source) flag for a detailed description of the syntax. The flag \fB\-\-dst\fP is an alias for this option. .TP +\fB\-m\fP, \fB\-\-match\fP \fImatch\fP +Specifies a match to use, that is, an extension module that tests for a +specific property. The set of matches make up the condition under which a +target is invoked. Matches are evaluated first to last as specified on the +command line and work in short-circuit fashion, i.e. if one extension yields +false, evaluation will stop. +.TP \fB\-j\fP, \fB\-\-jump\fP \fItarget\fP This specifies the target of the rule; i.e., what to do if the packet matches it. The target can be a user-defined chain (other than the -- cgit v1.2.3 From 983196ceb4d3bb7b6d3cf6da18bb6d5a5eafb347 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 25 Dec 2012 13:11:28 +0000 Subject: doc: document the -4 and -6 options Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.8.in | 9 +++++++++ iptables/iptables.8.in | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 8f04b31c..58b7bfc7 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -240,6 +240,15 @@ Give a (currently very brief) description of the command syntax. The following parameters make up a rule specification (as used in the add, delete, insert, replace and append commands). .TP +\fB\-4\fP, \fB\-\-ipv4\fP +If a rule using the \fB\-4\fP option is inserted with (and only with) +ip6tables-restore, it will be silently ignored. Any other uses will throw an +error. This option allows to put both IPv4 and IPv6 rules in a single rule file +for use with both iptables-restore and ip6tables-restore. +.TP +\fB\-6\fP, \fB\-\-ipv6\fP +This option has no effect in ip6tables and ip6tables-restore. +.TP [\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP The protocol of the rule or of the packet to check. The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP, diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 8d657647..013ac77a 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -243,6 +243,15 @@ Give a (currently very brief) description of the command syntax. The following parameters make up a rule specification (as used in the add, delete, insert, replace and append commands). .TP +\fB\-4\fP, \fB\-\-ipv4\fP +This option has no effect in iptables and iptables-restore. +.TP +\fB\-6\fP, \fB\-\-ipv6\fP +If a rule using the \fB\-6\fP option is inserted with (and only with) +iptables-restore, it will be silently ignored. Any other uses will throw an +error. This option allows to put both IPv4 and IPv6 rules in a single rule file +for use with both iptables-restore and ip6tables-restore. +.TP [\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP The protocol of the rule or of the packet to check. The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP, -- cgit v1.2.3 From 2fda8fcef0f3c321fb03953b8ecc424a2bad4476 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 24 Jan 2013 09:37:55 +0000 Subject: extensions: S/DNPT: add missing save function Jean-Michel DILLY reports that `ip6tables -S` exits with Target `DNPT' is missing save function when a DNPT rule is invoked. Fix this omission. References: http://marc.info/?l=netfilter&m=135904831220440&w=2 Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNPT.c | 19 +++++++++++++++++++ extensions/libip6t_SNPT.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c index 7439816c..703adf60 100644 --- a/extensions/libip6t_DNPT.c +++ b/extensions/libip6t_DNPT.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -53,6 +54,23 @@ static void DNPT_print(const void *ip, const struct xt_entry_target *target, npt->dst_pfx_len); } +static void DNPT_save(const void *ip, const struct xt_entry_target *target) +{ + static const struct in6_addr zero_addr; + const struct ip6t_npt_tginfo *info = (const void *)target->data; + + if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || + info->src_pfx_len != 0) + printf("--src-pfx %s/%u ", + xtables_ip6addr_to_numeric(&info->src_pfx.in6), + info->src_pfx_len); + if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || + info->dst_pfx_len != 0) + printf("--dst-pfx %s/%u ", + xtables_ip6addr_to_numeric(&info->dst_pfx.in6), + info->dst_pfx_len); +} + static struct xtables_target snpt_tg_reg = { .name = "DNPT", .version = XTABLES_VERSION, @@ -62,6 +80,7 @@ static struct xtables_target snpt_tg_reg = { .help = DNPT_help, .x6_parse = DNPT_parse, .print = DNPT_print, + .save = DNPT_save, .x6_options = DNPT_options, }; diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c index 26a86c56..7ed80b20 100644 --- a/extensions/libip6t_SNPT.c +++ b/extensions/libip6t_SNPT.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -53,6 +54,23 @@ static void SNPT_print(const void *ip, const struct xt_entry_target *target, npt->dst_pfx_len); } +static void SNPT_save(const void *ip, const struct xt_entry_target *target) +{ + static const struct in6_addr zero_addr; + const struct ip6t_npt_tginfo *info = (const void *)target->data; + + if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || + info->src_pfx_len != 0) + printf("--src-pfx %s/%u ", + xtables_ip6addr_to_numeric(&info->src_pfx.in6), + info->src_pfx_len); + if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || + info->dst_pfx_len != 0) + printf("--dst-pfx %s/%u ", + xtables_ip6addr_to_numeric(&info->dst_pfx.in6), + info->dst_pfx_len); +} + static struct xtables_target snpt_tg_reg = { .name = "SNPT", .version = XTABLES_VERSION, @@ -62,6 +80,7 @@ static struct xtables_target snpt_tg_reg = { .help = SNPT_help, .x6_parse = SNPT_parse, .print = SNPT_print, + .save = SNPT_save, .x6_options = SNPT_options, }; -- cgit v1.2.3 From 166f20a3665a28e0f5fcedd0914c8e7d41521428 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 7 Jan 2013 21:34:39 +0100 Subject: doc: document nat table for IPv6 Based on the IPv4 description. Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.8.in | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 58b7bfc7..24c6f661 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -106,6 +106,13 @@ the built-in chains \fBINPUT\fP (for packets destined to local sockets), \fBFORWARD\fP (for packets being routed through the box), and \fBOUTPUT\fP (for locally-generated packets). .TP +\fBnat\fP: +This table is consulted when a packet that creates a new +connection is encountered. It consists of three built-ins: \fBPREROUTING\fP +(for altering packets as soon as they come in), \fBOUTPUT\fP +(for altering locally-generated packets before routing), and \fBPOSTROUTING\fP +(for altering packets as they are about to go out). Available since kernel 3.7. +.TP \fBmangle\fP: This table is used for specialized packet alteration. Until kernel 2.4.17 it had two built-in chains: \fBPREROUTING\fP -- cgit v1.2.3 From efcdba41ca6bde51c8753cb30c869c370f0a3b93 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Mon, 28 Jan 2013 21:15:27 +0100 Subject: Introduce match/target aliases The match/target alias allows us to support the syntax of matches, targets targets merged into other matches/targets. --- include/xtables.h | 16 ++++++++++++++++ iptables/ip6tables.c | 34 ++++++++++++++++++---------------- iptables/iptables.c | 34 ++++++++++++++++++---------------- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/include/xtables.h b/include/xtables.h index 75de958e..c35a6e6d 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -201,6 +201,10 @@ struct xtables_lmap { struct xtables_lmap *next; }; +enum xtables_ext_flags { + XTABLES_EXT_ALIAS = 1 << 0, +}; + /* Include file for additions: new matches and targets. */ struct xtables_match { @@ -218,6 +222,9 @@ struct xtables_match /* Revision of match (0 by default). */ u_int8_t revision; + /* Extension flags */ + u_int8_t ext_flags; + u_int16_t family; /* Size of match data. */ @@ -251,6 +258,9 @@ struct xtables_match /* ip is struct ipt_ip * for example */ void (*save)(const void *ip, const struct xt_entry_match *match); + /* Print match name or alias */ + const char *(*alias)(const struct xt_entry_match *match); + /* Pointer to list of extra command-line options */ const struct option *extra_opts; @@ -289,6 +299,9 @@ struct xtables_target /* Revision of target (0 by default). */ u_int8_t revision; + /* Extension flags */ + u_int8_t ext_flags; + u_int16_t family; @@ -322,6 +335,9 @@ struct xtables_target void (*save)(const void *ip, const struct xt_entry_target *target); + /* Print target name or alias */ + const char *(*alias)(const struct xt_entry_target *target); + /* Pointer to list of extra command-line options */ const struct option *extra_opts; diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 556647f8..4cfbea3d 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1000,7 +1000,8 @@ static int print_match_save(const struct xt_entry_match *e, xtables_find_match(e->u.user.name, XTF_TRY_LOAD, NULL); if (match) { - printf(" -m %s", e->u.user.name); + printf(" -m %s", + match->alias ? match->alias(e) : e->u.user.name); /* some matches don't provide a save function */ if (match->save) @@ -1089,16 +1090,8 @@ void print_rule6(const struct ip6t_entry *e, if (counters < 0) printf(" -c %llu %llu", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt); - /* Print target name */ + /* Print target name and targinfo part */ target_name = ip6tc_get_target(e, h); - if (target_name && (*target_name != '\0')) -#ifdef IP6T_F_GOTO - printf(" -%c %s", e->ipv6.flags & IP6T_F_GOTO ? 'g' : 'j', target_name); -#else - printf(" -j %s", target_name); -#endif - - /* Print targinfo part */ t = ip6t_get_target((struct ip6t_entry *)e); if (t->u.user.name[0]) { struct xtables_target *target = @@ -1110,6 +1103,7 @@ void print_rule6(const struct ip6t_entry *e, exit(1); } + printf(" -j %s", target->alias ? target->alias(t) : target_name); if (target->save) target->save(&e->ipv6, t); else { @@ -1124,7 +1118,13 @@ void print_rule6(const struct ip6t_entry *e, exit(1); } } - } + } else if (target_name && (*target_name != '\0')) +#ifdef IP6T_F_GOTO + printf(" -%c %s", e->ipv6.flags & IP6T_F_GOTO ? 'g' : 'j', target_name); +#else + printf(" -j %s", target_name); +#endif + printf("\n"); } @@ -1229,9 +1229,10 @@ static void command_jump(struct iptables_command_state *cs) strcpy(cs->target->t->u.user.name, cs->jumpto); } else { strcpy(cs->target->t->u.user.name, cs->target->real_name); - fprintf(stderr, "WARNING: The %s target is obsolete. " - "Use %s instead.\n", - cs->jumpto, cs->target->real_name); + if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS)) + fprintf(stderr, "Notice: The %s target is converted into %s target " + "in rule listing and saving.\n", + cs->jumpto, cs->target->real_name); } cs->target->t->u.user.revision = cs->target->revision; @@ -1265,8 +1266,9 @@ static void command_match(struct iptables_command_state *cs) strcpy(m->m->u.user.name, m->name); } else { strcpy(m->m->u.user.name, m->real_name); - fprintf(stderr, "WARNING: The %s match is obsolete. " - "Use %s instead.\n", m->name, m->real_name); + if (!(m->ext_flags & XTABLES_EXT_ALIAS)) + fprintf(stderr, "Notice: The %s match is converted into %s match " + "in rule listing and saving.\n", m->name, m->real_name); } m->m->u.user.revision = m->revision; diff --git a/iptables/iptables.c b/iptables/iptables.c index 00e3f016..085eea16 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -991,7 +991,8 @@ static int print_match_save(const struct xt_entry_match *e, xtables_find_match(e->u.user.name, XTF_TRY_LOAD, NULL); if (match) { - printf(" -m %s", e->u.user.name); + printf(" -m %s", + match->alias ? match->alias(e) : e->u.user.name); /* some matches don't provide a save function */ if (match->save) @@ -1080,16 +1081,8 @@ void print_rule4(const struct ipt_entry *e, if (counters < 0) printf(" -c %llu %llu", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt); - /* Print target name */ + /* Print target name and targinfo part */ target_name = iptc_get_target(e, h); - if (target_name && (*target_name != '\0')) -#ifdef IPT_F_GOTO - printf(" -%c %s", e->ip.flags & IPT_F_GOTO ? 'g' : 'j', target_name); -#else - printf(" -j %s", target_name); -#endif - - /* Print targinfo part */ t = ipt_get_target((struct ipt_entry *)e); if (t->u.user.name[0]) { const struct xtables_target *target = @@ -1101,6 +1094,7 @@ void print_rule4(const struct ipt_entry *e, exit(1); } + printf(" -j %s", target->alias ? target->alias(t) : target_name); if (target->save) target->save(&e->ip, t); else { @@ -1115,7 +1109,13 @@ void print_rule4(const struct ipt_entry *e, exit(1); } } - } + } else if (target_name && (*target_name != '\0')) +#ifdef IPT_F_GOTO + printf(" -%c %s", e->ip.flags & IPT_F_GOTO ? 'g' : 'j', target_name); +#else + printf(" -j %s", target_name); +#endif + printf("\n"); } @@ -1222,9 +1222,10 @@ static void command_jump(struct iptables_command_state *cs) } else { /* Alias support for userspace side */ strcpy(cs->target->t->u.user.name, cs->target->real_name); - fprintf(stderr, "WARNING: The %s target is obsolete. " - "Use %s instead.\n", - cs->jumpto, cs->target->real_name); + if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS)) + fprintf(stderr, "Notice: The %s target is converted into %s target " + "in rule listing and saving.\n", + cs->jumpto, cs->target->real_name); } cs->target->t->u.user.revision = cs->target->revision; @@ -1259,8 +1260,9 @@ static void command_match(struct iptables_command_state *cs) strcpy(m->m->u.user.name, m->name); } else { strcpy(m->m->u.user.name, m->real_name); - fprintf(stderr, "WARNING: The %s match is obsolete. " - "Use %s instead.\n", m->name, m->real_name); + if (!(m->ext_flags & XTABLES_EXT_ALIAS)) + fprintf(stderr, "Notice: the %s match is converted into %s match " + "in rule listing and saving.\n", m->name, m->real_name); } m->m->u.user.revision = m->revision; -- cgit v1.2.3 From e612a9d285477e9951349dd137305393a1255b19 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Mon, 28 Jan 2013 21:18:59 +0100 Subject: Add the "state" alias to the "conntrack" match --- extensions/libxt_conntrack.c | 27 ++++++++++++++++++++++++--- extensions/libxt_state.man | 2 +- include/linux/netfilter/xt_conntrack.h | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index c37f14d2..f7704eba 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -801,7 +801,9 @@ conntrack_dump(const struct xt_conntrack_mtinfo3 *info, const char *prefix, if (info->match_flags & XT_CONNTRACK_STATE) { if (info->invert_flags & XT_CONNTRACK_STATE) printf(" !"); - printf(" %sctstate", prefix); + printf(" %s%s", prefix, + info->match_flags & XT_CONNTRACK_STATE_ALIAS + ? "state" : "ctstate"); print_state(info->state_mask); } @@ -902,6 +904,15 @@ conntrack_dump(const struct xt_conntrack_mtinfo3 *info, const char *prefix, } } +static const char * +conntrack_print_name_alias(const struct xt_entry_match *match) +{ + struct xt_conntrack_mtinfo1 *info = (void *)match->data; + + return info->match_flags & XT_CONNTRACK_STATE_ALIAS + ? "state" : "conntrack"; +} + static void conntrack_print(const void *ip, const struct xt_entry_match *match, int numeric) { @@ -1083,7 +1094,7 @@ static void state_ct1_parse(struct xt_option_call *cb) struct xt_conntrack_mtinfo1 *sinfo = cb->data; xtables_option_parse(cb); - sinfo->match_flags = XT_CONNTRACK_STATE; + sinfo->match_flags = XT_CONNTRACK_STATE | XT_CONNTRACK_STATE_ALIAS; sinfo->state_mask = state_parse_states(cb->arg); if (cb->invert) sinfo->invert_flags |= XT_CONNTRACK_STATE; @@ -1094,7 +1105,7 @@ static void state_ct23_parse(struct xt_option_call *cb) struct xt_conntrack_mtinfo3 *sinfo = cb->data; xtables_option_parse(cb); - sinfo->match_flags = XT_CONNTRACK_STATE; + sinfo->match_flags = XT_CONNTRACK_STATE | XT_CONNTRACK_STATE_ALIAS; sinfo->state_mask = state_parse_states(cb->arg); if (cb->invert) sinfo->invert_flags |= XT_CONNTRACK_STATE; @@ -1158,6 +1169,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack_print, .save = conntrack_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack_mt_opts_v0, }, { @@ -1172,6 +1184,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt4_print, .save = conntrack1_mt4_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1186,6 +1199,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt6_print, .save = conntrack1_mt6_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1200,6 +1214,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt_print, .save = conntrack2_mt_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1214,6 +1229,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt6_print, .save = conntrack2_mt6_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack2_mt_opts, }, { @@ -1228,6 +1244,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack3_mt_print, .save = conntrack3_mt_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack3_mt_opts, }, { @@ -1242,6 +1259,7 @@ static struct xtables_match conntrack_mt_reg[] = { .x6_fcheck = conntrack_mt_check, .print = conntrack3_mt6_print, .save = conntrack3_mt6_save, + .alias = conntrack_print_name_alias, .x6_options = conntrack3_mt_opts, }, { @@ -1249,6 +1267,7 @@ static struct xtables_match conntrack_mt_reg[] = { .name = "state", .real_name = "conntrack", .revision = 1, + .ext_flags = XTABLES_EXT_ALIAS, .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), @@ -1261,6 +1280,7 @@ static struct xtables_match conntrack_mt_reg[] = { .name = "state", .real_name = "conntrack", .revision = 2, + .ext_flags = XTABLES_EXT_ALIAS, .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), @@ -1273,6 +1293,7 @@ static struct xtables_match conntrack_mt_reg[] = { .name = "state", .real_name = "conntrack", .revision = 3, + .ext_flags = XTABLES_EXT_ALIAS, .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), diff --git a/extensions/libxt_state.man b/extensions/libxt_state.man index bd60468f..ec096ca6 100644 --- a/extensions/libxt_state.man +++ b/extensions/libxt_state.man @@ -1,4 +1,4 @@ -The "state" module is an obsolete version of "conntrack". +The "state" extension is a subset of the "conntrack" module. "state" allows access to the connection tracking state for this packet. .TP [\fB!\fP] \fB\-\-state\fP \fIstate\fP diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index 74b904d8..e9715011 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h @@ -30,6 +30,7 @@ enum { XT_CONNTRACK_REPLSRC_PORT = 1 << 10, XT_CONNTRACK_REPLDST_PORT = 1 << 11, XT_CONNTRACK_DIRECTION = 1 << 12, + XT_CONNTRACK_STATE_ALIAS = 1 << 13, }; struct xt_conntrack_mtinfo1 { -- cgit v1.2.3 From 3e55c13513f90cabd525e3893602c0e7e126651e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 5 Feb 2013 14:47:02 +0000 Subject: build: bump SONAME for libxtables Commit v1.4.17-16-gefcdba4 updated structs in xtables.h, so age must become 0 and vcurrent be increased. The latter has already happened in v1.4.17-6-gd1e7922. Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ffd088c2..27e0b10e 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_INIT([iptables], [1.4.17]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=10 -libxtables_vage=1 +libxtables_vage=0 AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) -- cgit v1.2.3 From e422fd2773ff55a34f5109798fae44de78cd4608 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 17 Feb 2013 14:05:35 +0100 Subject: doc: iptables provides up to 5 independent tables This closes bugzilla: http://bugzilla.netfilter.org/show_bug.cgi?id=807 Reported-by: Quentin Armitage Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.8.in | 2 +- iptables/iptables.8.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 24c6f661..86348548 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -87,7 +87,7 @@ or a rule in a built-in chain with target \fBRETURN\fP is matched, the target specified by the chain policy determines the fate of the packet. .SH TABLES -There are currently three independent tables (which tables are present +There are currently five independent tables (which tables are present at any time depends on the kernel configuration options and which modules are present). .TP diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 013ac77a..9643705f 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -86,7 +86,7 @@ or a rule in a built-in chain with target \fBRETURN\fP is matched, the target specified by the chain policy determines the fate of the packet. .SH TABLES -There are currently three independent tables (which tables are present +There are currently five independent tables (which tables are present at any time depends on the kernel configuration options and which modules are present). .TP -- cgit v1.2.3 From d4961b909a75ed0745abb43cdc940e8d947ccf4a Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 17 Feb 2013 23:16:11 +0100 Subject: doc: rpfilter: invert option should have own paragraph Signed-off-by: Florian Westphal --- extensions/libxt_rpfilter.man | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/libxt_rpfilter.man b/extensions/libxt_rpfilter.man index aeb4a9d1..f7f56d23 100644 --- a/extensions/libxt_rpfilter.man +++ b/extensions/libxt_rpfilter.man @@ -17,6 +17,7 @@ Also use the packets' nfmark value when performing the reverse path route lookup \fB\-\-accept\-local\fP This will permit packets arriving from the network with a source address that is also assigned to the local machine. +.TP \fB\-\-invert\fP This will invert the sense of the match. Instead of matching packets that passed the reverse path filter test, match those that have failed it. -- cgit v1.2.3 From d797d0ff0338d2938d18b03038d6f4455b000579 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 3 Mar 2013 22:40:11 +0100 Subject: build: bump version to 1.4.18 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 27e0b10e..2ba5cecb 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.17]) +AC_INIT([iptables], [1.4.18]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=10 -- cgit v1.2.3 From cccfff9309743f173c504dd265fae173caa5b47f Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 16 Mar 2013 12:11:07 +0100 Subject: libip6t_NETMAP: Use xtables_ip6mask_to_cidr and get rid of libip6tc dependency This patch changes the NETMAP target extension (IPv6 side) to use the xtables_ip6mask_to_cidr available in libxtables. As a side effect, we get rid of the libip6tc dependency. Signed-off-by: Pablo Neira Ayuso --- extensions/GNUmakefile.in | 1 - extensions/libip6t_NETMAP.c | 2 +- include/libiptc/libip6tc.h | 3 --- iptables/ip6tables.c | 2 +- libiptc/libip6tc.c | 2 +- 5 files changed, 3 insertions(+), 7 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index adad4d68..3db69859 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -105,7 +105,6 @@ libxt_state.so: libxt_conntrack.so ${AM_VERBOSE_GEN} ln -fs $< $@ # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD -ip6t_NETMAP_LIBADD = ../libiptc/libip6tc.la xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm diff --git a/extensions/libip6t_NETMAP.c b/extensions/libip6t_NETMAP.c index d14dece3..a4df70ee 100644 --- a/extensions/libip6t_NETMAP.c +++ b/extensions/libip6t_NETMAP.c @@ -61,7 +61,7 @@ static void NETMAP_print(const void *ip, const struct xt_entry_target *target, printf("%s", xtables_ip6addr_to_numeric(&a)); for (i = 0; i < 4; i++) a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]); - bits = ipv6_prefix_length(&a); + bits = xtables_ip6mask_to_cidr(&a); if (bits < 0) printf("/%s", xtables_ip6addr_to_numeric(&a)); else diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index c656bc43..9aed80a0 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -154,9 +154,6 @@ int ip6tc_get_raw_socket(void); /* Translates errno numbers into more human-readable form than strerror. */ const char *ip6tc_strerror(int err); -/* Return prefix length, or -1 if not contiguous */ -int ipv6_prefix_length(const struct in6_addr *a); - extern void dump_entries6(struct xtc_handle *const); extern const struct xtc_ops ip6tc_ops; diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 4cfbea3d..7d02cc12 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1022,7 +1022,7 @@ static void print_ip(const char *prefix, const struct in6_addr *ip, const struct in6_addr *mask, int invert) { char buf[51]; - int l = ipv6_prefix_length(mask); + int l = xtables_ip6mask_to_cidr(mask); if (l == 0 && !invert) return; diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index 7128e1cf..ca01bcb4 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -113,7 +113,7 @@ typedef unsigned int socklen_t; #define BIT6(a, l) \ ((ntohl(a->s6_addr32[(l) / 32]) >> (31 - ((l) & 31))) & 1) -int +static int ipv6_prefix_length(const struct in6_addr *a) { int l, i; -- cgit v1.2.3 From 37b19d08f3cbc83a653386d76261490e173a874b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 16 Mar 2013 12:15:30 +0100 Subject: Revert "build: resolve link failure for ip6t_NETMAP" This reverts commit 68e77a26111ee6b8f10c735a76891a7de6d57ee6. The use of libtool was introduced to resolve linking problems in NETMAP (IPv6 version), but that resulted in RPATH problems reported from distributors and warnings spotted by libtool at linking stage. Since (0ca548b libip6t_NETMAP: Use xtables_ip6mask_to_cidr and get rid of libip6tc dependency) fixed the NETMAP issue, let's roll back to our previous stage. A small conflicts in extensions/GNUmakefile.in has been resolved in this revert. Signed-off-by: Pablo Neira Ayuso --- extensions/GNUmakefile.in | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 3db69859..1ae7f74f 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -33,7 +33,6 @@ AM_VERBOSE_CXX = @echo " CXX " $@; AM_VERBOSE_CXXLD = @echo " CXXLD " $@; AM_VERBOSE_AR = @echo " AR " $@; AM_VERBOSE_GEN = @echo " GEN " $@; -AM_VERBOSE_NULL = @ endif # @@ -76,7 +75,7 @@ install: ${targets_install} if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi; clean: - rm -f *.la *.o *.lo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c; + rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c; rm -f .*.d .*.dd; distclean: clean @@ -90,19 +89,16 @@ init%.o: init%.c # # Shared libraries # -lib%.so: lib%.la - ${AM_VERBOSE_NULL} ln -fs .libs/$@ $@ +lib%.so: lib%.oo + ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD}; -lib%.la: lib%.lo - ${AM_VERBOSE_CCLD} ../libtool ${AM_LIBTOOL_SILENT} --tag=CC --mode=link ${CCLD} ${AM_LDFLAGS} -module ${LDFLAGS} -o $@ $< ../libxtables/libxtables.la ${$*_LIBADD} -rpath ${xtlibdir} - -lib%.lo: ${srcdir}/lib%.c - ${AM_VERBOSE_CC} ../libtool ${AM_LIBTOOL_SILENT} --tag=CC --mode=compile ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $< +lib%.oo: ${srcdir}/lib%.c + ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; libxt_NOTRACK.so: libxt_CT.so - ${AM_VERBOSE_GEN} ln -fs $< $@ + ln -fs $< $@ libxt_state.so: libxt_conntrack.so - ${AM_VERBOSE_GEN} ln -fs $< $@ + ln -fs $< $@ # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD xt_RATEEST_LIBADD = -lm -- cgit v1.2.3 From bf75fc041b35c75c2c592e01f1906771e00ce4eb Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 20 Mar 2013 04:14:06 +0000 Subject: ip[6]tables: show --protocol instead of --proto in usage As the man page shows --protocol not --proto, also do so in the usage text displayed by ip[6]tables -h. Signed-off-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.c | 2 +- iptables/iptables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 7d02cc12..c8d34e2d 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -237,7 +237,7 @@ exit_printhelp(const struct xtables_rule_match *matches) "Options:\n" " --ipv4 -4 Error (line is ignored by ip6tables-restore)\n" " --ipv6 -6 Nothing (line is ignored by iptables-restore)\n" -"[!] --proto -p proto protocol: by number or name, eg. `tcp'\n" +"[!] --protocol -p proto protocol: by number or name, eg. `tcp'\n" "[!] --source -s address[/mask][,...]\n" " source specification\n" "[!] --destination -d address[/mask][,...]\n" diff --git a/iptables/iptables.c b/iptables/iptables.c index 085eea16..79fa37b1 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -231,7 +231,7 @@ exit_printhelp(const struct xtables_rule_match *matches) "Options:\n" " --ipv4 -4 Nothing (line is ignored by ip6tables-restore)\n" " --ipv6 -6 Error (line is ignored by iptables-restore)\n" -"[!] --proto -p proto protocol: by number or name, eg. `tcp'\n" +"[!] --protocol -p proto protocol: by number or name, eg. `tcp'\n" "[!] --source -s address[/mask][...]\n" " source specification\n" "[!] --destination -d address[/mask][...]\n" -- cgit v1.2.3 From 71e2bf5cf25a821d62f7d75eb8efa4c61a214c6b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 24 Mar 2013 10:55:07 +0100 Subject: libxt_osf: fix missing --ttl and --log in save output closes http://bugzilla.netfilter.org/show_bug.cgi?id=805 Reported-by: Bourne Without Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_osf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/libxt_osf.c b/extensions/libxt_osf.c index 88274a0e..4e2139a5 100644 --- a/extensions/libxt_osf.c +++ b/extensions/libxt_osf.c @@ -93,6 +93,10 @@ static void osf_save(const void *ip, const struct xt_entry_match *match) const struct xt_osf_info *info = (const struct xt_osf_info*) match->data; printf(" --genre %s%s", (info->flags & XT_OSF_INVERT) ? "! ": "", info->genre); + if (info->flags & XT_OSF_TTL) + printf(" --ttl %u", info->ttl); + if (info->flags & XT_OSF_LOG) + printf(" --log %u", info->loglevel); } static struct xtables_match osf_match = { -- cgit v1.2.3 From 5c522b4523f2edb8e581131ba4cb414a5ee7ece4 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 24 Mar 2013 10:57:42 +0100 Subject: libxt_osf: fix bad location for location in --genre closes http://bugzilla.netfilter.org/show_bug.cgi?id=805 Reported-by: Bourne Without Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_osf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_osf.c b/extensions/libxt_osf.c index 4e2139a5..52dba474 100644 --- a/extensions/libxt_osf.c +++ b/extensions/libxt_osf.c @@ -92,7 +92,10 @@ static void osf_save(const void *ip, const struct xt_entry_match *match) { const struct xt_osf_info *info = (const struct xt_osf_info*) match->data; - printf(" --genre %s%s", (info->flags & XT_OSF_INVERT) ? "! ": "", info->genre); + if (info->flags & XT_OSF_INVERT) + printf(" !"); + + printf(" --genre %s", info->genre); if (info->flags & XT_OSF_TTL) printf(" --ttl %u", info->ttl); if (info->flags & XT_OSF_LOG) -- cgit v1.2.3 From 0a4c357cb91e16a001b1b06ff509d7fb75f5f2e0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 21 Mar 2013 02:40:47 +0000 Subject: libip6t_SNPT: add manpage Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_SNPT.man | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 extensions/libip6t_SNPT.man diff --git a/extensions/libip6t_SNPT.man b/extensions/libip6t_SNPT.man new file mode 100644 index 00000000..78d644a7 --- /dev/null +++ b/extensions/libip6t_SNPT.man @@ -0,0 +1,30 @@ +Provides stateless source IPv6-to-IPv6 Network Prefix Translation (as described +by RFC 6296). +.PP +You have to use this target in the +.B mangle +table, not in the +.B nat +table. It takes the following options: +.TP +\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength] +Set source prefix that you want to translate and length +.TP +\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength] +Set destination prefix that you want to use in the translation and length +.PP +You have to use the DNPT target to undo the translation. Example: +.IP +ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0 +\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64 +.IP +ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64 +\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64 +.PP +You may need to enable IPv6 neighbor proxy: +.IP +sysctl -w net.ipv6.conf.all.proxy_ndp=1 +.PP +You also have to use the +.B NOTRACK +target to disable connection tracking for translated flows. -- cgit v1.2.3 From 71eddedcbf7aebe0cd05421d13b049dd710eaf7f Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 21 Mar 2013 02:40:48 +0000 Subject: libip6t_DNPT: add manpage Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_DNPT.man | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 extensions/libip6t_DNPT.man diff --git a/extensions/libip6t_DNPT.man b/extensions/libip6t_DNPT.man new file mode 100644 index 00000000..61beeee8 --- /dev/null +++ b/extensions/libip6t_DNPT.man @@ -0,0 +1,30 @@ +Provides stateless destination IPv6-to-IPv6 Network Prefix Translation (as +described by RFC 6296). +.PP +You have to use this target in the +.B mangle +table, not in the +.B nat +table. It takes the following options: +.TP +\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength] +Set source prefix that you want to translate and length +.TP +\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength] +Set destination prefix that you want to use in the translation and length +.PP +You have to use the SNPT target to undo the translation. Example: +.IP +ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0 +\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64 +.IP +ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64 +\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64 +.PP +You may need to enable IPv6 neighbor proxy: +.IP +sysctl -w net.ipv6.conf.all.proxy_ndp=1 +.PP +You also have to use the +.B NOTRACK +target to disable connection tracking for translated flows. -- cgit v1.2.3 From e0a0dd703b3448f0f07fc59b7232bf1f1cce7b86 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Wed, 23 Jan 2013 16:00:58 +0000 Subject: extensions: add libxt_bpf extension Add user-space code to support the new BPF iptables extension. Pablo has mangled the original patch to: * include a copy of include/linux/netfilter/xt_bpf.h in the tree. * I have also remove the --bytecode-file option. The original proposal was to accept BPF code in a file in human readable format. Now, with the nfbpf_compile utility, it's very easy to generate the filter using tcpdump-like syntax. * I have remove the trailing comma in the backtick format, the parser works just fine for me here. * Fix error message if --bytecode is missing. Signed-off-by: Willem de Bruijn Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_bpf.c | 152 +++++++++++++++++++++++++++++++++++++++ extensions/libxt_bpf.man | 34 +++++++++ include/linux/netfilter/xt_bpf.h | 17 +++++ 3 files changed, 203 insertions(+) create mode 100644 extensions/libxt_bpf.c create mode 100644 extensions/libxt_bpf.man create mode 100644 include/linux/netfilter/xt_bpf.h diff --git a/extensions/libxt_bpf.c b/extensions/libxt_bpf.c new file mode 100644 index 00000000..dca97d70 --- /dev/null +++ b/extensions/libxt_bpf.c @@ -0,0 +1,152 @@ +/* + * Xtables BPF extension + * + * Written by Willem de Bruijn (willemb@google.com) + * Copyright Google, Inc. 2013 + * Licensed under the GNU General Public License version 2 (GPLv2) +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BCODE_FILE_MAX_LEN_B 1024 + +enum { + O_BCODE_STDIN = 0, +}; + +static void bpf_help(void) +{ + printf( +"bpf match options:\n" +"--bytecode : a bpf program as generated by\n" +" `nfbpf_compiler RAW `\n"); +} + +static const struct xt_option_entry bpf_opts[] = { + {.name = "bytecode", .id = O_BCODE_STDIN, .type = XTTYPE_STRING}, + XTOPT_TABLEEND, +}; + +static void bpf_parse_string(struct xt_option_call *cb, const char *bpf_program, + const char separator) +{ + struct xt_bpf_info *bi = (void *) cb->data; + const char *token; + char sp; + int i; + + /* parse head: length. */ + if (sscanf(bpf_program, "%hu%c", &bi->bpf_program_num_elem, &sp) != 2 || + sp != separator) + xtables_error(PARAMETER_PROBLEM, + "bpf: error parsing program length"); + if (!bi->bpf_program_num_elem) + xtables_error(PARAMETER_PROBLEM, + "bpf: illegal zero length program"); + if (bi->bpf_program_num_elem > XT_BPF_MAX_NUM_INSTR) + xtables_error(PARAMETER_PROBLEM, + "bpf: number of instructions exceeds maximum"); + + /* parse instructions. */ + i = 0; + token = bpf_program; + while ((token = strchr(token, separator)) && (++token)[0]) { + if (i >= bi->bpf_program_num_elem) + xtables_error(PARAMETER_PROBLEM, + "bpf: real program length exceeds" + " the encoded length parameter"); + if (sscanf(token, "%hu %hhu %hhu %u,", + &bi->bpf_program[i].code, + &bi->bpf_program[i].jt, + &bi->bpf_program[i].jf, + &bi->bpf_program[i].k) != 4) + xtables_error(PARAMETER_PROBLEM, + "bpf: error at instr %d", i); + i++; + } + + if (i != bi->bpf_program_num_elem) + xtables_error(PARAMETER_PROBLEM, + "bpf: parsed program length is less than the" + " encoded length parameter"); +} + +static void bpf_parse(struct xt_option_call *cb) +{ + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_BCODE_STDIN: + bpf_parse_string(cb, cb->arg, ','); + break; + default: + xtables_error(PARAMETER_PROBLEM, "bpf: unknown option"); + } +} + +static void bpf_print_code(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_bpf_info *info = (void *) match->data; + int i; + + for (i = 0; i < info->bpf_program_num_elem-1; i++) + printf("%hu %hhu %hhu %u,", info->bpf_program[i].code, + info->bpf_program[i].jt, + info->bpf_program[i].jf, + info->bpf_program[i].k); + + printf("%hu %hhu %hhu %u", info->bpf_program[i].code, + info->bpf_program[i].jt, + info->bpf_program[i].jf, + info->bpf_program[i].k); +} + +static void bpf_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_bpf_info *info = (void *) match->data; + + printf(" --bytecode \"%hu,", info->bpf_program_num_elem); + bpf_print_code(ip, match); + printf("\""); +} + +static void bpf_fcheck(struct xt_fcheck_call *cb) +{ + if (!(cb->xflags & (1 << O_BCODE_STDIN))) + xtables_error(PARAMETER_PROBLEM, + "bpf: missing --bytecode parameter"); +} + +static void bpf_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + printf("match bpf "); + return bpf_print_code(ip, match); +} + +static struct xtables_match bpf_match = { + .family = NFPROTO_UNSPEC, + .name = "bpf", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_bpf_info)), + .userspacesize = XT_ALIGN(offsetof(struct xt_bpf_info, filter)), + .help = bpf_help, + .print = bpf_print, + .save = bpf_save, + .x6_parse = bpf_parse, + .x6_fcheck = bpf_fcheck, + .x6_options = bpf_opts, +}; + +void _init(void) +{ + xtables_register_match(&bpf_match); +} diff --git a/extensions/libxt_bpf.man b/extensions/libxt_bpf.man new file mode 100644 index 00000000..4120a23d --- /dev/null +++ b/extensions/libxt_bpf.man @@ -0,0 +1,34 @@ +Match using Linux Socket Filter. Expects a BPF program in decimal format. This +is the format generated by the \fBnfbpf_compile\fP utility. +.TP +\fB\-\-bytecode\fP \fIcode\fP +Pass the code in backtick format as argument. +.PP +The code format is similar to the output of the tcpdump -ddd command: one line +that stores the number of instructions, followed by one line for each +instruction. Instruction lines follow the pattern 'u16 u8 u8 u32' in decimal +notation. Fields encode the operation, jump offset if true, jump offset if +false and generic multiuse field 'K'. Comments are not supported. +.PP +For example, to read only packets matching 'ip proto 6', insert the following, +without the comments or trailing whitespace: +.IP +4 # number of instructions +.br +48 0 0 9 # load byte ip->proto +.br +21 0 1 6 # jump equal IPPROTO_TCP +.br +6 0 0 1 # return pass (non-zero) +.br +6 0 0 0 # return fail (zero) +.PP +You can pass this filter to the bpf match with the following command: +.IP +iptables \-A OUTPUT \-m bpf \-\-bytecode '4,48 0 0 9,21 0 1 6,6 0 0 1,6 0 0 0' \-j ACCEPT +.PP +Or instead, you can invoke the nfbpf_compile utility. +.IP +iptables \-A OUTPUT \-m bpf \-\-bytecode "`nfbpf_compile RAW 'ip proto 6'`" \-j ACCEPT +.PP +You may want to learn more about BPF from FreeBSD's bpf(4) manpage. diff --git a/include/linux/netfilter/xt_bpf.h b/include/linux/netfilter/xt_bpf.h new file mode 100644 index 00000000..5dda450e --- /dev/null +++ b/include/linux/netfilter/xt_bpf.h @@ -0,0 +1,17 @@ +#ifndef _XT_BPF_H +#define _XT_BPF_H + +#include +#include + +#define XT_BPF_MAX_NUM_INSTR 64 + +struct xt_bpf_info { + __u16 bpf_program_num_elem; + struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR]; + + /* only used in the kernel */ + struct sk_filter *filter __attribute__((aligned(8))); +}; + +#endif /*_XT_BPF_H */ -- cgit v1.2.3 From 1ac30c97c339957b6e3c5cf571de7bc38c827730 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Tue, 12 Mar 2013 05:44:12 +0000 Subject: utils: nfbpf_compile A BPF compiler to convert tcpdump expressions to the decimal format accepted by the libxt_bpf. Generate a file and pass that to iptables: nfbpf_compile RAW 'udp dst port 9000' > test.bpf iptables -A OUTPUT -m bpf --bytecode-file test.bpf -j LOG Or pass the output directly to iptables using backticks: iptables -A INPUT -m bpf --bytecode \ "`./nfbpf_compile RAW 'udp dst port 9000'" -j LOG This utility depends on libpcap. The library is only compiled if the option --enable-bpf-compiler is explicitly passed to ./configure and libpcap is found. Pablo has mangled the original patch to rename the utility to nfbpf_compile. Also modified the output to match exactly what -m bpf --bytecode needs. Signed-off-by: Willem de Bruijn Signed-off-by: Pablo Neira Ayuso --- Makefile.am | 2 -- configure.ac | 4 ++++ utils/Makefile.am | 14 +++++++++++-- utils/nfbpf_compile.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 utils/nfbpf_compile.c diff --git a/Makefile.am b/Makefile.am index 6400ba41..c38d3600 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,9 +10,7 @@ endif if ENABLE_LIBIPQ SUBDIRS += libipq endif -if HAVE_LIBNFNETLINK SUBDIRS += utils -endif # Depends on libxtables: SUBDIRS += extensions # Depends on extensions/libext.a: diff --git a/configure.ac b/configure.ac index 2ba5cecb..06204665 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,9 @@ AC_ARG_ENABLE([devel], [enable_devel="$enableval"], [enable_devel="yes"]) AC_ARG_ENABLE([libipq], AS_HELP_STRING([--enable-libipq], [Build and install libipq])) +AC_ARG_ENABLE([bpf-compiler], + AS_HELP_STRING([--enable-bpf-compiler], [Build bpf compiler]), + [enable_bpfc="yes"]) AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], [Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]), [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) @@ -88,6 +91,7 @@ AM_CONDITIONAL([ENABLE_IPV6], [test "$enable_ipv6" = "yes"]) AM_CONDITIONAL([ENABLE_LARGEFILE], [test "$enable_largefile" = "yes"]) AM_CONDITIONAL([ENABLE_DEVEL], [test "$enable_devel" = "yes"]) AM_CONDITIONAL([ENABLE_LIBIPQ], [test "$enable_libipq" = "yes"]) +AM_CONDITIONAL([ENABLE_BPFC], [test "$enable_bpfc" = "yes"]) PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0], [nfnetlink=1], [nfnetlink=0]) diff --git a/utils/Makefile.am b/utils/Makefile.am index f1bbfc52..bfafd1d0 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -4,7 +4,17 @@ AM_CFLAGS = ${regular_CFLAGS} AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include \ -I${top_srcdir}/include ${libnfnetlink_CFLAGS} -sbin_PROGRAMS = nfnl_osf -pkgdata_DATA = pf.os +sbin_PROGRAMS = +pkgdata_DATA = + +if HAVE_LIBNFNETLINK +sbin_PROGRAMS += nfnl_osf +pkgdata_DATA += pf.os nfnl_osf_LDADD = -lnfnetlink +endif + +if ENABLE_BPFC +sbin_PROGRAMS += nfbpf_compile +nfbpf_compile_LDADD = -lpcap +endif diff --git a/utils/nfbpf_compile.c b/utils/nfbpf_compile.c new file mode 100644 index 00000000..2c46c7b0 --- /dev/null +++ b/utils/nfbpf_compile.c @@ -0,0 +1,55 @@ +/* + * BPF program compilation tool + * + * Generates decimal output, similar to `tcpdump -ddd ...`. + * Unlike tcpdump, will generate for any given link layer type. + * + * Written by Willem de Bruijn (willemb@google.com) + * Copyright Google, Inc. 2013 + * Licensed under the GNU General Public License version 2 (GPLv2) +*/ + +#include +#include + +int main(int argc, char **argv) +{ + struct bpf_program program; + struct bpf_insn *ins; + int i, dlt = DLT_RAW; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s [link] ''\n\n" + " link is a pcap linklayer type:\n" + " one of EN10MB, RAW, SLIP, ...\n\n" + "Examples: %s RAW 'tcp and greater 100'\n" + " %s EN10MB 'ip proto 47'\n'", + argv[0], argv[0], argv[0]); + return 1; + } + + if (argc == 3) { + dlt = pcap_datalink_name_to_val(argv[1]); + if (dlt == -1) { + fprintf(stderr, "Unknown datalinktype: %s\n", argv[1]); + return 1; + } + } + + if (pcap_compile_nopcap(65535, dlt, &program, argv[argc - 1], 1, + PCAP_NETMASK_UNKNOWN)) { + fprintf(stderr, "Compilation error\n"); + return 1; + } + + printf("%d,", program.bf_len); + ins = program.bf_insns; + for (i = 0; i < program.bf_len-1; ++ins, ++i) + printf("%u %u %u %u,", ins->code, ins->jt, ins->jf, ins->k); + + printf("%u %u %u %u\n", ins->code, ins->jt, ins->jf, ins->k); + + pcap_freecode(&program); + return 0; +} + -- cgit v1.2.3 From e82a71d7de5f6e364738dbb7154b88bfff8a5fcd Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 2 Apr 2013 23:21:02 +0000 Subject: utils: nfnl_osf: use the right nfnetlink lib If the user specify libnfnetlink_LIBS during the configure, we must use it. Signed-off-by: Nicolas Dichtel Signed-off-by: Pablo Neira Ayuso --- utils/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/Makefile.am b/utils/Makefile.am index f1bbfc52..66f5c5c1 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -7,4 +7,4 @@ AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include \ sbin_PROGRAMS = nfnl_osf pkgdata_DATA = pf.os -nfnl_osf_LDADD = -lnfnetlink +nfnl_osf_LDADD = ${libnfnetlink_LIBS} -- cgit v1.2.3 From d09cc98b481efc6ea121ce7acd739a87a381c6ed Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Fri, 5 Apr 2013 23:20:51 +0000 Subject: libxt_recent: Fix missing space in manpage for --mask option Signed-off-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_recent.man | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_recent.man b/extensions/libxt_recent.man index 8e6a8e91..d9bd5d2a 100644 --- a/extensions/libxt_recent.man +++ b/extensions/libxt_recent.man @@ -24,7 +24,7 @@ is the default. \fB\-\-rdest\fP Match/save the destination address of each packet in the recent list table. .TP -\fB\-\-mask\fPnetmask +\fB\-\-mask\fP \fInetmask\fP Netmask that will be applied to this recent list. .TP [\fB!\fP] \fB\-\-rcheck\fP -- cgit v1.2.3 From e816ac4fa83f65a5d7d40445c72aa1c3e811cb78 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 13 Apr 2013 11:52:22 +0200 Subject: libxt_NFQUEUE: fix bypass option documentation Steve Caligo points out that the documentation says 'packet will move on to the next rule'. This is incorrect; packet moves to the next table. nf bugzilla #778. Signed-off-by: Florian Westphal --- extensions/libxt_NFQUEUE.man | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/libxt_NFQUEUE.man b/extensions/libxt_NFQUEUE.man index 910e3863..f11e0c89 100644 --- a/extensions/libxt_NFQUEUE.man +++ b/extensions/libxt_NFQUEUE.man @@ -21,5 +21,5 @@ Packets belonging to the same connection are put into the same nfqueue. .TP \fB\-\-queue\-bypass\fP By default, if no userspace program is listening on an NFQUEUE, then all packets that are to be queued -are dropped. When this option is used, the NFQUEUE rule is silently bypassed instead. The packet -will move on to the next rule. +are dropped. When this option is used, the NFQUEUE rule behaves like ACCEPT instead, and the packet +will move on to the next table. -- cgit v1.2.3 From 461faea515c11e58e7cbe598ffe8d22eeb6edffd Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 19 Apr 2013 02:08:04 +0200 Subject: utils: updates .gitignore to include nfbpf_compile Reported-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- utils/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/.gitignore b/utils/.gitignore index ccfd2ecf..216d1e4a 100644 --- a/utils/.gitignore +++ b/utils/.gitignore @@ -1 +1,2 @@ /nfnl_osf +/nfbpf_compile -- cgit v1.2.3 From 1cb432c06637b5030b4a70ff33e306f2bb81d366 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 19 Apr 2013 02:14:04 +0200 Subject: extensions: libxt_bpf: clarify --bytecode argument Mart Frauenlob suggested a change to explain the --bytecode better. I have added some reference to the example bytecode in the format that this argument accepts. Reported-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_bpf.man | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_bpf.man b/extensions/libxt_bpf.man index 4120a23d..5b1d0424 100644 --- a/extensions/libxt_bpf.man +++ b/extensions/libxt_bpf.man @@ -2,7 +2,7 @@ Match using Linux Socket Filter. Expects a BPF program in decimal format. This is the format generated by the \fBnfbpf_compile\fP utility. .TP \fB\-\-bytecode\fP \fIcode\fP -Pass the code in backtick format as argument. +Pass the BPF byte code format (described in the example below). .PP The code format is similar to the output of the tcpdump -ddd command: one line that stores the number of instructions, followed by one line for each -- cgit v1.2.3 From b46f3d833f926c40dd73d52d8cedb94206e6d83d Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Tue, 9 Apr 2013 08:51:53 +0000 Subject: extensions: libxt_multiport: Update manpage to list valid protocols This patch updates the list of valid protocols in the man page section of the multiport match to: tcp, udp, udplite, dccp and sctp. Signed-off-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_multiport.man | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/libxt_multiport.man b/extensions/libxt_multiport.man index caf5c56a..7eb083e1 100644 --- a/extensions/libxt_multiport.man +++ b/extensions/libxt_multiport.man @@ -1,9 +1,8 @@ This module matches a set of source or destination ports. Up to 15 ports can be specified. A port range (port:port) counts as two -ports. It can only be used in conjunction with -\fB\-p tcp\fP -or -\fB\-p udp\fP. +ports. It can only be used in conjunction with one of the +following protocols: +\fBtcp\fP, \fBudp\fP, \fBudplite\fP, \fBdccp\fP and \fBsctp\fP. .TP [\fB!\fP] \fB\-\-source\-ports\fP,\fB\-\-sports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]... Match if the source port is one of the given ports. The flag -- cgit v1.2.3 From b5c12f4aa3ebfc4dac37799e41616c37c188ab4f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 26 Apr 2013 14:45:15 +0200 Subject: libxt_conntrack: fix state match alias state parsing The conntrack match uses a different value for the UNTRACKED state than the state match. Translate states to conntrack states to make sure they all match. Signed-off-by: Patrick McHardy --- extensions/libxt_conntrack.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index f7704eba..9f7b5db2 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -1037,15 +1037,15 @@ static unsigned int state_parse_state(const char *state, size_t len) { if (strncasecmp(state, "INVALID", len) == 0) - return XT_STATE_INVALID; + return XT_CONNTRACK_STATE_INVALID; else if (strncasecmp(state, "NEW", len) == 0) - return XT_STATE_BIT(IP_CT_NEW); + return XT_CONNTRACK_STATE_BIT(IP_CT_NEW); else if (strncasecmp(state, "ESTABLISHED", len) == 0) - return XT_STATE_BIT(IP_CT_ESTABLISHED); + return XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED); else if (strncasecmp(state, "RELATED", len) == 0) - return XT_STATE_BIT(IP_CT_RELATED); + return XT_CONNTRACK_STATE_BIT(IP_CT_RELATED); else if (strncasecmp(state, "UNTRACKED", len) == 0) - return XT_STATE_UNTRACKED; + return XT_CONNTRACK_STATE_UNTRACKED; return 0; } @@ -1115,23 +1115,23 @@ static void state_print_state(unsigned int statemask) { const char *sep = ""; - if (statemask & XT_STATE_INVALID) { + if (statemask & XT_CONNTRACK_STATE_INVALID) { printf("%sINVALID", sep); sep = ","; } - if (statemask & XT_STATE_BIT(IP_CT_NEW)) { + if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) { printf("%sNEW", sep); sep = ","; } - if (statemask & XT_STATE_BIT(IP_CT_RELATED)) { + if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) { printf("%sRELATED", sep); sep = ","; } - if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) { + if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) { printf("%sESTABLISHED", sep); sep = ","; } - if (statemask & XT_STATE_UNTRACKED) { + if (statemask & XT_CONNTRACK_STATE_UNTRACKED) { printf("%sUNTRACKED", sep); sep = ","; } -- cgit v1.2.3 From ca376fcbe51b9a102a490545957d5fee69e253e1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 6 May 2013 21:01:38 +0200 Subject: extensions: add connlabel match allows to "tag" connections with up to 128 label names. Labels are defined in /etc/xtables/connlabel.conf, example: 0 from eth0 1 via eth0 Labels can then be attached to flows, e.g. -A PREROUTING -i eth0 -m connlabel --label "from eth0" --set Signed-off-by: Florian Westphal --- Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile.am b/Makefile.am index c38d3600..cd008a19 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,5 +24,9 @@ tarball: tar -C /tmp -cjf ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root ${PACKAGE_TARNAME}-${PACKAGE_VERSION}/; rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION}; +install-data-hook: + @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || : + @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || : + config.status: extensions/GNUmakefile.in \ include/xtables-version.h.in include/iptables/internal.h.in -- cgit v1.2.3 From ccbf6b6448a4210432b76fd4660798705b05f8c4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 6 May 2013 21:07:38 +0200 Subject: extensions: add connlabel match allows to "tag" connections with up to 128 label names. Labels are defined in /etc/xtables/connlabel.conf, example: 0 from eth0 1 via eth0 Labels can then be attached to flows, e.g. -A PREROUTING -i eth0 -m connlabel --label "from eth0" --set Signed-off-by: Florian Westphal --- Makefile.am | 4 + etc/xtables/connlabel.conf | 8 ++ extensions/libxt_connlabel.c | 210 +++++++++++++++++++++++++++++++++ extensions/libxt_connlabel.man | 32 +++++ include/linux/netfilter/xt_connlabel.h | 12 ++ 5 files changed, 266 insertions(+) create mode 100644 etc/xtables/connlabel.conf create mode 100644 extensions/libxt_connlabel.c create mode 100644 extensions/libxt_connlabel.man create mode 100644 include/linux/netfilter/xt_connlabel.h diff --git a/Makefile.am b/Makefile.am index cd008a19..931c565f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,5 +28,9 @@ install-data-hook: @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || : @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || : +install-data-hook: + @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || : + @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || : + config.status: extensions/GNUmakefile.in \ include/xtables-version.h.in include/iptables/internal.h.in diff --git a/etc/xtables/connlabel.conf b/etc/xtables/connlabel.conf new file mode 100644 index 00000000..9167029e --- /dev/null +++ b/etc/xtables/connlabel.conf @@ -0,0 +1,8 @@ +# example connlabel.conf mapping file. +# used by the "connlabel" match to translate names to their bit-value. +0 eth0-in +1 eth0-out +2 ppp-in +3 ppp-out +4 bulk-traffic +5 interactive diff --git a/extensions/libxt_connlabel.c b/extensions/libxt_connlabel.c new file mode 100644 index 00000000..ae52901b --- /dev/null +++ b/extensions/libxt_connlabel.c @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include + +enum { + O_LABEL = 0, + O_SET = 1, +}; + +#define CONNLABEL_CFG "/etc/xtables/connlabel.conf" + +static void connlabel_mt_help(void) +{ + puts( +"connlabel match options:\n" +"[!] --label name Match if label has been set on connection\n" +" --set Set label on connection"); +} + +static const struct xt_option_entry connlabel_mt_opts[] = { + {.name = "label", .id = O_LABEL, .type = XTTYPE_STRING, + .min = 1, .flags = XTOPT_MAND|XTOPT_INVERT}, + {.name = "set", .id = O_SET, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; + +static int +xtables_parse_connlabel_numerical(const char *s, char **end) +{ + uintmax_t value; + + if (!xtables_strtoul(s, end, &value, 0, XT_CONNLABEL_MAXBIT)) + return -1; + return value; +} + +static bool is_space_posix(int c) +{ + return c == ' ' || c == '\f' || c == '\r' || c == '\t' || c == '\v'; +} + +static char * trim_label(char *label) +{ + char *end; + + while (is_space_posix(*label)) + label++; + end = strchr(label, '\n'); + if (end) + *end = 0; + else + end = strchr(label, '\0'); + end--; + + while (is_space_posix(*end) && end > label) { + *end = 0; + end--; + } + + return *label ? label : NULL; +} + +static void +xtables_get_connlabel(uint16_t bit, char *buf, size_t len) +{ + FILE *fp = fopen(CONNLABEL_CFG, "r"); + char label[1024]; + char *end; + + if (!fp) + goto error; + + while (fgets(label, sizeof(label), fp)) { + int tmp; + + if (label[0] == '#') + continue; + tmp = xtables_parse_connlabel_numerical(label, &end); + if (tmp < 0 || tmp < (int) bit) + continue; + if (tmp > (int) bit) + break; + + end = trim_label(end); + if (!end) + continue; + snprintf(buf, len, "%s", end); + fclose(fp); + return; + } + fclose(fp); + error: + snprintf(buf, len, "%u", (unsigned int) bit); +} + + +static uint16_t xtables_parse_connlabel(const char *s) +{ + FILE *fp = fopen(CONNLABEL_CFG, "r"); + char label[1024]; + char *end; + int bit; + + if (!fp) + xtables_error(PARAMETER_PROBLEM, "label '%s': could not open '%s': %s", + s, CONNLABEL_CFG, strerror(errno)); + + while (fgets(label, sizeof(label), fp)) { + if (label[0] == '#' || !strstr(label, s)) + continue; + bit = xtables_parse_connlabel_numerical(label, &end); + if (bit < 0) + continue; + + end = trim_label(end); + if (!end) + continue; + if (strcmp(end, s) == 0) { + fclose(fp); + return bit; + } + } + fclose(fp); + xtables_error(PARAMETER_PROBLEM, "label '%s' not found in config file %s", + s, CONNLABEL_CFG); +} + +static void connlabel_mt_parse(struct xt_option_call *cb) +{ + struct xt_connlabel_mtinfo *info = cb->data; + int tmp; + + xtables_option_parse(cb); + + switch (cb->entry->id) { + case O_LABEL: + tmp = xtables_parse_connlabel_numerical(cb->arg, NULL); + info->bit = tmp < 0 ? xtables_parse_connlabel(cb->arg) : tmp; + + if (cb->invert) + info->options |= XT_CONNLABEL_OP_INVERT; + break; + case O_SET: + info->options |= XT_CONNLABEL_OP_SET; + break; + } + +} + +static void +connlabel_mt_print_op(const struct xt_connlabel_mtinfo *info, const char *prefix) +{ + if (info->options & XT_CONNLABEL_OP_SET) + printf(" %sset", prefix); +} + +static void +connlabel_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) +{ + const struct xt_connlabel_mtinfo *info = (const void *)match->data; + char buf[1024]; + + printf(" connlabel"); + if (info->options & XT_CONNLABEL_OP_INVERT) + printf(" !"); + if (numeric) { + printf(" %u", info->bit); + } else { + xtables_get_connlabel(info->bit, buf, sizeof(buf)); + printf(" '%s'", buf); + } + connlabel_mt_print_op(info, ""); +} + +static void +connlabel_mt_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_connlabel_mtinfo *info = (const void *)match->data; + char buf[1024]; + + if (info->options & XT_CONNLABEL_OP_INVERT) + printf(" !"); + + xtables_get_connlabel(info->bit, buf, sizeof(buf)); + printf(" --label \"%s\"", buf); + + connlabel_mt_print_op(info, "--"); +} + +static struct xtables_match connlabel_mt_reg = { + .family = NFPROTO_UNSPEC, + .name = "connlabel", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_connlabel_mtinfo)), + .userspacesize = offsetof(struct xt_connlabel_mtinfo, bit), + .help = connlabel_mt_help, + .print = connlabel_mt_print, + .save = connlabel_mt_save, + .x6_parse = connlabel_mt_parse, + .x6_options = connlabel_mt_opts, +}; + +void _init(void) +{ + xtables_register_match(&connlabel_mt_reg); +} diff --git a/extensions/libxt_connlabel.man b/extensions/libxt_connlabel.man new file mode 100644 index 00000000..9fd2043d --- /dev/null +++ b/extensions/libxt_connlabel.man @@ -0,0 +1,32 @@ +Module matches or adds connlabels to a connection. +connlabels are similar to connmarks, except labels are bit-based; i.e. +all labels may be attached to a flow at the same time. +Up to 128 unique labels are currently supported. +.TP +[\fB!\fP] \fB\-\-label\fP \fBname\fP +matches if label \fBname\fP has been set on a connection. +Instead of a name (which will be translated to a number, see EXAMPLE below), +a number may be used instead. Using a number always overrides connlabel.conf. +.TP +\fB\-\-set\fP +if the label has not been set on the connection, set it. +Note that setting a label can fail. This is because the kernel allocates the +conntrack label storage area when the connection is created, and it only +reserves the amount of memory required by the ruleset that exists at +the time the connection is created. +In this case, the match will fail (or succeed, in case \fB\-\-label\fP +option was negated). +.PP +Label translation is done via the \fB/etc/xtables/connlabel.conf\fP configuration file. +.PP +Example: +.IP +.nf +0 eth0-in +1 eth0-out +2 ppp-in +3 ppp-out +4 bulk-traffic +5 interactive +.fi +.PP diff --git a/include/linux/netfilter/xt_connlabel.h b/include/linux/netfilter/xt_connlabel.h new file mode 100644 index 00000000..c4bc9ee9 --- /dev/null +++ b/include/linux/netfilter/xt_connlabel.h @@ -0,0 +1,12 @@ +#include + +#define XT_CONNLABEL_MAXBIT 127 +enum xt_connlabel_mtopts { + XT_CONNLABEL_OP_INVERT = 1 << 0, + XT_CONNLABEL_OP_SET = 1 << 1, +}; + +struct xt_connlabel_mtinfo { + __u16 bit; + __u16 options; +}; -- cgit v1.2.3 From 33e262d4f80afcc464014f28012491bf0c5567ef Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 8 May 2013 15:01:12 +0200 Subject: libxtables: fix parsing of dotted network mask format After upgrade from iptables 1.4.8 to 1.4.18 netmask parsing got broken: -A foo -m policy --mode tunnel --dir in --tunnel-src 192.168.123.0/255.255.255.0 -j RETURN With iptables 1.4.18: iptables-restore v1.4.18: policy: bad value for option "--tunnel-src", or out of range (0-32) This was probably broken by the augmented parser. Reported-by: Thomas Jarosch Signed-off-by: Pablo Neira Ayuso --- libxtables/xtoptions.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c index 452e0fef..78e9abd6 100644 --- a/libxtables/xtoptions.c +++ b/libxtables/xtoptions.c @@ -667,6 +667,33 @@ static void xtopt_parse_mport(struct xt_option_call *cb) free(lo_arg); } +static int xtopt_parse_mask(struct xt_option_call *cb) +{ + struct addrinfo hints = {.ai_family = afinfo->family, + .ai_flags = AI_NUMERICHOST }; + struct addrinfo *res; + int ret; + + ret = getaddrinfo(cb->arg, NULL, &hints, &res); + if (ret < 0) + return 0; + + memcpy(&cb->val.hmask, xtables_sa_host(res->ai_addr, res->ai_family), + xtables_sa_hostlen(res->ai_family)); + + switch(afinfo->family) { + case AF_INET: + cb->val.hlen = xtables_ipmask_to_cidr(&cb->val.hmask.in); + break; + case AF_INET6: + cb->val.hlen = xtables_ip6mask_to_cidr(&cb->val.hmask.in6); + break; + } + + freeaddrinfo(res); + return 1; +} + /** * Parse an integer and ensure it is within the address family's prefix length * limits. The result is stored in @cb->val.hlen. @@ -677,12 +704,17 @@ static void xtopt_parse_plen(struct xt_option_call *cb) unsigned int prefix_len = 128; /* happiness is a warm gcc */ cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; - if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) + if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) { + /* Is this mask expressed in full format? e.g. 255.255.255.0 */ + if (xtopt_parse_mask(cb)) + return; + xt_params->exit_err(PARAMETER_PROBLEM, "%s: bad value for option \"--%s\", " - "or out of range (%u-%u).\n", + "neither a valid network mask " + "nor valid CIDR (%u-%u).\n", cb->ext_name, entry->name, 0, cb->val.hlen); - + } cb->val.hlen = prefix_len; } -- cgit v1.2.3 From 0efff29d495f5bf234d06e4730f1abd78bdb8a1a Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 15 May 2013 23:18:02 +0200 Subject: Revert "extensions: add connlabel match" duplicate This reverts commit ca376fcbe51b9a102a490545957d5fee69e253e1 to get rid of the duplicated install-data-hook. This should get the tree back into the right state. Conflicts: Makefile.am --- Makefile.am | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 931c565f..cd008a19 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,9 +28,5 @@ install-data-hook: @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || : @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || : -install-data-hook: - @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || : - @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || : - config.status: extensions/GNUmakefile.in \ include/xtables-version.h.in include/iptables/internal.h.in -- cgit v1.2.3 From 472bc914415baf2cd9aeb44605867365723a2e3d Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Sun, 19 May 2013 13:22:16 +0200 Subject: doc: mention SNAT in INPUT chain since kernel 2.6.36 SNAT in the INPUT chain was added Jun 2010 to the kernel (commit c68cd6cc21eb329c47ff020ff7412bf58176984e). Signed-off-by: Michael Roth Signed-off-by: Florian Westphal --- extensions/libipt_SNAT.man | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/extensions/libipt_SNAT.man b/extensions/libipt_SNAT.man index 626b5929..093b09c4 100644 --- a/extensions/libipt_SNAT.man +++ b/extensions/libipt_SNAT.man @@ -2,7 +2,10 @@ This target is only valid in the .B nat table, in the .B POSTROUTING -chain. It specifies that the source address of the packet should be +and +.B INPUT +chains, and user-defined chains which are only called from those +chains. It specifies that the source address of the packet should be modified (and all future packets in this connection will also be mangled), and rules should cease being examined. It takes one type of option: @@ -35,3 +38,9 @@ is used then port mapping will be randomized (kernel >= 2.6.21). Gives a client the same source-/destination-address for each connection. This supersedes the SAME target. Support for persistent mappings is available from 2.6.29-rc2. +.PP +Kernels prior to 2.6.36-rc1 don't have the ability to +.B SNAT +in the +.B INPUT +chain. -- cgit v1.2.3 From da18dbcd084cc6f00c46f738e838e752f2d7ae3c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 May 2013 15:14:38 +0200 Subject: build: bump version to 1.4.19 Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 06204665..3f4c3130 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.18]) +AC_INIT([iptables], [1.4.19]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=10 -- cgit v1.2.3 From aef9c366d1761fd2d2013250df699f3dd5a4b708 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 May 2013 15:48:30 +0200 Subject: iptables 1.4.19.1 release Unfortunately, previous release was not included two patches that were applied by Florian recently. This release fixes it. Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3f4c3130..d165d52c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.19]) +AC_INIT([iptables], [1.4.19.1]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=10 -- cgit v1.2.3 From ce7d0619ce49587ca78456caf467cf25f7cbbc4e Mon Sep 17 00:00:00 2001 From: "holger@eitzenberger.org" Date: Tue, 2 Apr 2013 00:35:39 +0000 Subject: extensions: libxt_NFQUEUE: add --queue-cpu-fanout parameter Signed-off-by: Holger Eitzenberger Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_NFQUEUE.c | 63 ++++++++++++++++++++++++++++++++++-- extensions/libxt_NFQUEUE.man | 7 ++++ include/linux/netfilter/xt_NFQUEUE.h | 9 ++++++ 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c index 8c2f6999..0c869187 100644 --- a/extensions/libxt_NFQUEUE.c +++ b/extensions/libxt_NFQUEUE.c @@ -13,8 +13,10 @@ enum { O_QUEUE_NUM = 0, O_QUEUE_BALANCE, O_QUEUE_BYPASS, + O_QUEUE_CPU_FANOUT, F_QUEUE_NUM = 1 << O_QUEUE_NUM, F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE, + F_QUEUE_CPU_FANOUT = 1 << O_QUEUE_CPU_FANOUT, }; static void NFQUEUE_help(void) @@ -37,7 +39,15 @@ static void NFQUEUE_help_v2(void) { NFQUEUE_help_v1(); printf( -" --queue-bypass Bypass Queueing if no queue instance exists.\n"); +" --queue-bypass Bypass Queueing if no queue instance exists.\n" +" --queue-cpu-fanout Use current CPU (no hashing)\n"); +} + +static void NFQUEUE_help_v3(void) +{ + NFQUEUE_help_v2(); + printf( +" --queue-cpu-fanout Use current CPU (no hashing)\n"); } #define s struct xt_NFQ_info @@ -48,6 +58,8 @@ static const struct xt_option_entry NFQUEUE_opts[] = { {.name = "queue-balance", .id = O_QUEUE_BALANCE, .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM}, {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE}, + {.name = "queue-cpu-fanout", .id = O_QUEUE_CPU_FANOUT, + .type = XTTYPE_NONE, .also = F_QUEUE_BALANCE}, XTOPT_TABLEEND, }; #undef s @@ -92,6 +104,18 @@ static void NFQUEUE_parse_v2(struct xt_option_call *cb) } } +static void NFQUEUE_parse_v3(struct xt_option_call *cb) +{ + struct xt_NFQ_info_v3 *info = cb->data; + + NFQUEUE_parse_v2(cb); + switch (cb->entry->id) { + case O_QUEUE_CPU_FANOUT: + info->flags |= NFQ_FLAG_CPU_FANOUT; + break; + } +} + static void NFQUEUE_print(const void *ip, const struct xt_entry_target *target, int numeric) { @@ -120,10 +144,20 @@ static void NFQUEUE_print_v2(const void *ip, const struct xt_NFQ_info_v2 *info = (void *) target->data; NFQUEUE_print_v1(ip, target, numeric); - if (info->bypass) + if (info->bypass & NFQ_FLAG_BYPASS) printf(" bypass"); } +static void NFQUEUE_print_v3(const void *ip, + const struct xt_entry_target *target, int numeric) +{ + const struct xt_NFQ_info_v3 *info = (void *)target->data; + + NFQUEUE_print_v2(ip, target, numeric); + if (info->flags & NFQ_FLAG_CPU_FANOUT) + printf(" cpu-fanout"); +} + static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target) { const struct xt_NFQ_info *tinfo = @@ -151,10 +185,20 @@ static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target NFQUEUE_save_v1(ip, target); - if (info->bypass) + if (info->bypass & NFQ_FLAG_BYPASS) printf(" --queue-bypass"); } +static void NFQUEUE_save_v3(const void *ip, + const struct xt_entry_target *target) +{ + const struct xt_NFQ_info_v3 *info = (void *)target->data; + + NFQUEUE_save_v2(ip, target); + if (info->flags & NFQ_FLAG_CPU_FANOUT) + printf(" --queue-cpu-fanout"); +} + static void NFQUEUE_init_v1(struct xt_entry_target *t) { struct xt_NFQ_info_v1 *tinfo = (void *)t->data; @@ -199,6 +243,19 @@ static struct xtables_target nfqueue_targets[] = { .save = NFQUEUE_save_v2, .x6_parse = NFQUEUE_parse_v2, .x6_options = NFQUEUE_opts, +},{ + .family = NFPROTO_UNSPEC, + .revision = 3, + .name = "NFQUEUE", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)), + .help = NFQUEUE_help_v3, + .init = NFQUEUE_init_v1, + .print = NFQUEUE_print_v3, + .save = NFQUEUE_save_v3, + .x6_parse = NFQUEUE_parse_v3, + .x6_options = NFQUEUE_opts, } }; diff --git a/extensions/libxt_NFQUEUE.man b/extensions/libxt_NFQUEUE.man index f11e0c89..7a991291 100644 --- a/extensions/libxt_NFQUEUE.man +++ b/extensions/libxt_NFQUEUE.man @@ -23,3 +23,10 @@ Packets belonging to the same connection are put into the same nfqueue. By default, if no userspace program is listening on an NFQUEUE, then all packets that are to be queued are dropped. When this option is used, the NFQUEUE rule behaves like ACCEPT instead, and the packet will move on to the next table. +.PP +.TP +\fB\-\-queue\-cpu-fanout\fP +Available starting Linux kernel 3.10. When used together with +\fB--queue-balance\fP this will use the CPU ID as an index to map packets to +the queues. The idea is that you can improve performance if there's a queue +per CPU. This requires \fB--queue-balance\fP to be specified. diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h index 9eafdbbb..8bb5fe65 100644 --- a/include/linux/netfilter/xt_NFQUEUE.h +++ b/include/linux/netfilter/xt_NFQUEUE.h @@ -26,4 +26,13 @@ struct xt_NFQ_info_v2 { __u16 bypass; }; +struct xt_NFQ_info_v3 { + __u16 queuenum; + __u16 queues_total; + __u16 flags; +#define NFQ_FLAG_BYPASS 0x01 /* for compatibility with v2 */ +#define NFQ_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */ +#define NFQ_FLAG_MASK 0x03 +}; + #endif /* _XT_NFQ_TARGET_H */ -- cgit v1.2.3 From 0c3753b1d4226a6e7bea9619415cf40cadee1e58 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 6 Apr 2013 13:41:25 +0200 Subject: extensions: add copyright statements Add copyright statements to all extensions authored by myself. Signed-off-by: Patrick McHardy --- extensions/libip6t_DNPT.c | 4 ++++ extensions/libip6t_SNPT.c | 4 ++++ extensions/libxt_CLASSIFY.c | 4 ++++ extensions/libxt_CT.c | 4 ++++ extensions/libxt_RATEEST.c | 4 ++++ extensions/libxt_addrtype.c | 2 ++ extensions/libxt_policy.c | 4 ++++ extensions/libxt_rateest.c | 4 ++++ extensions/libxt_statistic.c | 4 ++++ 9 files changed, 34 insertions(+) diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c index 703adf60..a442de6d 100644 --- a/extensions/libip6t_DNPT.c +++ b/extensions/libip6t_DNPT.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2012-2013 Patrick McHardy + */ + #include #include #include diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c index 7ed80b20..4f10de03 100644 --- a/extensions/libip6t_SNPT.c +++ b/extensions/libip6t_SNPT.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2012-2013 Patrick McHardy + */ + #include #include #include diff --git a/extensions/libxt_CLASSIFY.c b/extensions/libxt_CLASSIFY.c index ee0f9e1c..e04657ae 100644 --- a/extensions/libxt_CLASSIFY.c +++ b/extensions/libxt_CLASSIFY.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2003-2013 Patrick McHardy + */ + #include #include #include diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index a576a953..c8437b6c 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2010-2013 Patrick McHardy + */ + #include #include #include diff --git a/extensions/libxt_RATEEST.c b/extensions/libxt_RATEEST.c index acdefb90..449ceab6 100644 --- a/extensions/libxt_RATEEST.c +++ b/extensions/libxt_RATEEST.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2008-2013 Patrick McHardy + */ + #include #include #include diff --git a/extensions/libxt_addrtype.c b/extensions/libxt_addrtype.c index e8a85456..e5d3033c 100644 --- a/extensions/libxt_addrtype.c +++ b/extensions/libxt_addrtype.c @@ -1,4 +1,6 @@ /* Shared library add-on to iptables to add addrtype matching support + * + * Copyright (c) 2003-2013 Patrick McHardy * * This program is released under the terms of GNU GPL */ #include diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c index 54ec2294..0a64a80c 100644 --- a/extensions/libxt_policy.c +++ b/extensions/libxt_policy.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2005-2013 Patrick McHardy + */ + #include #include #include diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c index 185a8135..fb244121 100644 --- a/extensions/libxt_rateest.c +++ b/extensions/libxt_rateest.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2008-2013 Patrick McHardy + */ + #include #include #include diff --git a/extensions/libxt_statistic.c b/extensions/libxt_statistic.c index c23805fb..b6ae5f5c 100644 --- a/extensions/libxt_statistic.c +++ b/extensions/libxt_statistic.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2006-2013 Patrick McHardy + */ + #include #include #include -- cgit v1.2.3 From a17d7fdf4fd8da8b41e67f02c8b8b371c2daa619 Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 10 Apr 2013 13:23:45 +0200 Subject: libip6t_mh: Correct command to list named mh types in manpage Signed-off-by: Patrick McHardy --- extensions/libip6t_mh.man | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libip6t_mh.man b/extensions/libip6t_mh.man index 4559e783..8ec08c6f 100644 --- a/extensions/libip6t_mh.man +++ b/extensions/libip6t_mh.man @@ -8,5 +8,5 @@ a numeric MH .IR type or one of the MH type names shown by the command .nf - ip6tables \-p ipv6\-mh \-h + ip6tables \-p mh \-h .fi -- cgit v1.2.3 From 11965180ba6f278fea81f55a3aa48c8f7c667142 Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 10 Apr 2013 06:47:07 +0000 Subject: extensions: libxt_DNAT: rename IPv4 manpage and tell about IPv6 support This patch renames libipt_DNAT.man to libxt_DNAT.man thus informing about the IPv6 version, as suggested by Patrick McHardy. Also, it updates the list of valid protocols for port mapping is updated to: tcp, udp, dccp and sctp. Signed-off-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_DNAT.man | 39 --------------------------------------- extensions/libxt_DNAT.man | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 39 deletions(-) delete mode 100644 extensions/libipt_DNAT.man create mode 100644 extensions/libxt_DNAT.man diff --git a/extensions/libipt_DNAT.man b/extensions/libipt_DNAT.man deleted file mode 100644 index d5ded35b..00000000 --- a/extensions/libipt_DNAT.man +++ /dev/null @@ -1,39 +0,0 @@ -This target is only valid in the -.B nat -table, in the -.B PREROUTING -and -.B OUTPUT -chains, and user-defined chains which are only called from those -chains. It specifies that the destination address of the packet -should be modified (and all future packets in this connection will -also be mangled), and rules should cease being examined. It takes one -type of option: -.TP -\fB\-\-to\-destination\fP [\fIipaddr\fP[\fB\-\fP\fIipaddr\fP]][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]] -which can specify a single new destination IP address, an inclusive -range of IP addresses, and optionally, a port range (which is only -valid if the rule also specifies -\fB\-p tcp\fP -or -\fB\-p udp\fP). -If no port range is specified, then the destination port will never be -modified. If no IP address is specified then only the destination port -will be modified. - -In Kernels up to 2.6.10 you can add several \-\-to\-destination options. For -those kernels, if you specify more than one destination address, either via an -address range or multiple \-\-to\-destination options, a simple round-robin (one -after another in cycle) load balancing takes place between these addresses. -Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges -anymore. -.TP -\fB\-\-random\fP -If option -\fB\-\-random\fP -is used then port mapping will be randomized (kernel >= 2.6.22). -.TP -\fB\-\-persistent\fP -Gives a client the same source-/destination-address for each connection. -This supersedes the SAME target. Support for persistent mappings is available -from 2.6.29-rc2. diff --git a/extensions/libxt_DNAT.man b/extensions/libxt_DNAT.man new file mode 100644 index 00000000..225274ff --- /dev/null +++ b/extensions/libxt_DNAT.man @@ -0,0 +1,38 @@ +This target is only valid in the +.B nat +table, in the +.B PREROUTING +and +.B OUTPUT +chains, and user-defined chains which are only called from those +chains. It specifies that the destination address of the packet +should be modified (and all future packets in this connection will +also be mangled), and rules should cease being examined. It takes the +following options: +.TP +\fB\-\-to\-destination\fP [\fIipaddr\fP[\fB\-\fP\fIipaddr\fP]][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]] +which can specify a single new destination IP address, an inclusive +range of IP addresses. Optionally a port range, +if the rule also specifies one of the following protocols: +\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP. +If no port range is specified, then the destination port will never be +modified. If no IP address is specified then only the destination port +will be modified. +In Kernels up to 2.6.10 you can add several \-\-to\-destination options. For +those kernels, if you specify more than one destination address, either via an +address range or multiple \-\-to\-destination options, a simple round-robin (one +after another in cycle) load balancing takes place between these addresses. +Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges +anymore. +.TP +\fB\-\-random\fP +If option +\fB\-\-random\fP +is used then port mapping will be randomized (kernel >= 2.6.22). +.TP +\fB\-\-persistent\fP +Gives a client the same source-/destination-address for each connection. +This supersedes the SAME target. Support for persistent mappings is available +from 2.6.29-rc2. +.TP +IPv6 support available since Linux kernels >= 3.7. -- cgit v1.2.3 From ebd4a00b74aa99ed25841a235fe79b1462baea7f Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 10 Apr 2013 06:48:49 +0000 Subject: extensions: libxt_REDIRECT: rename IPv4 manpage and tell about IPv6 support This patch renames libipt_REDIRECT.man to libxt_REDIRECT.man thus informing about the IPv6 version. Also the list of valid protocols for port mapping is updated to: tcp, udp, dccp and sctp. Signed-off-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_REDIRECT.man | 25 ------------------------- extensions/libxt_REDIRECT.man | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 25 deletions(-) delete mode 100644 extensions/libipt_REDIRECT.man create mode 100644 extensions/libxt_REDIRECT.man diff --git a/extensions/libipt_REDIRECT.man b/extensions/libipt_REDIRECT.man deleted file mode 100644 index 90ab19d7..00000000 --- a/extensions/libipt_REDIRECT.man +++ /dev/null @@ -1,25 +0,0 @@ -This target is only valid in the -.B nat -table, in the -.B PREROUTING -and -.B OUTPUT -chains, and user-defined chains which are only called from those -chains. It redirects the packet to the machine itself by changing the -destination IP to the primary address of the incoming interface -(locally-generated packets are mapped to the 127.0.0.1 address). -.TP -\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP] -This specifies a destination port or range of ports to use: without -this, the destination port is never altered. This is only valid -if the rule also specifies -\fB\-p tcp\fP -or -\fB\-p udp\fP. -.TP -\fB\-\-random\fP -If option -\fB\-\-random\fP -is used then port mapping will be randomized (kernel >= 2.6.22). -.RS -.PP diff --git a/extensions/libxt_REDIRECT.man b/extensions/libxt_REDIRECT.man new file mode 100644 index 00000000..3400a6df --- /dev/null +++ b/extensions/libxt_REDIRECT.man @@ -0,0 +1,24 @@ +This target is only valid in the +.B nat +table, in the +.B PREROUTING +and +.B OUTPUT +chains, and user-defined chains which are only called from those +chains. It redirects the packet to the machine itself by changing the +destination IP to the primary address of the incoming interface +(locally-generated packets are mapped to the localhost address, +127.0.0.1 for IPv4 and ::1 for IPv6). +.TP +\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP] +This specifies a destination port or range of ports to use: without +this, the destination port is never altered. This is only valid +if the rule also specifies one of the following protocols: +\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP. +.TP +\fB\-\-random\fP +If option +\fB\-\-random\fP +is used then port mapping will be randomized (kernel >= 2.6.22). +.TP +IPv6 support available starting Linux kernels >= 3.7. -- cgit v1.2.3 From b8646dc9623631db3b71a5c1846566cf54a66a3a Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 10 Apr 2013 06:49:25 +0000 Subject: extensions: libxt_NETMAP: rename IPv4 manpage and tell about IPv6 support This patch renames libipt_NETMAP.man to libxt_NETMAP.man thus informing about the IPv6 version. Signed-off-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_NETMAP.man | 9 --------- extensions/libxt_NETMAP.man | 11 +++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) delete mode 100644 extensions/libipt_NETMAP.man create mode 100644 extensions/libxt_NETMAP.man diff --git a/extensions/libipt_NETMAP.man b/extensions/libipt_NETMAP.man deleted file mode 100644 index a7e90b8d..00000000 --- a/extensions/libipt_NETMAP.man +++ /dev/null @@ -1,9 +0,0 @@ -This target allows you to statically map a whole network of addresses onto -another network of addresses. It can only be used from rules in the -.B nat -table. -.TP -\fB\-\-to\fP \fIaddress\fP[\fB/\fP\fImask\fP] -Network address to map to. The resulting address will be constructed in the -following way: All 'one' bits in the mask are filled in from the new `address'. -All bits that are zero in the mask are filled in from the original address. diff --git a/extensions/libxt_NETMAP.man b/extensions/libxt_NETMAP.man new file mode 100644 index 00000000..06507db7 --- /dev/null +++ b/extensions/libxt_NETMAP.man @@ -0,0 +1,11 @@ +This target allows you to statically map a whole network of addresses onto +another network of addresses. It can only be used from rules in the +.B nat +table. +.TP +\fB\-\-to\fP \fIaddress\fP[\fB/\fP\fImask\fP] +Network address to map to. The resulting address will be constructed in the +following way: All 'one' bits in the mask are filled in from the new `address'. +All bits that are zero in the mask are filled in from the original address. +.TP +IPv6 support available since Linux kernels >= 3.7. -- cgit v1.2.3 From 8df3c38438bb75edb480845913af77692c8a5c99 Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 10 Apr 2013 06:49:57 +0000 Subject: extensions: libxt_SNAT: rename IPv4 manpage and tell about IPv6 support This patch renames libipt_SNAT.man to libxt_SNAT.man thus informing about the IPv6 version. Also the list of valid protocols for port mapping is updated to: tcp, udp, dccp and sctp. Signed-off-by: Mart Frauenlob Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_SNAT.man | 46 ---------------------------------------------- extensions/libxt_SNAT.man | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 46 deletions(-) delete mode 100644 extensions/libipt_SNAT.man create mode 100644 extensions/libxt_SNAT.man diff --git a/extensions/libipt_SNAT.man b/extensions/libipt_SNAT.man deleted file mode 100644 index 093b09c4..00000000 --- a/extensions/libipt_SNAT.man +++ /dev/null @@ -1,46 +0,0 @@ -This target is only valid in the -.B nat -table, in the -.B POSTROUTING -and -.B INPUT -chains, and user-defined chains which are only called from those -chains. It specifies that the source address of the packet should be -modified (and all future packets in this connection will also be -mangled), and rules should cease being examined. It takes one type -of option: -.TP -\fB\-\-to\-source\fP [\fIipaddr\fP[\fB\-\fP\fIipaddr\fP]][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]] -which can specify a single new source IP address, an inclusive range -of IP addresses, and optionally, a port range (which is only valid if -the rule also specifies -\fB\-p tcp\fP -or -\fB\-p udp\fP). -If no port range is specified, then source ports below 512 will be -mapped to other ports below 512: those between 512 and 1023 inclusive -will be mapped to ports below 1024, and other ports will be mapped to -1024 or above. Where possible, no port alteration will occur. - -In Kernels up to 2.6.10, you can add several \-\-to\-source options. For those -kernels, if you specify more than one source address, either via an address -range or multiple \-\-to\-source options, a simple round-robin (one after another -in cycle) takes place between these addresses. -Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges -anymore. -.TP -\fB\-\-random\fP -If option -\fB\-\-random\fP -is used then port mapping will be randomized (kernel >= 2.6.21). -.TP -\fB\-\-persistent\fP -Gives a client the same source-/destination-address for each connection. -This supersedes the SAME target. Support for persistent mappings is available -from 2.6.29-rc2. -.PP -Kernels prior to 2.6.36-rc1 don't have the ability to -.B SNAT -in the -.B INPUT -chain. diff --git a/extensions/libxt_SNAT.man b/extensions/libxt_SNAT.man new file mode 100644 index 00000000..f0620a21 --- /dev/null +++ b/extensions/libxt_SNAT.man @@ -0,0 +1,45 @@ +This target is only valid in the +.B nat +table, in the +.B POSTROUTING +and +.B INPUT +chains, and user-defined chains which are only called from those +chains. It specifies that the source address of the packet should be +modified (and all future packets in this connection will also be +mangled), and rules should cease being examined. It takes the +following options: +.TP +\fB\-\-to\-source\fP [\fIipaddr\fP[\fB\-\fP\fIipaddr\fP]][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]] +which can specify a single new source IP address, an inclusive range +of IP addresses. Optionally a port range, +if the rule also specifies one of the following protocols: +\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP. +If no port range is specified, then source ports below 512 will be +mapped to other ports below 512: those between 512 and 1023 inclusive +will be mapped to ports below 1024, and other ports will be mapped to +1024 or above. Where possible, no port alteration will occur. +In Kernels up to 2.6.10, you can add several \-\-to\-source options. For those +kernels, if you specify more than one source address, either via an address +range or multiple \-\-to\-source options, a simple round-robin (one after another +in cycle) takes place between these addresses. +Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges +anymore. +.TP +\fB\-\-random\fP +If option +\fB\-\-random\fP +is used then port mapping will be randomized (kernel >= 2.6.21). +.TP +\fB\-\-persistent\fP +Gives a client the same source-/destination-address for each connection. +This supersedes the SAME target. Support for persistent mappings is available +from 2.6.29-rc2. +.PP +Kernels prior to 2.6.36-rc1 don't have the ability to +.B SNAT +in the +.B INPUT +chain. +.TP +IPv6 support available since Linux kernels >= 3.7. -- cgit v1.2.3 From 14bca55dde79adddd77999ae262b8132ae0396f9 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Sun, 19 May 2013 17:01:06 +0000 Subject: iptables: use autoconf to process .in man pages This fixes a bug in iptables.8 and ip6tables.8 where @PACKAGE_VERSION@ was not processed in the VERSION section. It also simplifies the Makefile by avoiding some sed commands. [ Mangled this patch to rename iptables-extensions.8.in to iptables-extensions.8.tmpl.in to avoid having a file whose name is terminated by .in.in --pablo ] Signed-off-by: Andy Spencer Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 ++ iptables/.gitignore | 1 + iptables/Makefile.am | 11 ++--------- iptables/ip6tables.8.in | 2 +- iptables/iptables-extensions.8.in | 28 ---------------------------- iptables/iptables-extensions.8.tmpl.in | 28 ++++++++++++++++++++++++++++ iptables/iptables.8.in | 2 +- 7 files changed, 35 insertions(+), 39 deletions(-) delete mode 100644 iptables/iptables-extensions.8.in create mode 100644 iptables/iptables-extensions.8.tmpl.in diff --git a/configure.ac b/configure.ac index d165d52c..3e5e8268 100644 --- a/configure.ac +++ b/configure.ac @@ -127,6 +127,8 @@ AC_SUBST([libxtables_vmajor]) AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc + iptables/iptables.8 iptables/ip6tables.8 + iptables/iptables-extensions.8.tmpl libipq/Makefile libipq/libipq.pc libiptc/Makefile libiptc/libiptc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc diff --git a/iptables/.gitignore b/iptables/.gitignore index 4fc63aa4..c9c31788 100644 --- a/iptables/.gitignore +++ b/iptables/.gitignore @@ -6,6 +6,7 @@ /iptables /iptables.8 /iptables-extensions.8 +/iptables-extensions.8.tmpl /iptables-save /iptables-restore /iptables-static diff --git a/iptables/Makefile.am b/iptables/Makefile.am index 61e78db9..46d24630 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -38,15 +38,8 @@ if ENABLE_IPV6 v6_sbin_links = ip6tables ip6tables-restore ip6tables-save endif -iptables.8: ${srcdir}/iptables.8.in - ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@; - -ip6tables.8: ${srcdir}/ip6tables.8.in - ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@; - -iptables-extensions.8: ${srcdir}/iptables-extensions.8.in ../extensions/matches.man ../extensions/targets.man - ${AM_VERBOSE_GEN} sed -e \ - 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' \ +iptables-extensions.8: ${srcdir}/iptables-extensions.8.tmpl ../extensions/matches.man ../extensions/targets.man + ${AM_VERBOSE_GEN} sed \ -e '/@MATCH@/ r ../extensions/matches.man' \ -e '/@TARGET@/ r ../extensions/targets.man' $< >$@; diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 86348548..05e0d0f7 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -1,4 +1,4 @@ -.TH IP6TABLES 8 "" "@PACKAGE_AND_VERSION@" "@PACKAGE_AND_VERSION@" +.TH IP6TABLES 8 "" "@PACKAGE_STRING@" "@PACKAGE_STRING@" .\" .\" Man page written by Andras Kis-Szabo .\" It is based on iptables man page. diff --git a/iptables/iptables-extensions.8.in b/iptables/iptables-extensions.8.in deleted file mode 100644 index 9ec3fb0b..00000000 --- a/iptables/iptables-extensions.8.in +++ /dev/null @@ -1,28 +0,0 @@ -.TH iptables-extensions 8 "" "@PACKAGE_AND_VERSION@" "@PACKAGE_AND_VERSION@" -.SH NAME -iptables-extensions \(em list of extensions in the standard iptables distribution -.SH SYNOPSIS -\fBip6tables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]] -[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...] -.PP -\fBiptables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]] -[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...] -.SH MATCH EXTENSIONS -iptables can use extended packet matching modules -with the \fB\-m\fP or \fB\-\-match\fP -options, followed by the matching module name; after these, various -extra command line options become available, depending on the specific -module. You can specify multiple extended match modules in one line, -and you can use the \fB\-h\fP or \fB\-\-help\fP -options after the module has been specified to receive help specific -to that module. The extended match modules are evaluated in the order -they are specified in the rule. -.PP -If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an -unknown option is encountered, iptables will try load a match module of the -same name as the protocol, to try making the option available. -.\" @MATCH@ -.SH TARGET EXTENSIONS -iptables can use extended target modules: the following are included -in the standard distribution. -.\" @TARGET@ diff --git a/iptables/iptables-extensions.8.tmpl.in b/iptables/iptables-extensions.8.tmpl.in new file mode 100644 index 00000000..99d89a1f --- /dev/null +++ b/iptables/iptables-extensions.8.tmpl.in @@ -0,0 +1,28 @@ +.TH iptables-extensions 8 "" "@PACKAGE_STRING@" "@PACKAGE_STRING@" +.SH NAME +iptables-extensions \(em list of extensions in the standard iptables distribution +.SH SYNOPSIS +\fBip6tables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]] +[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...] +.PP +\fBiptables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]] +[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...] +.SH MATCH EXTENSIONS +iptables can use extended packet matching modules +with the \fB\-m\fP or \fB\-\-match\fP +options, followed by the matching module name; after these, various +extra command line options become available, depending on the specific +module. You can specify multiple extended match modules in one line, +and you can use the \fB\-h\fP or \fB\-\-help\fP +options after the module has been specified to receive help specific +to that module. The extended match modules are evaluated in the order +they are specified in the rule. +.PP +If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an +unknown option is encountered, iptables will try load a match module of the +same name as the protocol, to try making the option available. +.\" @MATCH@ +.SH TARGET EXTENSIONS +iptables can use extended target modules: the following are included +in the standard distribution. +.\" @TARGET@ diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 9643705f..0fba603d 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -1,4 +1,4 @@ -.TH IPTABLES 8 "" "@PACKAGE_AND_VERSION@" "@PACKAGE_AND_VERSION@" +.TH IPTABLES 8 "" "@PACKAGE_STRING@" "@PACKAGE_STRING@" .\" .\" Man page written by Herve Eychenne (May 1999) .\" It is based on ipchains page. -- cgit v1.2.3 From 17fd36631d3ca17b581be9acb8ab054931b5a917 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Mon, 27 May 2013 06:55:11 +0000 Subject: xtables: improve get_modprobe handling In bug #455, Dmitry V. Levin proposed a more robust get_modprobe implementation. The patch below is a version of his patch, updated to apply to current git. This closes bug #455. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- libxtables/xtables.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 009ab911..ebc77b6c 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -305,8 +305,8 @@ static char *get_modprobe(void) { int procfile; char *ret; + int count; -#define PROCFILE_BUFSIZ 1024 procfile = open(PROC_SYS_MODPROBE, O_RDONLY); if (procfile < 0) return NULL; @@ -316,19 +316,19 @@ static char *get_modprobe(void) exit(1); } - ret = malloc(PROCFILE_BUFSIZ); + ret = malloc(PATH_MAX); if (ret) { - memset(ret, 0, PROCFILE_BUFSIZ); - switch (read(procfile, ret, PROCFILE_BUFSIZ)) { - case -1: goto fail; - case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ + count = read(procfile, ret, PATH_MAX); + if (count > 0 && count < PATH_MAX) + { + if (ret[count - 1] == '\n') + ret[count - 1] = '\0'; + else + ret[count] = '\0'; + close(procfile); + return ret; } - if (ret[strlen(ret)-1]=='\n') - ret[strlen(ret)-1]=0; - close(procfile); - return ret; } - fail: free(ret); close(procfile); return NULL; -- cgit v1.2.3 From 96c42d4c46df3edbd41fa47b860fba217f03cfeb Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 30 May 2013 12:44:43 +0200 Subject: extensions: libxt_LED: fix parsing of delay Closes bugzilla: https://bugzilla.netfilter.org/show_bug.cgi?id=825 Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_LED.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/libxt_LED.c b/extensions/libxt_LED.c index e6cf8497..8622c379 100644 --- a/extensions/libxt_LED.c +++ b/extensions/libxt_LED.c @@ -49,7 +49,6 @@ static void LED_help(void) static void LED_parse(struct xt_option_call *cb) { struct xt_led_info *led = cb->data; - unsigned int delay; xtables_option_parse(cb); switch (cb->entry->id) { @@ -60,7 +59,7 @@ static void LED_parse(struct xt_option_call *cb) case O_LED_DELAY: if (strncasecmp(cb->arg, "inf", 3) == 0) led->delay = -1; - else if (!xtables_strtoui(cb->arg, NULL, &delay, 0, UINT32_MAX)) + else if (!xtables_strtoui(cb->arg, NULL, &led->delay, 0, UINT32_MAX)) xtables_error(PARAMETER_PROBLEM, "Delay value must be within range 0..%u", UINT32_MAX); -- cgit v1.2.3 From fe42fac939288cf72cc751dc6b517714e0720e62 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Wed, 5 Jun 2013 04:16:25 +0200 Subject: configure: display summary This patch adds a message at the end of configure which displays the different compilation options and system settings. An example output is the following: Iptables Configuration: IPv4 support: yes IPv6 support: yes Devel support: yes IPQ support: no Large file support: yes BPF utils support: no Build parameters: Put plugins into executable (static): no Support plugins via dlopen (shared): yes Installation prefix (--prefix): /usr/local Xtables extension directory: /usr/local/lib/xtables Pkg-config directory: /usr/local/lib/pkgconfig Kernel build directory: /lib/modules/custom Host: x86_64-unknown-linux-gnu GCC binary: gcc Signed-off-by: Eric Leblond Signed-off-by: Pablo Neira Ayuso --- configure.ac | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 3e5e8268..d2094945 100644 --- a/configure.ac +++ b/configure.ac @@ -49,10 +49,11 @@ AC_ARG_ENABLE([devel], [Install Xtables development headers]), [enable_devel="$enableval"], [enable_devel="yes"]) AC_ARG_ENABLE([libipq], - AS_HELP_STRING([--enable-libipq], [Build and install libipq])) + AS_HELP_STRING([--enable-libipq], [Build and install libipq]), + [enable_libipq="$enableval"], [enable_libipq="no"]) AC_ARG_ENABLE([bpf-compiler], AS_HELP_STRING([--enable-bpf-compiler], [Build bpf compiler]), - [enable_bpfc="yes"]) + [enable_bpfc="yes"], [enable_bpfc="no"]) AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], [Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]), [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) @@ -111,6 +112,20 @@ if [[ -n "$ksourcedir" ]]; then fi; pkgdatadir='${datadir}/xtables'; +define([EXPAND_VARIABLE], +[$2=[$]$1 +if test $prefix = 'NONE'; then + prefix="/usr/local" +fi +while true; do + case "[$]$2" in + *\[$]* ) eval "$2=[$]$2" ;; + *) break ;; + esac +done +eval "$2=[$]$2" +])dnl EXPAND_VARIABLE + AC_SUBST([regular_CFLAGS]) AC_SUBST([regular_CPPFLAGS]) AC_SUBST([noundef_LDFLAGS]) @@ -135,3 +150,33 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile libxtables/Makefile utils/Makefile include/xtables-version.h include/iptables/internal.h]) AC_OUTPUT + + +EXPAND_VARIABLE(xtlibdir, e_xtlibdir) +EXPAND_VARIABLE(pkgconfigdir, e_pkgconfigdir) + +echo " +Iptables Configuration: + IPv4 support: ${enable_ipv4} + IPv6 support: ${enable_ipv6} + Devel support: ${enable_devel} + IPQ support: ${enable_libipq} + Large file support: ${enable_largefile} + BPF utils support: ${enable_bpfc} + +Build parameters: + Put plugins into executable (static): ${enable_static} + Support plugins via dlopen (shared): ${enable_shared} + Installation prefix (--prefix): ${prefix} + Xtables extension directory: ${e_xtlibdir} + Pkg-config directory: ${e_pkgconfigdir}" + +if [[ -n "$ksourcedir" ]]; then + echo " Kernel source directory: ${ksourcedir}" +fi; +if [[ -n "$kbuilddir" ]]; then + echo " Kernel build directory: ${kbuilddir}" +fi; + +echo " Host: ${host} + GCC binary: ${CC}" -- cgit v1.2.3 From 48356408ccf03ec2fdba0ceae3d9b5eae5e5e959 Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 10 Apr 2013 06:45:08 +0000 Subject: extensions: libxt_MASQUERADE: rename IPv4 manpage and tell about IPv6 support also update list of protocols valid for port mapping. Signed-off-by: Mart Frauenlob Signed-off-by: Florian Westphal --- extensions/libip6t_MASQUERADE.man | 30 ------------------------------ extensions/libipt_MASQUERADE.man | 30 ------------------------------ extensions/libxt_MASQUERADE.man | 28 ++++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 60 deletions(-) delete mode 100644 extensions/libip6t_MASQUERADE.man delete mode 100644 extensions/libipt_MASQUERADE.man create mode 100644 extensions/libxt_MASQUERADE.man diff --git a/extensions/libip6t_MASQUERADE.man b/extensions/libip6t_MASQUERADE.man deleted file mode 100644 index c63d826b..00000000 --- a/extensions/libip6t_MASQUERADE.man +++ /dev/null @@ -1,30 +0,0 @@ -This target is only valid in the -.B nat -table, in the -.B POSTROUTING -chain. It should only be used with dynamically assigned IPv6 (dialup) -connections: if you have a static IP address, you should use the SNAT -target. Masquerading is equivalent to specifying a mapping to the IP -address of the interface the packet is going out, but also has the -effect that connections are -.I forgotten -when the interface goes down. This is the correct behavior when the -next dialup is unlikely to have the same interface address (and hence -any established connections are lost anyway). -.TP -\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP] -This specifies a range of source ports to use, overriding the default -.B SNAT -source port-selection heuristics (see above). This is only valid -if the rule also specifies -\fB\-p tcp\fP -or -\fB\-p udp\fP. -.TP -\fB\-\-random\fP -Randomize source port mapping -If option -\fB\-\-random\fP -is used then port mapping will be randomized. -.RS -.PP diff --git a/extensions/libipt_MASQUERADE.man b/extensions/libipt_MASQUERADE.man deleted file mode 100644 index 2dae9640..00000000 --- a/extensions/libipt_MASQUERADE.man +++ /dev/null @@ -1,30 +0,0 @@ -This target is only valid in the -.B nat -table, in the -.B POSTROUTING -chain. It should only be used with dynamically assigned IP (dialup) -connections: if you have a static IP address, you should use the SNAT -target. Masquerading is equivalent to specifying a mapping to the IP -address of the interface the packet is going out, but also has the -effect that connections are -.I forgotten -when the interface goes down. This is the correct behavior when the -next dialup is unlikely to have the same interface address (and hence -any established connections are lost anyway). -.TP -\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP] -This specifies a range of source ports to use, overriding the default -.B SNAT -source port-selection heuristics (see above). This is only valid -if the rule also specifies -\fB\-p tcp\fP -or -\fB\-p udp\fP. -.TP -\fB\-\-random\fP -Randomize source port mapping -If option -\fB\-\-random\fP -is used then port mapping will be randomized (kernel >= 2.6.21). -.RS -.PP diff --git a/extensions/libxt_MASQUERADE.man b/extensions/libxt_MASQUERADE.man new file mode 100644 index 00000000..c9e39501 --- /dev/null +++ b/extensions/libxt_MASQUERADE.man @@ -0,0 +1,28 @@ +This target is only valid in the +.B nat +table, in the +.B POSTROUTING +chain. It should only be used with dynamically assigned IP (dialup) +connections: if you have a static IP address, you should use the SNAT +target. Masquerading is equivalent to specifying a mapping to the IP +address of the interface the packet is going out, but also has the +effect that connections are +.I forgotten +when the interface goes down. This is the correct behavior when the +next dialup is unlikely to have the same interface address (and hence +any established connections are lost anyway). +.TP +\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP] +This specifies a range of source ports to use, overriding the default +.B SNAT +source port-selection heuristics (see above). This is only valid +if the rule also specifies one of the following protocols: +\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP. +.TP +\fB\-\-random\fP +Randomize source port mapping +If option +\fB\-\-random\fP +is used then port mapping will be randomized (kernel >= 2.6.21). +.TP +IPv6 support available since Linux kernels >= 3.7. -- cgit v1.2.3 From f927d5fc3a6a0a8a8fb03e733a6572a934482723 Mon Sep 17 00:00:00 2001 From: Mart Frauenlob Date: Wed, 10 Apr 2013 06:47:32 +0000 Subject: extensions: libxt_LOG: rename IPv4 manpage and tell about IPv6 support Signed-off-by: Mart Frauenlob Signed-off-by: Florian Westphal --- extensions/libip6t_LOG.man | 34 ---------------------------------- extensions/libipt_LOG.man | 34 ---------------------------------- extensions/libxt_LOG.man | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 68 deletions(-) delete mode 100644 extensions/libip6t_LOG.man delete mode 100644 extensions/libipt_LOG.man create mode 100644 extensions/libxt_LOG.man diff --git a/extensions/libip6t_LOG.man b/extensions/libip6t_LOG.man deleted file mode 100644 index 0a486404..00000000 --- a/extensions/libip6t_LOG.man +++ /dev/null @@ -1,34 +0,0 @@ -Turn on kernel logging of matching packets. When this option is set -for a rule, the Linux kernel will print some information on all -matching packets (like most IPv6 IPv6-header fields) via the kernel log -(where it can be read with -.I dmesg -or -.IR syslogd (8)). -This is a "non-terminating target", i.e. rule traversal continues at -the next rule. So if you want to LOG the packets you refuse, use two -separate rules with the same matching criteria, first using target LOG -then DROP (or REJECT). -.TP -\fB\-\-log\-level\fP \fIlevel\fP -Level of logging, which can be (system-specific) numeric or a mnemonic. -Possible values are (in decreasing order of priority): \fBemerg\fP, -\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP -or \fBdebug\fP. -.TP -\fB\-\-log\-prefix\fP \fIprefix\fP -Prefix log messages with the specified prefix; up to 29 letters long, -and useful for distinguishing messages in the logs. -.TP -\fB\-\-log\-tcp\-sequence\fP -Log TCP sequence numbers. This is a security risk if the log is -readable by users. -.TP -\fB\-\-log\-tcp\-options\fP -Log options from the TCP packet header. -.TP -\fB\-\-log\-ip\-options\fP -Log options from the IPv6 packet header. -.TP -\fB\-\-log\-uid\fP -Log the userid of the process which generated the packet. diff --git a/extensions/libipt_LOG.man b/extensions/libipt_LOG.man deleted file mode 100644 index f2574f88..00000000 --- a/extensions/libipt_LOG.man +++ /dev/null @@ -1,34 +0,0 @@ -Turn on kernel logging of matching packets. When this option is set -for a rule, the Linux kernel will print some information on all -matching packets (like most IP header fields) via the kernel log -(where it can be read with -.I dmesg -or -.IR syslogd (8)). -This is a "non-terminating target", i.e. rule traversal continues at -the next rule. So if you want to LOG the packets you refuse, use two -separate rules with the same matching criteria, first using target LOG -then DROP (or REJECT). -.TP -\fB\-\-log\-level\fP \fIlevel\fP -Level of logging, which can be (system-specific) numeric or a mnemonic. -Possible values are (in decreasing order of priority): \fBemerg\fP, -\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP -or \fBdebug\fP. -.TP -\fB\-\-log\-prefix\fP \fIprefix\fP -Prefix log messages with the specified prefix; up to 29 letters long, -and useful for distinguishing messages in the logs. -.TP -\fB\-\-log\-tcp\-sequence\fP -Log TCP sequence numbers. This is a security risk if the log is -readable by users. -.TP -\fB\-\-log\-tcp\-options\fP -Log options from the TCP packet header. -.TP -\fB\-\-log\-ip\-options\fP -Log options from the IP packet header. -.TP -\fB\-\-log\-uid\fP -Log the userid of the process which generated the packet. diff --git a/extensions/libxt_LOG.man b/extensions/libxt_LOG.man new file mode 100644 index 00000000..6d3a83a4 --- /dev/null +++ b/extensions/libxt_LOG.man @@ -0,0 +1,34 @@ +Turn on kernel logging of matching packets. When this option is set +for a rule, the Linux kernel will print some information on all +matching packets (like most IP/IPv6 header fields) via the kernel log +(where it can be read with +.I dmesg +or +.IR syslogd (8)). +This is a "non-terminating target", i.e. rule traversal continues at +the next rule. So if you want to LOG the packets you refuse, use two +separate rules with the same matching criteria, first using target LOG +then DROP (or REJECT). +.TP +\fB\-\-log\-level\fP \fIlevel\fP +Level of logging, which can be (system-specific) numeric or a mnemonic. +Possible values are (in decreasing order of priority): \fBemerg\fP, +\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP +or \fBdebug\fP. +.TP +\fB\-\-log\-prefix\fP \fIprefix\fP +Prefix log messages with the specified prefix; up to 29 letters long, +and useful for distinguishing messages in the logs. +.TP +\fB\-\-log\-tcp\-sequence\fP +Log TCP sequence numbers. This is a security risk if the log is +readable by users. +.TP +\fB\-\-log\-tcp\-options\fP +Log options from the TCP packet header. +.TP +\fB\-\-log\-ip\-options\fP +Log options from the IP/IPv6 packet header. +.TP +\fB\-\-log\-uid\fP +Log the userid of the process which generated the packet. -- cgit v1.2.3 From 34844da8f53ec80b34ad094f2fca2519a7079ec2 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 1 May 2013 00:56:35 +0200 Subject: Introduce a new revision for the set match with the counters support The revision add the support of matching the packet/byte counters if the set was defined with the extension. Also, a new flag is introduced to suppress updating the packet/byte counters if required. Signed-off-by: Jozsef Kadlecsik --- extensions/libxt_set.c | 222 +++++++++++++++++++++++++++++++++ extensions/libxt_set.man | 41 +++++- include/linux/netfilter/ipset/ip_set.h | 52 ++++++-- include/linux/netfilter/xt_set.h | 9 ++ 4 files changed, 312 insertions(+), 12 deletions(-) diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c index e0111568..2cb9e78a 100644 --- a/extensions/libxt_set.c +++ b/extensions/libxt_set.c @@ -289,6 +289,214 @@ set_save_v2(const void *ip, const struct xt_entry_match *match) printf(" --return-nomatch"); } +/* Revision 3 */ +static void +set_help_v3(void) +{ + printf("set match options:\n" + " [!] --match-set name flags [--return-nomatch]\n" + " [! --update-counters] [! --update-subcounters]\n" + " [[!] --packets-eq value | --packets-lt value | --packets-gt value\n" + " [[!] --bytes-eq value | --bytes-lt value | --bytes-gt value\n" + " 'name' is the set name from to match,\n" + " 'flags' are the comma separated list of\n" + " 'src' and 'dst' specifications.\n"); +} + +static const struct option set_opts_v3[] = { + {.name = "match-set", .has_arg = true, .val = '1'}, + {.name = "set", .has_arg = true, .val = '2'}, + {.name = "return-nomatch", .has_arg = false, .val = '3'}, + {.name = "update-counters", .has_arg = false, .val = '4'}, + {.name = "packets-eq", .has_arg = true, .val = '5'}, + {.name = "packets-lt", .has_arg = true, .val = '6'}, + {.name = "packets-gt", .has_arg = true, .val = '7'}, + {.name = "bytes-eq", .has_arg = true, .val = '8'}, + {.name = "bytes-lt", .has_arg = true, .val = '9'}, + {.name = "bytes-gt", .has_arg = true, .val = '0'}, + {.name = "update-subcounters", .has_arg = false, .val = 'a'}, + XT_GETOPT_TABLEEND, +}; + +static uint64_t +parse_counter(const char *opt) +{ + uintmax_t value; + + if (!xtables_strtoul(opt, NULL, &value, 0, UINT64_MAX)) + xtables_error(PARAMETER_PROBLEM, + "Cannot parse %s as a counter value\n", + opt); + return (uint64_t)value; +} + +static int +set_parse_v3(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct xt_set_info_match_v3 *info = + (struct xt_set_info_match_v3 *) (*match)->data; + + switch (c) { + case 'a': + if (invert) + info->flags |= IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE; + break; + case '0': + if (info->bytes.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --bytes-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--bytes-gt option cannot be inverted\n"); + info->bytes.op = IPSET_COUNTER_GT; + info->bytes.value = parse_counter(optarg); + break; + case '9': + if (info->bytes.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --bytes-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--bytes-lt option cannot be inverted\n"); + info->bytes.op = IPSET_COUNTER_LT; + info->bytes.value = parse_counter(optarg); + break; + case '8': + if (info->bytes.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --bytes-[eq|lt|gt]" + " is allowed\n"); + info->bytes.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; + info->bytes.value = parse_counter(optarg); + break; + case '7': + if (info->packets.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --packets-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--packets-gt option cannot be inverted\n"); + info->packets.op = IPSET_COUNTER_GT; + info->packets.value = parse_counter(optarg); + break; + case '6': + if (info->packets.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --packets-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--packets-lt option cannot be inverted\n"); + info->packets.op = IPSET_COUNTER_LT; + info->packets.value = parse_counter(optarg); + break; + case '5': + if (info->packets.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --packets-[eq|lt|gt]" + " is allowed\n"); + info->packets.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; + info->packets.value = parse_counter(optarg); + break; + case '4': + if (invert) + info->flags |= IPSET_FLAG_SKIP_COUNTER_UPDATE; + break; + case '3': + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--return-nomatch flag cannot be inverted\n"); + info->flags |= IPSET_FLAG_RETURN_NOMATCH; + break; + case '2': + fprintf(stderr, + "--set option deprecated, please use --match-set\n"); + case '1': /* --match-set [, */ + if (info->match_set.dim) + xtables_error(PARAMETER_PROBLEM, + "--match-set can be specified only once"); + if (invert) + info->match_set.flags |= IPSET_INV_MATCH; + + if (!argv[optind] + || argv[optind][0] == '-' + || argv[optind][0] == '!') + xtables_error(PARAMETER_PROBLEM, + "--match-set requires two args."); + + if (strlen(optarg) > IPSET_MAXNAMELEN - 1) + xtables_error(PARAMETER_PROBLEM, + "setname `%s' too long, max %d characters.", + optarg, IPSET_MAXNAMELEN - 1); + + get_set_byname(optarg, &info->match_set); + parse_dirs(argv[optind], &info->match_set); + DEBUGP("parse: set index %u\n", info->match_set.index); + optind++; + + *flags = 1; + break; + } + + return 1; +} + +static void +set_printv3_counter(const struct ip_set_counter_match *c, const char *name, + const char *sep) +{ + switch (c->op) { + case IPSET_COUNTER_EQ: + printf(" %s%s-eq %llu", sep, name, c->value); + break; + case IPSET_COUNTER_NE: + printf(" ! %s%s-eq %llu", sep, name, c->value); + break; + case IPSET_COUNTER_LT: + printf(" %s%s-lt %llu", sep, name, c->value); + break; + case IPSET_COUNTER_GT: + printf(" %s%s-gt %llu", sep, name, c->value); + break; + } +} + +static void +set_print_v3_matchinfo(const struct xt_set_info_match_v3 *info, + const char *opt, const char *sep) +{ + print_match(opt, &info->match_set); + if (info->flags & IPSET_FLAG_RETURN_NOMATCH) + printf(" %sreturn-nomatch", sep); + if ((info->flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) + printf(" ! %supdate-counters", sep); + if ((info->flags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)) + printf(" ! %supdate-subcounters", sep); + set_printv3_counter(&info->packets, "packets", sep); + set_printv3_counter(&info->bytes, "bytes", sep); +} + +/* Prints out the matchinfo. */ +static void +set_print_v3(const void *ip, const struct xt_entry_match *match, int numeric) +{ + const struct xt_set_info_match_v3 *info = (const void *)match->data; + + set_print_v3_matchinfo(info, "match-set", ""); +} + +static void +set_save_v3(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_set_info_match_v3 *info = (const void *)match->data; + + set_print_v3_matchinfo(info, "--match-set", "--"); +} + static struct xtables_match set_mt_reg[] = { { .name = "set", @@ -332,6 +540,20 @@ static struct xtables_match set_mt_reg[] = { .save = set_save_v2, .extra_opts = set_opts_v2, }, + { + .name = "set", + .revision = 3, + .version = XTABLES_VERSION, + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_set_info_match_v3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v3)), + .help = set_help_v3, + .parse = set_parse_v3, + .final_check = set_check_v0, + .print = set_print_v3, + .save = set_save_v3, + .extra_opts = set_opts_v3, + }, }; void _init(void) diff --git a/extensions/libxt_set.man b/extensions/libxt_set.man index ac60f148..7012ef2e 100644 --- a/extensions/libxt_set.man +++ b/extensions/libxt_set.man @@ -15,11 +15,48 @@ the set type of the specified set is single dimension (for example ipmap), then the command will match packets for which the source address can be found in the specified set. .TP -\fB\-\-return\-\-nomatch\fP -If the \fB\-\-return\-\-nomatch\fP option is specified and the set type +\fB\-\-return\-nomatch\fP +If the \fB\-\-return\-nomatch\fP option is specified and the set type supports the \fBnomatch\fP flag, then the matching is reversed: a match with an element flagged with \fBnomatch\fP returns \fBtrue\fP, while a match with a plain element returns \fBfalse\fP. +.TP +\fB!\fP \fB\-\-update\-counters\fP +If the \fB\-\-update\-counters\fP flag is negated, then the packet and +byte counters of the matching element in the set won't be updated. Default +the packet and byte counters are updated. +.TP +\fB!\fP \fB\-\-update\-subcounters\fP +If the \fB\-\-update\-subcounters\fP flag is negated, then the packet and +byte counters of the matching element in the member set of a list type of +set won't be updated. Default the packet and byte counters are updated. +.TP +[\fB!\fP] \fB\-\-packets\-eq\fP \fIvalue\fP +If the packet is matched an element in the set, match only if the +packet counter of the element matches the given value too. +.TP +\fB\-\-packets\-lt\fP \fIvalue\fP +If the packet is matched an element in the set, match only if the +packet counter of the element is less than the given value as well. +.TP +\fB\-\-packets\-gt\fP \fIvalue\fP +If the packet is matched an element in the set, match only if the +packet counter of the element is greater than the given value as well. +.TP +[\fB!\fP] \fB\-bytes\-eq\fP \fIvalue\fP +If the packet is matched an element in the set, match only if the +byte counter of the element matches the given value too. +.TP +\fB\-\-bytes\-lt\fP \fIvalue\fP +If the packet is matched an element in the set, match only if the +byte counter of the element is less than the given value as well. +.TP +\fB\-\-bytes\-gt\fP \fIvalue\fP +If the packet is matched an element in the set, match only if the +byte counter of the element is greater than the given value as well. +.PP +The packet and byte counters related options and flags are ignored +when the set was defined without counter support. .PP The option \fB\-\-match\-set\fP can be replaced by \fB\-\-set\fP if that does not clash with an option of other extensions. diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index fff191d6..eb9123e6 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -1,6 +1,3 @@ -#ifndef _IP_SET_H -#define _IP_SET_H - /* Copyright (C) 2000-2002 Joakim Axelsson * Patrick Schaaf * Martin Josefsson @@ -10,6 +7,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#ifndef _UAPI_IP_SET_H +#define _UAPI_IP_SET_H + #include @@ -108,6 +108,8 @@ enum { IPSET_ATTR_CIDR2, IPSET_ATTR_IP2_TO, IPSET_ATTR_IFACE, + IPSET_ATTR_BYTES, + IPSET_ATTR_PACKETS, __IPSET_ATTR_ADT_MAX, }; #define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1) @@ -137,12 +139,13 @@ enum ipset_errno { IPSET_ERR_REFERENCED, IPSET_ERR_IPADDR_IPV4, IPSET_ERR_IPADDR_IPV6, + IPSET_ERR_COUNTER, /* Type specific error codes */ IPSET_ERR_TYPE_SPECIFIC = 4352, }; -/* Flags at command level */ +/* Flags at command level or match/target flags, lower half of cmdattrs */ enum ipset_cmd_flags { IPSET_FLAG_BIT_EXIST = 0, IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST), @@ -150,14 +153,30 @@ enum ipset_cmd_flags { IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME), IPSET_FLAG_BIT_LIST_HEADER = 2, IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER), + IPSET_FLAG_BIT_SKIP_COUNTER_UPDATE = 3, + IPSET_FLAG_SKIP_COUNTER_UPDATE = + (1 << IPSET_FLAG_BIT_SKIP_COUNTER_UPDATE), + IPSET_FLAG_BIT_SKIP_SUBCOUNTER_UPDATE = 4, + IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE = + (1 << IPSET_FLAG_BIT_SKIP_SUBCOUNTER_UPDATE), + IPSET_FLAG_BIT_MATCH_COUNTERS = 5, + IPSET_FLAG_MATCH_COUNTERS = (1 << IPSET_FLAG_BIT_MATCH_COUNTERS), + IPSET_FLAG_BIT_RETURN_NOMATCH = 7, + IPSET_FLAG_RETURN_NOMATCH = (1 << IPSET_FLAG_BIT_RETURN_NOMATCH), + IPSET_FLAG_CMD_MAX = 15, }; -/* Flags at CADT attribute level */ +/* Flags at CADT attribute level, upper half of cmdattrs */ enum ipset_cadt_flags { IPSET_FLAG_BIT_BEFORE = 0, IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE), IPSET_FLAG_BIT_PHYSDEV = 1, IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV), + IPSET_FLAG_BIT_NOMATCH = 2, + IPSET_FLAG_NOMATCH = (1 << IPSET_FLAG_BIT_NOMATCH), + IPSET_FLAG_BIT_WITH_COUNTERS = 3, + IPSET_FLAG_WITH_COUNTERS = (1 << IPSET_FLAG_BIT_WITH_COUNTERS), + IPSET_FLAG_CADT_MAX = 15, }; /* Commands with settype-specific attributes */ @@ -186,6 +205,7 @@ enum ip_set_dim { * If changed, new revision of iptables match/target is required. */ IPSET_DIM_MAX = 6, + /* Backward compatibility: set match revision 2 */ IPSET_BIT_RETURN_NOMATCH = 7, }; @@ -198,6 +218,18 @@ enum ip_set_kopt { IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH), }; +enum { + IPSET_COUNTER_NONE = 0, + IPSET_COUNTER_EQ, + IPSET_COUNTER_NE, + IPSET_COUNTER_LT, + IPSET_COUNTER_GT, +}; + +struct ip_set_counter_match { + __u8 op; + __u64 value; +}; /* Interface to iptables/ip6tables */ @@ -210,8 +242,8 @@ union ip_set_name_index { #define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */ struct ip_set_req_get_set { - unsigned op; - unsigned version; + unsigned int op; + unsigned int version; union ip_set_name_index set; }; @@ -220,8 +252,8 @@ struct ip_set_req_get_set { #define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */ struct ip_set_req_version { - unsigned op; - unsigned version; + unsigned int op; + unsigned int version; }; -#endif /*_IP_SET_H */ +#endif /* _UAPI_IP_SET_H */ diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h index e3a9978f..964d3d42 100644 --- a/include/linux/netfilter/xt_set.h +++ b/include/linux/netfilter/xt_set.h @@ -62,4 +62,13 @@ struct xt_set_info_target_v2 { __u32 timeout; }; +/* Revision 3 match */ + +struct xt_set_info_match_v3 { + struct xt_set_info match_set; + struct ip_set_counter_match packets; + struct ip_set_counter_match bytes; + __u32 flags; +}; + #endif /*_XT_SET_H*/ -- cgit v1.2.3 From 93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Fri, 31 May 2013 09:07:04 -0400 Subject: ip[6]tables: Add locking to prevent concurrent instances There have been numerous complaints and bug reports over the years when admins attempt to run more than one instance of iptables simultaneously. Currently open bug reports which are related: 325: Parallel execution of the iptables is impossible 758: Retry iptables command on transient failure 764: Doing -Z twice in parallel breaks counters 822: iptables shows negative or other bad packet/byte counts As Patrick notes in 325: "Since this has been a problem people keep running into, I'd suggest to simply add some locking to iptables to catch the most common case." I started looking into alternatives to add locking, and of course the most common/obvious solution is to use a pidfile. But this has various downsides, such as if the application is terminated abnormally and the pidfile isn't cleaned up. And this also requires a writable filesystem. Using a UNIX domain socket file (e.g. in /var/run) has similar issues. Starting in 2.2, Linux added support for abstract sockets. These sockets require no filesystem, and automatically disappear once the application terminates. This is the locking solution I chose to implement in ip[6]tables. As an added bonus, since each network namespace has its own socket pool, an ip[6]tables instance running in one namespace will not lock out an ip[6]tables instance running in another namespace. A filesystem approach would have to recognize and handle multiple network namespaces. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- iptables/ip6tables.8.in | 7 +++++++ iptables/ip6tables.c | 17 ++++++++++++++++- iptables/iptables.8.in | 7 +++++++ iptables/iptables.c | 17 ++++++++++++++++- iptables/xshared.c | 33 +++++++++++++++++++++++++++++++++ iptables/xshared.h | 2 ++ 6 files changed, 81 insertions(+), 2 deletions(-) diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in index 05e0d0f7..5b2a7d76 100644 --- a/iptables/ip6tables.8.in +++ b/iptables/ip6tables.8.in @@ -363,6 +363,13 @@ For appending, insertion, deletion and replacement, this causes detailed information on the rule or rules to be printed. \fB\-v\fP may be specified multiple times to possibly emit more detailed debug statements. .TP +\fB\-w\fP, \fB\-\-wait\fP +Wait for the xtables lock. +To prevent multiple instances of the program from running concurrently, +an attempt will be made to obtain an exclusive lock at launch. By default, +the program will exit if the lock cannot be obtained. This option will +make the program wait until the exclusive lock can be obtained. +.TP \fB\-n\fP, \fB\-\-numeric\fP Numeric output. IP addresses and port numbers will be printed in numeric format. diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index c8d34e2d..eededee1 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -102,6 +102,7 @@ static struct option original_opts[] = { {.name = "numeric", .has_arg = 0, .val = 'n'}, {.name = "out-interface", .has_arg = 1, .val = 'o'}, {.name = "verbose", .has_arg = 0, .val = 'v'}, + {.name = "wait", .has_arg = 0, .val = 'w'}, {.name = "exact", .has_arg = 0, .val = 'x'}, {.name = "version", .has_arg = 0, .val = 'V'}, {.name = "help", .has_arg = 2, .val = 'h'}, @@ -257,6 +258,7 @@ exit_printhelp(const struct xtables_rule_match *matches) " network interface name ([+] for wildcard)\n" " --table -t table table to manipulate (default: `filter')\n" " --verbose -v verbose mode\n" +" --wait -w wait for the xtables lock\n" " --line-numbers print line numbers when listing\n" " --exact -x expand numbers (display exact values)\n" /*"[!] --fragment -f match second or further fragments only\n"*/ @@ -1293,6 +1295,7 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle struct in6_addr *smasks = NULL, *dmasks = NULL; int verbose = 0; + bool wait = false; const char *chain = NULL; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; const char *policy = NULL, *newname = NULL; @@ -1328,7 +1331,7 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle opts = xt_params->orig_opts; while ((cs.c = getopt_long(argc, argv, - "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:g:46", + "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvwnt:m:xc:g:46", opts, NULL)) != -1) { switch (cs.c) { /* @@ -1573,6 +1576,10 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle verbose++; break; + case 'w': + wait = true; + break; + case 'm': command_match(&cs); break; @@ -1724,6 +1731,14 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle "chain name `%s' too long (must be under %u chars)", chain, XT_EXTENSION_MAXNAMELEN); + /* Attempt to acquire the xtables lock */ + if (!xtables_lock(wait)) { + fprintf(stderr, "Another app is currently holding the xtables lock. " + "Perhaps you want to use the -w option?\n"); + xtables_free_opts(1); + exit(RESOURCE_PROBLEM); + } + /* only allocate handle if we weren't called with a handle */ if (!*handle) *handle = ip6tc_init(*table); diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in index 0fba603d..6f310039 100644 --- a/iptables/iptables.8.in +++ b/iptables/iptables.8.in @@ -351,6 +351,13 @@ For appending, insertion, deletion and replacement, this causes detailed information on the rule or rules to be printed. \fB\-v\fP may be specified multiple times to possibly emit more detailed debug statements. .TP +\fB\-w\fP, \fB\-\-wait\fP +Wait for the xtables lock. +To prevent multiple instances of the program from running concurrently, +an attempt will be made to obtain an exclusive lock at launch. By default, +the program will exit if the lock cannot be obtained. This option will +make the program wait until the exclusive lock can be obtained. +.TP \fB\-n\fP, \fB\-\-numeric\fP Numeric output. IP addresses and port numbers will be printed in numeric format. diff --git a/iptables/iptables.c b/iptables/iptables.c index 79fa37b1..f857bebc 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -99,6 +99,7 @@ static struct option original_opts[] = { {.name = "numeric", .has_arg = 0, .val = 'n'}, {.name = "out-interface", .has_arg = 1, .val = 'o'}, {.name = "verbose", .has_arg = 0, .val = 'v'}, + {.name = "wait", .has_arg = 0, .val = 'w'}, {.name = "exact", .has_arg = 0, .val = 'x'}, {.name = "fragments", .has_arg = 0, .val = 'f'}, {.name = "version", .has_arg = 0, .val = 'V'}, @@ -251,6 +252,7 @@ exit_printhelp(const struct xtables_rule_match *matches) " network interface name ([+] for wildcard)\n" " --table -t table table to manipulate (default: `filter')\n" " --verbose -v verbose mode\n" +" --wait -w wait for the xtables lock\n" " --line-numbers print line numbers when listing\n" " --exact -x expand numbers (display exact values)\n" "[!] --fragment -f match second or further fragments only\n" @@ -1289,6 +1291,7 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle struct in_addr *daddrs = NULL, *dmasks = NULL; int verbose = 0; + bool wait = false; const char *chain = NULL; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; const char *policy = NULL, *newname = NULL; @@ -1324,7 +1327,7 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle opts = xt_params->orig_opts; while ((cs.c = getopt_long(argc, argv, - "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:46", + "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvwnt:m:xc:g:46", opts, NULL)) != -1) { switch (cs.c) { /* @@ -1567,6 +1570,10 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle verbose++; break; + case 'w': + wait = true; + break; + case 'm': command_match(&cs); break; @@ -1721,6 +1728,14 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle "chain name `%s' too long (must be under %u chars)", chain, XT_EXTENSION_MAXNAMELEN); + /* Attempt to acquire the xtables lock */ + if (!xtables_lock(wait)) { + fprintf(stderr, "Another app is currently holding the xtables lock. " + "Perhaps you want to use the -w option?\n"); + xtables_free_opts(1); + exit(RESOURCE_PROBLEM); + } + /* only allocate handle if we weren't called with a handle */ if (!*handle) *handle = iptc_init(*table); diff --git a/iptables/xshared.c b/iptables/xshared.c index e61c28c8..6c9992ed 100644 --- a/iptables/xshared.c +++ b/iptables/xshared.c @@ -6,9 +6,15 @@ #include #include #include +#include +#include +#include #include #include "xshared.h" +#define XT_SOCKET_NAME "xtables" +#define XT_SOCKET_LEN 8 + /* * Print out any special helps. A user might like to be able to add a --help * to the commandline, and see expected results. So we call help for all @@ -236,3 +242,30 @@ void xs_init_match(struct xtables_match *match) if (match->init != NULL) match->init(match->m); } + +bool xtables_lock(bool wait) +{ + int i = 0, ret, xt_socket; + struct sockaddr_un xt_addr; + + memset(&xt_addr, 0, sizeof(xt_addr)); + xt_addr.sun_family = AF_UNIX; + strcpy(xt_addr.sun_path+1, XT_SOCKET_NAME); + xt_socket = socket(AF_UNIX, SOCK_STREAM, 0); + /* If we can't even create a socket, fall back to prior (lockless) behavior */ + if (xt_socket < 0) + return true; + + while (1) { + ret = bind(xt_socket, (struct sockaddr*)&xt_addr, + offsetof(struct sockaddr_un, sun_path)+XT_SOCKET_LEN); + if (ret == 0) + return true; + else if (wait == false) + return false; + if (++i % 2 == 0) + fprintf(stderr, "Another app is currently holding the xtables lock; " + "waiting for it to exit...\n"); + sleep(1); + } +} diff --git a/iptables/xshared.h b/iptables/xshared.h index b804aafe..1e2b9b8e 100644 --- a/iptables/xshared.h +++ b/iptables/xshared.h @@ -2,6 +2,7 @@ #define IPTABLES_XSHARED_H 1 #include +#include #include #include #include @@ -83,6 +84,7 @@ extern struct xtables_match *load_proto(struct iptables_command_state *); extern int subcmd_main(int, char **, const struct subcommand *); extern void xs_init_target(struct xtables_target *); extern void xs_init_match(struct xtables_match *); +extern bool xtables_lock(bool wait); extern const struct xtables_afinfo *afinfo; -- cgit v1.2.3 From c5459339b0cae14b733fef0e52b3c9294deac65e Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Mon, 10 Jun 2013 05:35:44 -0400 Subject: iptables: Fix connlabel.conf install location As reported by Danny Rawlins in bug #828, connlabel.conf is unconditionally installed in /etc/xtables instead of using prefix set at configure time. Fix to use sysconfdir variable. This closes bugzilla #828. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index cd008a19..73f1352c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,8 +25,8 @@ tarball: rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION}; install-data-hook: - @mkdir -p -m 755 $(DESTDIR)/etc/xtables/ || : - @test -f /etc/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf $(DESTDIR)/etc/xtables/connlabel.conf || : + @mkdir -p -m 755 @sysconfdir@/xtables/ || : + @test -f @sysconfdir@/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf @sysconfdir@/xtables/connlabel.conf || : config.status: extensions/GNUmakefile.in \ include/xtables-version.h.in include/iptables/internal.h.in -- cgit v1.2.3 From 7c7bf4c1f05d9dcb1e35fda7912bb15159d8db5b Mon Sep 17 00:00:00 2001 From: Alexey Perevalov Date: Thu, 4 Jul 2013 11:26:17 +0400 Subject: doc: clarify DEBUG usage macro Signed-off-by: Alexey Perevalov Signed-off-by: Pablo Neira Ayuso --- INSTALL | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INSTALL b/INSTALL index e17e8441..d62b428c 100644 --- a/INSTALL +++ b/INSTALL @@ -70,6 +70,8 @@ If you want to enable debugging, use (-O0 is used to turn off instruction reordering, which makes debugging much easier.) +To show debug traces you can add -DDEBUG to CFLAGS option + Other notes =========== -- cgit v1.2.3 From 945353a25bbb2dbf88128c27a9169851da6ebf05 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Thu, 20 Jun 2013 16:11:38 -0400 Subject: ip6tables: don't print out /128 Similar to how iptables does not print /32 on IPv4 addresses, ip6tables should not print out /128 on IPv6 addresses. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- libxtables/xtables.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index ebc77b6c..ef5bc072 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -1597,7 +1597,11 @@ const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) strcat(buf, xtables_ip6addr_to_numeric(addrp)); return buf; } - sprintf(buf, "/%d", l); + /* we don't want to see "/128" */ + if (l == 128) + return ""; + else + sprintf(buf, "/%d", l); return buf; } -- cgit v1.2.3 From d7aeda5ed45ac7ca959f12180690caa371b5b14b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 8 Jul 2013 19:34:12 +0200 Subject: ip{6}tables-restore: fix breakage due to new locking approach Since (93587a0 ip[6]tables: Add locking to prevent concurrent instances), ip{6}tables-restore does not work anymore: iptables-restore < x Another app is currently holding the xtables lock. Perhaps you want to use the -w option? do_command{6}(...) is called from ip{6}tables-restore for every iptables command contained in the rule-set file. Thus, hitting the lock error after the second command. Fix it by bypassing the locking in the ip{6}tables-restore path. Signed-off-by: Pablo Neira Ayuso --- include/ip6tables.h | 2 +- include/iptables.h | 2 +- iptables/ip6tables-restore.c | 2 +- iptables/ip6tables-standalone.c | 2 +- iptables/ip6tables.c | 10 ++++++++-- iptables/iptables-restore.c | 2 +- iptables/iptables-standalone.c | 2 +- iptables/iptables.c | 10 ++++++++-- 8 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/ip6tables.h b/include/ip6tables.h index 37d2e0a3..5f1c5b65 100644 --- a/include/ip6tables.h +++ b/include/ip6tables.h @@ -8,7 +8,7 @@ /* Your shared library should call one of these. */ extern int do_command6(int argc, char *argv[], char **table, - struct xtc_handle **handle); + struct xtc_handle **handle, bool restore); extern int for_each_chain6(int (*fn)(const xt_chainlabel, int, struct xtc_handle *), int verbose, int builtinstoo, struct xtc_handle *handle); extern int flush_entries6(const xt_chainlabel chain, int verbose, struct xtc_handle *handle); diff --git a/include/iptables.h b/include/iptables.h index c42613c9..ac9dc0e5 100644 --- a/include/iptables.h +++ b/include/iptables.h @@ -8,7 +8,7 @@ /* Your shared library should call one of these. */ extern int do_command4(int argc, char *argv[], char **table, - struct xtc_handle **handle); + struct xtc_handle **handle, bool restore); extern int delete_chain4(const xt_chainlabel chain, int verbose, struct xtc_handle *handle); extern int flush_entries4(const xt_chainlabel chain, int verbose, diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c index 0e8252f4..b8b9e0dd 100644 --- a/iptables/ip6tables-restore.c +++ b/iptables/ip6tables-restore.c @@ -438,7 +438,7 @@ int ip6tables_restore_main(int argc, char *argv[]) DEBUGP("argv[%u]: %s\n", a, newargv[a]); ret = do_command6(newargc, newargv, - &newargv[2], &handle); + &newargv[2], &handle, true); free_argv(); fflush(stdout); diff --git a/iptables/ip6tables-standalone.c b/iptables/ip6tables-standalone.c index 21b58116..656e08d5 100644 --- a/iptables/ip6tables-standalone.c +++ b/iptables/ip6tables-standalone.c @@ -58,7 +58,7 @@ ip6tables_main(int argc, char *argv[]) init_extensions6(); #endif - ret = do_command6(argc, argv, &table, &handle); + ret = do_command6(argc, argv, &table, &handle, false); if (ret) { ret = ip6tc_commit(handle); ip6tc_free(handle); diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index eededee1..1fb33f6d 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1286,7 +1286,8 @@ static void command_match(struct iptables_command_state *cs) m->extra_opts, &m->option_offset); } -int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle) +int do_command6(int argc, char *argv[], char **table, + struct xtc_handle **handle, bool restore) { struct iptables_command_state cs; struct ip6t_entry *e = NULL; @@ -1577,6 +1578,11 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle break; case 'w': + if (restore) { + xtables_error(PARAMETER_PROBLEM, + "You cannot use `-w' from " + "ip6tables-restore"); + } wait = true; break; @@ -1732,7 +1738,7 @@ int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle chain, XT_EXTENSION_MAXNAMELEN); /* Attempt to acquire the xtables lock */ - if (!xtables_lock(wait)) { + if (!restore && !xtables_lock(wait)) { fprintf(stderr, "Another app is currently holding the xtables lock. " "Perhaps you want to use the -w option?\n"); xtables_free_opts(1); diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 08225139..8c942ff6 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -438,7 +438,7 @@ iptables_restore_main(int argc, char *argv[]) DEBUGP("argv[%u]: %s\n", a, newargv[a]); ret = do_command4(newargc, newargv, - &newargv[2], &handle); + &newargv[2], &handle, true); free_argv(); fflush(stdout); diff --git a/iptables/iptables-standalone.c b/iptables/iptables-standalone.c index 683a44a5..4da1d7f8 100644 --- a/iptables/iptables-standalone.c +++ b/iptables/iptables-standalone.c @@ -58,7 +58,7 @@ iptables_main(int argc, char *argv[]) init_extensions4(); #endif - ret = do_command4(argc, argv, &table, &handle); + ret = do_command4(argc, argv, &table, &handle, false); if (ret) { ret = iptc_commit(handle); iptc_free(handle); diff --git a/iptables/iptables.c b/iptables/iptables.c index f857bebc..fe18e1cc 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1282,7 +1282,8 @@ static void command_match(struct iptables_command_state *cs) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); } -int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle) +int do_command4(int argc, char *argv[], char **table, + struct xtc_handle **handle, bool restore) { struct iptables_command_state cs; struct ipt_entry *e = NULL; @@ -1571,6 +1572,11 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle break; case 'w': + if (restore) { + xtables_error(PARAMETER_PROBLEM, + "You cannot use `-w' from " + "iptables-restore"); + } wait = true; break; @@ -1729,7 +1735,7 @@ int do_command4(int argc, char *argv[], char **table, struct xtc_handle **handle chain, XT_EXTENSION_MAXNAMELEN); /* Attempt to acquire the xtables lock */ - if (!xtables_lock(wait)) { + if (!restore && !xtables_lock(wait)) { fprintf(stderr, "Another app is currently holding the xtables lock. " "Perhaps you want to use the -w option?\n"); xtables_free_opts(1); -- cgit v1.2.3 From 8cf6fb833840d794289f2abf04b2c5cade5a37bf Mon Sep 17 00:00:00 2001 From: Russell Senior Date: Sat, 13 Jul 2013 10:08:07 +0000 Subject: libxt_recent: restore reap functionality to recent module The reap functionality appears to have been accidentally disabled by (74ded72 libxt_recent: add --mask netmask) since iptables 1.4.15 and later. This adds a patch to restore reap functionality for recent_opts_v1. Patch obtained via: http://patchwork.openwrt.org/patch/3812/ Signed-off-by: Russell Senior Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_recent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c index f4ebe6a3..42c866cd 100644 --- a/extensions/libxt_recent.c +++ b/extensions/libxt_recent.c @@ -63,6 +63,8 @@ static const struct xt_option_entry recent_opts_v1[] = { .excl = F_ANY_OP, .flags = XTOPT_INVERT}, {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32, .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)}, + {.name = "reap", .id = O_REAP, .type = XTTYPE_NONE, + .also = F_SECONDS }, {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32, .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)}, {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE, -- cgit v1.2.3 From a963e217528d2849f32ec6516a1f82450c65f588 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 12 Jul 2013 23:20:50 +0200 Subject: extensions: libipt_ULOG: man page should mention NFLOG as replacement Signed-off-by: Florian Westphal --- extensions/libipt_ULOG.man | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/libipt_ULOG.man b/extensions/libipt_ULOG.man index 649b6e3e..c91f7764 100644 --- a/extensions/libipt_ULOG.man +++ b/extensions/libipt_ULOG.man @@ -1,4 +1,5 @@ -This target provides userspace logging of matching packets. When this +This is the deprecated ipv4-only predecessor of the NFLOG target. +It provides userspace logging of matching packets. When this target is set for a rule, the Linux kernel will multicast this packet through a .IR netlink -- cgit v1.2.3 From 51340f7b6a1103b12d86ef488f7140406d80401e Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 15 Jul 2013 16:35:08 +0200 Subject: extensions: libxt_connlabel: use libnetfilter_conntrack Pablo suggested to make it depend on lnf-conntrack, and get rid of the example config file as well. The problem is that the file must be in a fixed path, /etc/xtables/connlabel.conf, else userspace needs to "guess-the-right-file" when translating names to their bit values (and vice versa). Originally "make install" did put an example file into /etc/xtables/, but distributors complained about iptables ignoring the sysconfdir. So rather remove the example file, the man-page explains the format, and connlabels are inherently system-specific anyway. Signed-off-by: Florian Westphal --- Makefile.am | 4 -- configure.ac | 12 ++++ etc/xtables/connlabel.conf | 8 --- extensions/GNUmakefile.in | 5 +- extensions/libxt_connlabel.c | 142 ++++++++--------------------------------- extensions/libxt_connlabel.man | 1 + 6 files changed, 45 insertions(+), 127 deletions(-) delete mode 100644 etc/xtables/connlabel.conf diff --git a/Makefile.am b/Makefile.am index 73f1352c..c38d3600 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,9 +24,5 @@ tarball: tar -C /tmp -cjf ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root ${PACKAGE_TARNAME}-${PACKAGE_VERSION}/; rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION}; -install-data-hook: - @mkdir -p -m 755 @sysconfdir@/xtables/ || : - @test -f @sysconfdir@/xtables/connlabel.conf || $(INSTALL) -m 644 etc/xtables/connlabel.conf @sysconfdir@/xtables/connlabel.conf || : - config.status: extensions/GNUmakefile.in \ include/xtables-version.h.in include/iptables/internal.h.in diff --git a/configure.ac b/configure.ac index d2094945..be216b0f 100644 --- a/configure.ac +++ b/configure.ac @@ -82,6 +82,15 @@ if test "$ac_cv_header_linux_ip_vs_h" != "yes"; then blacklist_modules="$blacklist_modules ipvs"; fi; +PKG_CHECK_MODULES([libnetfilter_conntrack], [libnetfilter_conntrack >= 1.0.4], + [nfconntrack=1], [nfconntrack=0]) +AM_CONDITIONAL([HAVE_LIBNETFILTER_CONNTRACK], [test "$nfconntrack" = 1]) + +if test "$nfconntrack" -ne 1; then + blacklist_modules="$blacklist_modules connlabel"; + echo "WARNING: libnetfilter_conntrack not found, connlabel match will not be built"; +fi; + AC_SUBST([blacklist_modules]) AC_CHECK_SIZEOF([struct ip6_hdr], [], [#include ]) @@ -180,3 +189,6 @@ fi; echo " Host: ${host} GCC binary: ${CC}" + +test x"$blacklist_modules" = "x" || echo " +Iptables modules that will not be built: $blacklist_modules" diff --git a/etc/xtables/connlabel.conf b/etc/xtables/connlabel.conf deleted file mode 100644 index 9167029e..00000000 --- a/etc/xtables/connlabel.conf +++ /dev/null @@ -1,8 +0,0 @@ -# example connlabel.conf mapping file. -# used by the "connlabel" match to translate names to their bit-value. -0 eth0-in -1 eth0-out -2 ppp-in -3 ppp-out -4 bulk-traffic -5 interactive diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 1ae7f74f..14e7c576 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -93,7 +93,7 @@ lib%.so: lib%.oo ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD}; lib%.oo: ${srcdir}/lib%.c - ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; + ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} ${$*_CFLAGADD} -o $@ -c $<; libxt_NOTRACK.so: libxt_CT.so ln -fs $< $@ @@ -103,6 +103,9 @@ libxt_state.so: libxt_conntrack.so # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm +@HAVE_LIBNETFILTER_CONNTRACK_TRUE@xt_connlabel_LIBADD = @libnetfilter_conntrack_LIBS@ + +@HAVE_LIBNETFILTER_CONNTRACK_TRUE@xt_connlabel_CFLAGADD = @libnetfilter_conntrack_CFLAGS@ # # Static bits diff --git a/extensions/libxt_connlabel.c b/extensions/libxt_connlabel.c index ae52901b..c84a1671 100644 --- a/extensions/libxt_connlabel.c +++ b/extensions/libxt_connlabel.c @@ -5,13 +5,14 @@ #include #include #include +#include enum { O_LABEL = 0, O_SET = 1, }; -#define CONNLABEL_CFG "/etc/xtables/connlabel.conf" +static struct nfct_labelmap *map; static void connlabel_mt_help(void) { @@ -28,107 +29,6 @@ static const struct xt_option_entry connlabel_mt_opts[] = { XTOPT_TABLEEND, }; -static int -xtables_parse_connlabel_numerical(const char *s, char **end) -{ - uintmax_t value; - - if (!xtables_strtoul(s, end, &value, 0, XT_CONNLABEL_MAXBIT)) - return -1; - return value; -} - -static bool is_space_posix(int c) -{ - return c == ' ' || c == '\f' || c == '\r' || c == '\t' || c == '\v'; -} - -static char * trim_label(char *label) -{ - char *end; - - while (is_space_posix(*label)) - label++; - end = strchr(label, '\n'); - if (end) - *end = 0; - else - end = strchr(label, '\0'); - end--; - - while (is_space_posix(*end) && end > label) { - *end = 0; - end--; - } - - return *label ? label : NULL; -} - -static void -xtables_get_connlabel(uint16_t bit, char *buf, size_t len) -{ - FILE *fp = fopen(CONNLABEL_CFG, "r"); - char label[1024]; - char *end; - - if (!fp) - goto error; - - while (fgets(label, sizeof(label), fp)) { - int tmp; - - if (label[0] == '#') - continue; - tmp = xtables_parse_connlabel_numerical(label, &end); - if (tmp < 0 || tmp < (int) bit) - continue; - if (tmp > (int) bit) - break; - - end = trim_label(end); - if (!end) - continue; - snprintf(buf, len, "%s", end); - fclose(fp); - return; - } - fclose(fp); - error: - snprintf(buf, len, "%u", (unsigned int) bit); -} - - -static uint16_t xtables_parse_connlabel(const char *s) -{ - FILE *fp = fopen(CONNLABEL_CFG, "r"); - char label[1024]; - char *end; - int bit; - - if (!fp) - xtables_error(PARAMETER_PROBLEM, "label '%s': could not open '%s': %s", - s, CONNLABEL_CFG, strerror(errno)); - - while (fgets(label, sizeof(label), fp)) { - if (label[0] == '#' || !strstr(label, s)) - continue; - bit = xtables_parse_connlabel_numerical(label, &end); - if (bit < 0) - continue; - - end = trim_label(end); - if (!end) - continue; - if (strcmp(end, s) == 0) { - fclose(fp); - return bit; - } - } - fclose(fp); - xtables_error(PARAMETER_PROBLEM, "label '%s' not found in config file %s", - s, CONNLABEL_CFG); -} - static void connlabel_mt_parse(struct xt_option_call *cb) { struct xt_connlabel_mtinfo *info = cb->data; @@ -138,9 +38,10 @@ static void connlabel_mt_parse(struct xt_option_call *cb) switch (cb->entry->id) { case O_LABEL: - tmp = xtables_parse_connlabel_numerical(cb->arg, NULL); - info->bit = tmp < 0 ? xtables_parse_connlabel(cb->arg) : tmp; - + tmp = nfct_labelmap_get_bit(map, cb->arg); + if (tmp < 0) + xtables_error(PARAMETER_PROBLEM, "label '%s' not found", cb->arg); + info->bit = tmp; if (cb->invert) info->options |= XT_CONNLABEL_OP_INVERT; break; @@ -151,6 +52,14 @@ static void connlabel_mt_parse(struct xt_option_call *cb) } +static const char *connlabel_get_name(int b) +{ + const char *name = nfct_labelmap_get_name(map, b); + if (name && strcmp(name, "")) + return name; + return NULL; +} + static void connlabel_mt_print_op(const struct xt_connlabel_mtinfo *info, const char *prefix) { @@ -162,16 +71,15 @@ static void connlabel_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct xt_connlabel_mtinfo *info = (const void *)match->data; - char buf[1024]; + const char *name = connlabel_get_name(info->bit); printf(" connlabel"); if (info->options & XT_CONNLABEL_OP_INVERT) printf(" !"); - if (numeric) { + if (numeric || name == NULL) { printf(" %u", info->bit); } else { - xtables_get_connlabel(info->bit, buf, sizeof(buf)); - printf(" '%s'", buf); + printf(" '%s'", name); } connlabel_mt_print_op(info, ""); } @@ -180,14 +88,14 @@ static void connlabel_mt_save(const void *ip, const struct xt_entry_match *match) { const struct xt_connlabel_mtinfo *info = (const void *)match->data; - char buf[1024]; + const char *name = connlabel_get_name(info->bit); if (info->options & XT_CONNLABEL_OP_INVERT) printf(" !"); - - xtables_get_connlabel(info->bit, buf, sizeof(buf)); - printf(" --label \"%s\"", buf); - + if (name) + printf(" --label \"%s\"", name); + else + printf(" --label \"%u\"", info->bit); connlabel_mt_print_op(info, "--"); } @@ -206,5 +114,11 @@ static struct xtables_match connlabel_mt_reg = { void _init(void) { + map = nfct_labelmap_new(NULL); + if (!map) { + fprintf(stderr, "cannot open connlabel.conf, not registering '%s' match: %s\n", + connlabel_mt_reg.name, strerror(errno)); + return; + } xtables_register_match(&connlabel_mt_reg); } diff --git a/extensions/libxt_connlabel.man b/extensions/libxt_connlabel.man index 9fd2043d..bdaa51e8 100644 --- a/extensions/libxt_connlabel.man +++ b/extensions/libxt_connlabel.man @@ -17,6 +17,7 @@ the time the connection is created. In this case, the match will fail (or succeed, in case \fB\-\-label\fP option was negated). .PP +This match depends on libnetfilter_conntrack 1.0.4 or later. Label translation is done via the \fB/etc/xtables/connlabel.conf\fP configuration file. .PP Example: -- cgit v1.2.3 From 88b73a2bad9fc02355fad70698cc2c9469048abc Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 15 Jul 2013 12:14:55 +0200 Subject: libxt_recent: restore minimum value for --seconds This checking was accidentally removed in (74ded72 libxt_recent: add --mask netmask). Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_recent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c index 42c866cd..b3510d99 100644 --- a/extensions/libxt_recent.c +++ b/extensions/libxt_recent.c @@ -62,7 +62,7 @@ static const struct xt_option_entry recent_opts_v1[] = { {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE, .excl = F_ANY_OP, .flags = XTOPT_INVERT}, {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32, - .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)}, + .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds), .min = 1}, {.name = "reap", .id = O_REAP, .type = XTTYPE_NONE, .also = F_SECONDS }, {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32, -- cgit v1.2.3 From 33b529a7208952c250f245557d248e50ce533c7d Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Sat, 6 Jul 2013 08:56:01 -0700 Subject: libip6t_LOG: target output is different to libipt_LOG libipt_LOG is using the xtables_save_string func, which escapes unsafe characters as needed. libip6t_LOG should do the same. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_LOG.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/extensions/libip6t_LOG.c b/extensions/libip6t_LOG.c index 2b1ae289..4639268d 100644 --- a/extensions/libip6t_LOG.c +++ b/extensions/libip6t_LOG.c @@ -146,8 +146,10 @@ static void LOG_save(const void *ip, const struct xt_entry_target *target) const struct ip6t_log_info *loginfo = (const struct ip6t_log_info *)target->data; - if (strcmp(loginfo->prefix, "") != 0) - printf(" --log-prefix \"%s\"", loginfo->prefix); + if (strcmp(loginfo->prefix, "") != 0) { + printf(" --log-prefix"); + xtables_save_string(loginfo->prefix); + } if (loginfo->level != LOG_DEFAULT_LEVEL) printf(" --log-level %d", loginfo->level); -- cgit v1.2.3 From 7b26bafb9be05a23b47653640aadbb61d0032665 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Mon, 28 Jan 2013 21:32:55 +0100 Subject: libxt_CT: Add the "NOTRACK" alias Available since Linux kernel 3.8. Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_CT.c | 48 +++++++++++++++++++++++++++++++++++++++++ extensions/libxt_NOTRACK.man | 4 ++-- include/linux/netfilter/xt_CT.h | 5 ++++- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index c8437b6c..6b28fe1b 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -195,6 +195,10 @@ ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric) const struct xt_ct_target_info_v1 *info = (const struct xt_ct_target_info_v1 *)target->data; + if (info->flags & XT_CT_NOTRACK_ALIAS) { + printf (" NOTRACK"); + return; + } printf(" CT"); if (info->flags & XT_CT_NOTRACK) printf(" notrack"); @@ -217,6 +221,8 @@ static void ct_save(const void *ip, const struct xt_entry_target *target) const struct xt_ct_target_info *info = (const struct xt_ct_target_info *)target->data; + if (info->flags & XT_CT_NOTRACK_ALIAS) + return; if (info->flags & XT_CT_NOTRACK) printf(" --notrack"); if (info->helper[0]) @@ -236,6 +242,8 @@ static void ct_save_v1(const void *ip, const struct xt_entry_target *target) const struct xt_ct_target_info_v1 *info = (const struct xt_ct_target_info_v1 *)target->data; + if (info->flags & XT_CT_NOTRACK_ALIAS) + return; if (info->flags & XT_CT_NOTRACK) printf(" --notrack"); if (info->helper[0]) @@ -252,6 +260,14 @@ static void ct_save_v1(const void *ip, const struct xt_entry_target *target) printf(" --zone %u", info->zone); } +static const char * +ct_print_name_alias(const struct xt_entry_target *target) +{ + struct xt_ct_target_info *info = (void *)target->data; + + return info->flags & XT_CT_NOTRACK_ALIAS ? "NOTRACK" : "CT"; +} + static void notrack_ct0_tg_init(struct xt_entry_target *target) { struct xt_ct_target_info *info = (void *)target->data; @@ -266,6 +282,13 @@ static void notrack_ct1_tg_init(struct xt_entry_target *target) info->flags = XT_CT_NOTRACK; } +static void notrack_ct2_tg_init(struct xt_entry_target *target) +{ + struct xt_ct_target_info_v1 *info = (void *)target->data; + + info->flags = XT_CT_NOTRACK | XT_CT_NOTRACK_ALIAS; +} + static struct xtables_target ct_target_reg[] = { { .family = NFPROTO_UNSPEC, @@ -292,6 +315,20 @@ static struct xtables_target ct_target_reg[] = { .x6_parse = ct_parse_v1, .x6_options = ct_opts_v1, }, + { + .family = NFPROTO_UNSPEC, + .name = "CT", + .revision = 2, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), + .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), + .help = ct_help_v1, + .print = ct_print_v1, + .save = ct_save_v1, + .alias = ct_print_name_alias, + .x6_parse = ct_parse_v1, + .x6_options = ct_opts_v1, + }, { .family = NFPROTO_UNSPEC, .name = "NOTRACK", @@ -312,6 +349,17 @@ static struct xtables_target ct_target_reg[] = { .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), .init = notrack_ct1_tg_init, }, + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", + .real_name = "CT", + .revision = 2, + .ext_flags = XTABLES_EXT_ALIAS, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), + .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), + .init = notrack_ct2_tg_init, + }, { .family = NFPROTO_UNSPEC, .name = "NOTRACK", diff --git a/extensions/libxt_NOTRACK.man b/extensions/libxt_NOTRACK.man index 633b965e..4302b93a 100644 --- a/extensions/libxt_NOTRACK.man +++ b/extensions/libxt_NOTRACK.man @@ -1,3 +1,3 @@ -This target disables connection tracking for all packets matching that rule. -It is obsoleted by \-j CT \-\-notrack. Like CT, NOTRACK can only be used in +This extension disables connection tracking for all packets matching that rule. +It is equivalent with \-j CT \-\-notrack. Like CT, NOTRACK can only be used in the \fBraw\fP table. diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h index a064b8af..54528fdd 100644 --- a/include/linux/netfilter/xt_CT.h +++ b/include/linux/netfilter/xt_CT.h @@ -3,7 +3,10 @@ #include -#define XT_CT_NOTRACK 0x1 +enum { + XT_CT_NOTRACK = 1 << 0, + XT_CT_NOTRACK_ALIAS = 1 << 1, +}; struct xt_ct_target_info { __u16 flags; -- cgit v1.2.3 From 59bbc59fd2fbbb7a51ed19945d82172890bc40f9 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Sun, 21 Jul 2013 08:30:49 -0700 Subject: build: additional include path required after UAPI changes After kernel commit 607ca46e (UAPI: (Scripted) Disintegrate include/linux), using the "--with-kernel" argument to build iptables stopped working due to the missing #ifdefs in the original files. We need to make sure the UAPI include dir is listed before the original location. Leaving both allows support for old and new kernels. This fixes bug #833. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index be216b0f..5ed51654 100644 --- a/configure.ac +++ b/configure.ac @@ -114,10 +114,10 @@ regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \ -DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL"; kinclude_CPPFLAGS=""; if [[ -n "$kbuilddir" ]]; then - kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$kbuilddir/include"; + kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$kbuilddir/include/uapi -I$kbuilddir/include"; fi; if [[ -n "$ksourcedir" ]]; then - kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$ksourcedir/include"; + kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$ksourcedir/include/uapi -I$ksourcedir/include"; fi; pkgdatadir='${datadir}/xtables'; -- cgit v1.2.3 From c18f2ce7f61c7e7ae3bd207ef6337a1be0c7aff3 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Sun, 21 Jul 2013 20:02:38 -0400 Subject: build: fail in configure on missing dependency with --enable-bpf-compiler The build of utils/nfbpf_compile depends on libpcap. If configure is run with --enable-bpf-compiler, the script succeeds, but make fails. This small patch adds a test for the dependency (libpcap) in configure and fails hard if not found. Signed-off-by: Willem de Bruijn Signed-off-by: Pablo Neira Ayuso --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index 5ed51654..70f4eba3 100644 --- a/configure.ac +++ b/configure.ac @@ -103,6 +103,10 @@ AM_CONDITIONAL([ENABLE_DEVEL], [test "$enable_devel" = "yes"]) AM_CONDITIONAL([ENABLE_LIBIPQ], [test "$enable_libipq" = "yes"]) AM_CONDITIONAL([ENABLE_BPFC], [test "$enable_bpfc" = "yes"]) +if test "x$enable_bpfc" = "xyes"; then + AC_CHECK_LIB(pcap, pcap_compile,, AC_MSG_ERROR(missing libpcap library required by bpf compiler)) +fi + PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0], [nfnetlink=1], [nfnetlink=0]) AM_CONDITIONAL([HAVE_LIBNFNETLINK], [test "$nfnetlink" = 1]) -- cgit v1.2.3 From 68cecd598f55f58a1ae2132cdfb0b5e0a52cae1f Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Thu, 20 Jun 2013 08:53:36 -0400 Subject: iptables: iptables-xml: Fix various parsing bugs There are two bugs in iptables-xml do_rule_part parsing corrected by this patch: 1) Ignore "-A " instead of just "-A" 2) When checking to see if we need a tag, inversion needs to be taken into account This closes netfilter bugzilla #679. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- iptables/iptables-xml.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/iptables/iptables-xml.c b/iptables/iptables-xml.c index 4b12bd46..e272ef91 100644 --- a/iptables/iptables-xml.c +++ b/iptables/iptables-xml.c @@ -367,7 +367,8 @@ static void do_rule_part(char *leveltag1, char *leveltag2, int part, int argc, char *argv[], int argvattr[]) { - int arg = 1; // ignore leading -A + int i; + int arg = 2; // ignore leading -A char invert_next = 0; char *spacer = ""; // space when needed to assemble arguments char *level1 = NULL; @@ -399,11 +400,17 @@ do_rule_part(char *leveltag1, char *leveltag2, int part, int argc, arg++; } - /* Before we start, if the first arg is -[^-] and not -m or -j or -g - then start a dummy tag for old style built-in matches. - We would do this in any case, but no need if it would be empty */ - if (arg < argc && argv[arg][0] == '-' && !isTarget(argv[arg]) - && strcmp(argv[arg], "-m") != 0) { + /* Before we start, if the first arg is -[^-] and not -m or -j or -g + * then start a dummy tag for old style built-in matches. + * We would do this in any case, but no need if it would be empty. + * In the case of negation, we need to look at arg+1 + */ + if (arg < argc && strcmp(argv[arg], "!") == 0) + i = arg + 1; + else + i = arg; + if (i < argc && argv[i][0] == '-' && !isTarget(argv[i]) + && strcmp(argv[i], "-m") != 0) { OPEN_LEVEL(1, "match"); printf(">\n"); } -- cgit v1.2.3 From 20489ff351837a3209838fe5dd6cbbe1478e2bdc Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 26 Jul 2013 16:38:55 +0200 Subject: iptables-xml: fix parameter parsing (similar to 2165f38) Similar to (2165f38 iptables-restore: fix parameter parsing (shows up with gcc-4.7)), make sure iptables-xml doesn't hit the same problem. Signed-off-by: Pablo Neira Ayuso --- iptables/iptables-xml.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iptables/iptables-xml.c b/iptables/iptables-xml.c index e272ef91..96284476 100644 --- a/iptables/iptables-xml.c +++ b/iptables/iptables-xml.c @@ -740,6 +740,7 @@ iptables_xml_main(int argc, char *argv[]) /* the parser */ char *param_start, *curchar; int quote_open, quoted; + char param_buffer[1024]; /* reset the newargv */ newargc = 0; @@ -799,7 +800,6 @@ iptables_xml_main(int argc, char *argv[]) } if (*curchar == ' ' || *curchar == '\t' || *curchar == '\n') { - char param_buffer[1024]; int param_len = curchar - param_start; if (quote_open) -- cgit v1.2.3 From 8643adc8f0f0fe1e22ca0de0503eee0ee1e22bf5 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 6 Aug 2013 17:48:43 +0200 Subject: iptables 1.4.20 release Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 70f4eba3..f8affedd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT([iptables], [1.4.19.1]) +AC_INIT([iptables], [1.4.20]) # See libtool.info "Libtool's versioning system" libxtables_vcurrent=10 -- cgit v1.2.3 From 71a2b0c78a58387ec476673f1abc75e635ca62f6 Mon Sep 17 00:00:00 2001 From: Lutz Jaenicke Date: Wed, 7 Aug 2013 10:09:16 +0200 Subject: iptables: correctly reference generated file Since (14bca55 iptables: use autoconf to process .in man pages), the file "iptables-extensions.8.tmpl" is generated from "iptables-extensions.8.tmpl.in" and is consequently no longer found in ${srcdir} but in the build directory. (Becomes visible with builddir != srcdir) Signed-off-by: Lutz Jaenicke Signed-off-by: Pablo Neira Ayuso --- iptables/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iptables/Makefile.am b/iptables/Makefile.am index 46d24630..501e8255 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -38,7 +38,7 @@ if ENABLE_IPV6 v6_sbin_links = ip6tables ip6tables-restore ip6tables-save endif -iptables-extensions.8: ${srcdir}/iptables-extensions.8.tmpl ../extensions/matches.man ../extensions/targets.man +iptables-extensions.8: iptables-extensions.8.tmpl ../extensions/matches.man ../extensions/targets.man ${AM_VERBOSE_GEN} sed \ -e '/@MATCH@/ r ../extensions/matches.man' \ -e '/@TARGET@/ r ../extensions/targets.man' $< >$@; -- cgit v1.2.3 From b28d4dcc9f5559e9c03f35458ac103cfb89d8f87 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Wed, 7 Aug 2013 16:44:49 -0700 Subject: iptables: state match incompatibilty across versions As reported in Debian bug #718810 [1], state match rules added in < 1.4.16 iptables versions are incorrectly displayed by >= 1.4.16 iptables versions. Issue bisected to commit 0d701631 (libxt_state: replace as an alias to xt_conntrack). Fix this by adding the missing .print and .save functions for state match aliases in the conntrack match. [1] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=718810 Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_conntrack.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index 9f7b5db2..128bbd20 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -1272,6 +1272,8 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), .help = state_help, + .print = state_print, + .save = state_save, .x6_parse = state_ct1_parse, .x6_options = state_opts, }, @@ -1285,6 +1287,8 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), .help = state_help, + .print = state_print, + .save = state_save, .x6_parse = state_ct23_parse, .x6_options = state_opts, }, @@ -1298,6 +1302,8 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), .help = state_help, + .print = state_print, + .save = state_save, .x6_parse = state_ct23_parse, .x6_options = state_opts, }, -- cgit v1.2.3 From 76e230e41947576efb96e86e605bb84015cdb287 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 13 Aug 2013 21:02:06 +0200 Subject: iptables: link against libnetfilter_conntrack Linking currently fails in --enable-static case: ../extensions/libext.a(libxt_connlabel.o): In function `connlabel_get_name': iptables/extensions/libxt_connlabel.c:57: undefined reference to `nfct_labelmap_get_name' [..] It's libxtables.la(libxt_connlabel.o) using libnetfilter_conntrack. If libnetfilter_conntrack is not found, @libnetfilter_conntrack_CFLAGS@ and @libnetfilter_conntrack_LIBS@ (and their ${} ones) should be empty, therefore producing no harm to include unconditionally. Reported-and-tested-by: Gustavo Zacarias Signed-off-by: Florian Westphal --- extensions/GNUmakefile.in | 8 +++----- libxtables/Makefile.am | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 14e7c576..780e7150 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -21,7 +21,7 @@ regular_CPPFLAGS = @regular_CPPFLAGS@ kinclude_CPPFLAGS = @kinclude_CPPFLAGS@ AM_CFLAGS = ${regular_CFLAGS} -AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_builddir} -I${top_srcdir}/include ${kinclude_CPPFLAGS} +AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_builddir} -I${top_srcdir}/include ${kinclude_CPPFLAGS} @libnetfilter_conntrack_CFLAGS@ AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@ AM_LDFLAGS = @noundef_LDFLAGS@ @@ -93,7 +93,7 @@ lib%.so: lib%.oo ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD}; lib%.oo: ${srcdir}/lib%.c - ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} ${$*_CFLAGADD} -o $@ -c $<; + ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; libxt_NOTRACK.so: libxt_CT.so ln -fs $< $@ @@ -103,9 +103,7 @@ libxt_state.so: libxt_conntrack.so # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm -@HAVE_LIBNETFILTER_CONNTRACK_TRUE@xt_connlabel_LIBADD = @libnetfilter_conntrack_LIBS@ - -@HAVE_LIBNETFILTER_CONNTRACK_TRUE@xt_connlabel_CFLAGADD = @libnetfilter_conntrack_CFLAGS@ +xt_connlabel_LIBADD = @libnetfilter_conntrack_LIBS@ # # Static bits diff --git a/libxtables/Makefile.am b/libxtables/Makefile.am index c5795fef..4267cb5f 100644 --- a/libxtables/Makefile.am +++ b/libxtables/Makefile.am @@ -10,7 +10,7 @@ libxtables_la_LIBADD = if ENABLE_STATIC # With --enable-static, shipped extensions are linked into the main executable, # so we need all the LIBADDs here too -libxtables_la_LIBADD += -lm +libxtables_la_LIBADD += -lm ${libnetfilter_conntrack_LIBS} endif if ENABLE_SHARED libxtables_la_CFLAGS = ${AM_CFLAGS} -- cgit v1.2.3