Add support for using CIDR notation in --{orig,tuple}-{src,dst} arguments, instead of free-form formatting netmask in --mask-{src,dst}. Example: conntrack -L -s 2001:db8::/56 Instead of: conntrack -L -s 2001:db8:: --mask-src ffff:ffff:ffff:ff00:: Signed-off-by: Asbjørn Sloth Tønnesen <ast@xxxxxxxxxx> --- conntrack.8 | 4 +++ src/conntrack.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/conntrack.8 b/conntrack.8 index 5bba1b1..f2c1ca5 100644 --- a/conntrack.8 +++ b/conntrack.8 @@ -117,9 +117,11 @@ This option can only be used in conjunction with "\-E, \-\-event". .TP .BI "-s, --orig-src " IP_ADDRESS Match only entries whose source address in the original direction equals the one specified as argument. +Implies "--mask-src" when CIDR notation is used. .TP .BI "-d, --orig-dst " IP_ADDRESS Match only entries whose destination address in the original direction equals the one specified as argument. +Implies "--mask-dst" when CIDR notation is used. .TP .BI "-r, --reply-src " IP_ADDRESS Match only entries whose source address in the reply direction equals the one specified as argument. @@ -186,9 +188,11 @@ See iptables CT target for more information. .TP .BI "--tuple-src " IP_ADDRESS Specify the tuple source address of an expectation. +Implies "--mask-src" when CIDR notation is used. .TP .BI "--tuple-dst " IP_ADDRESS Specify the tuple destination address of an expectation. +Implies "--mask-dst" when CIDR notation is used. .TP .BI "--mask-src " IP_ADDRESS Specify the source address mask. diff --git a/src/conntrack.c b/src/conntrack.c index dfc2de8..d8b60a4 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -434,6 +434,17 @@ static const int opt2type[] = { [')'] = CT_OPT_REPL_ZONE, }; +static const int opt2maskopt[] = { + ['s'] = '{', + ['d'] = '}', + ['r'] = 0, /* no netmask */ + ['q'] = 0, /* support yet */ + ['{'] = 0, + ['}'] = 0, + ['['] = '{', + [']'] = '}', +}; + static const int opt2family_attr[][2] = { ['s'] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC }, ['d'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST }, @@ -684,6 +695,21 @@ static int bit2cmd(int command) return i; } +static const char * +get_long_opt(int opt) +{ + struct option o; + int i; + + for (i = 0 ; ; i++) { + o = opts[i]; + if (o.name == NULL) break; + if (o.val == opt) + return o.name; + } + return "unknown"; +} + int generic_opt_check(int local_options, int num_opts, char *optset, const char *optflg[], unsigned int *coupled_flags, int coupled_flags_size, @@ -2104,6 +2130,24 @@ static void merge_bitmasks(struct nfct_bitmask **current, } static void +nfct_build_netmask(uint32_t *dst, int b, int n) +{ + int i; + + for (i=0;i<n;i++) { + if (b >= 32) { + dst[i] = 0xffffffff; + b -= 32; + } else if (b > 0) { + dst[i] = (1<<b)-1; + b = 0; + } else { + dst[i] = 0; + } + } +} + +static void nfct_set_addr_opt(int opt, struct nf_conntrack *ct, union ct_address *ad, int l3protonum) { @@ -2125,17 +2169,47 @@ nfct_set_addr_opt(int opt, struct nf_conntrack *ct, union ct_address *ad, static void nfct_parse_addr_from_opt(int opt, struct nf_conntrack *ct, + struct nf_conntrack *ctmask, union ct_address *ad, int *family) { - int l3protonum; + int l3protonum, mask, maskopt; - l3protonum = parse_addr(optarg, ad, NULL); + l3protonum = parse_addr(optarg, ad, &mask); if (l3protonum == AF_UNSPEC) { exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'", optarg); } set_family(family, l3protonum); + maskopt = opt2maskopt[opt]; + if (!maskopt && mask != -1) { + exit_error(PARAMETER_PROBLEM, + "CIDR notation unavailable" + " for `--%s'", get_long_opt(opt)); + } else if (mask == -2) { + exit_error(PARAMETER_PROBLEM, + "Invalid netmask"); + } + nfct_set_addr_opt(opt, ct, ad, l3protonum); + + /* bail if we don't have a netmask to set*/ + if (!maskopt || mask == -1 || ctmask == NULL) + return; + + switch(l3protonum) { + case AF_INET: + if (mask == 32) + return; + nfct_build_netmask(&ad->v4, mask, 1); + break; + case AF_INET6: + if (mask == 128) + return; + nfct_build_netmask((uint32_t *) &ad->v6, mask, 4); + break; + } + + nfct_set_addr_opt(maskopt, ctmask, ad, l3protonum); } int main(int argc, char *argv[]) @@ -2216,15 +2290,17 @@ int main(int argc, char *argv[]) case 'd': case 'r': case 'q': - nfct_parse_addr_from_opt(c, tmpl.ct, &ad, &family); + nfct_parse_addr_from_opt(c, tmpl.ct, tmpl.mask, + &ad, &family); break; case '[': case ']': - nfct_parse_addr_from_opt(c, tmpl.exptuple, &ad, &family); + nfct_parse_addr_from_opt(c, tmpl.exptuple, tmpl.mask, + &ad, &family); break; case '{': case '}': - nfct_parse_addr_from_opt(c, tmpl.mask, &ad, &family); + nfct_parse_addr_from_opt(c, tmpl.mask, NULL, &ad, &family); break; case 'p': options |= CT_OPT_PROTO; -- 2.6.4 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html