From c8f28cc8b84133f20421470e9a61a5a0c78b9c4a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 20 Jan 2011 11:45:12 +0100 Subject: extensions: libxt_conntrack: add support for specifying port ranges Add support for revision 3 of the conntrack match, which allows to specify port ranges for origsrc/origdst/replsrc/repldst. Signed-off-by: Patrick McHardy --- extensions/libxt_conntrack.c | 252 ++++++++++++++++++++++++++++++----------- extensions/libxt_conntrack.man | 9 +- 2 files changed, 192 insertions(+), 69 deletions(-) (limited to 'extensions') diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index f21d1ab8..8d8e1b23 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -149,7 +149,7 @@ parse_states(const char *arg, struct xt_conntrack_info *sinfo) } static bool -conntrack_ps_state(struct xt_conntrack_mtinfo2 *info, const char *state, +conntrack_ps_state(struct xt_conntrack_mtinfo3 *info, const char *state, size_t z) { if (strncasecmp(state, "INVALID", z) == 0) @@ -172,7 +172,7 @@ conntrack_ps_state(struct xt_conntrack_mtinfo2 *info, const char *state, } static void -conntrack_ps_states(struct xt_conntrack_mtinfo2 *info, const char *arg) +conntrack_ps_states(struct xt_conntrack_mtinfo3 *info, const char *arg) { const char *comma; @@ -223,7 +223,7 @@ parse_statuses(const char *arg, struct xt_conntrack_info *sinfo) } static bool -conntrack_ps_status(struct xt_conntrack_mtinfo2 *info, const char *status, +conntrack_ps_status(struct xt_conntrack_mtinfo3 *info, const char *status, size_t z) { if (strncasecmp(status, "NONE", z) == 0) @@ -242,7 +242,7 @@ conntrack_ps_status(struct xt_conntrack_mtinfo2 *info, const char *status, } static void -conntrack_ps_statuses(struct xt_conntrack_mtinfo2 *info, const char *arg) +conntrack_ps_statuses(struct xt_conntrack_mtinfo3 *info, const char *arg) { const char *comma; @@ -297,7 +297,7 @@ parse_expires(const char *s, struct xt_conntrack_info *sinfo) } static void -conntrack_ps_expires(struct xt_conntrack_mtinfo2 *info, const char *s) +conntrack_ps_expires(struct xt_conntrack_mtinfo3 *info, const char *s) { unsigned int min, max; char *end; @@ -467,11 +467,51 @@ static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags, return 1; } +static void +ct_parse_ports(const char *param, const char *str, + u_int16_t *port_low, u_int16_t *port_high) +{ + unsigned int port; + char *buf, *cp; + + buf = strdup(str); + cp = strchr(buf, ':'); + if (cp != NULL) + *cp = '\0'; + + if (!xtables_strtoui(buf, NULL, &port, 0, UINT16_MAX)) + xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf); + + if (port_high == NULL) { + /* revision 0-2 do not support ranges */ + if (cp != NULL) + xtables_error(PARAMETER_PROBLEM, "conntrack: " + "port ranges not supported"); + + *port_low = htons(port); + } else { + *port_low = port; + + if (cp != NULL) { + if (!xtables_strtoui(cp + 1, NULL, &port, 0, UINT16_MAX)) + xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf); + + *port_high = port; + if (*port_low > *port_high) + xtables_error(PARAMETER_PROBLEM, + "invalid portrange (min > max)"); + } else + *port_high = port; + } + + free(buf); +} + + static int conntrack_mt_parse(int c, bool invert, unsigned int *flags, - struct xt_conntrack_mtinfo2 *info) + struct xt_conntrack_mtinfo3 *info, bool v3) { - unsigned int port; char *p; switch (c) { @@ -512,41 +552,41 @@ conntrack_mt_parse(int c, bool invert, unsigned int *flags, break; case 'a': /* --ctorigsrcport */ - if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX)) - xtables_param_act(XTF_BAD_VALUE, "conntrack", - "--ctorigsrcport", optarg); + ct_parse_ports("--ctorigsrcport", optarg, + &info->origsrc_port, + v3 ? &info->origsrc_port_high : NULL); + info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT; - info->origsrc_port = htons(port); if (invert) info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT; break; case 'b': /* --ctorigdstport */ - if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX)) - xtables_param_act(XTF_BAD_VALUE, "conntrack", - "--ctorigdstport", optarg); + ct_parse_ports("--ctorigdstport", optarg, + &info->origdst_port, + v3 ? &info->origdst_port_high : NULL); + info->match_flags |= XT_CONNTRACK_ORIGDST_PORT; - info->origdst_port = htons(port); if (invert) info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT; break; case 'c': /* --ctreplsrcport */ - if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX)) - xtables_param_act(XTF_BAD_VALUE, "conntrack", - "--ctreplsrcport", optarg); + ct_parse_ports("--ctreplsrcport", optarg, + &info->replsrc_port, + v3 ? &info->replsrc_port_high : NULL); + info->match_flags |= XT_CONNTRACK_REPLSRC_PORT; - info->replsrc_port = htons(port); if (invert) info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT; break; case 'd': /* --ctrepldstport */ - if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX)) - xtables_param_act(XTF_BAD_VALUE, "conntrack", - "--ctrepldstport", optarg); + ct_parse_ports("--ctrepldstport", optarg, + &info->repldst_port, + v3 ? &info->repldst_port_high : NULL); + info->match_flags |= XT_CONNTRACK_REPLDST_PORT; - info->repldst_port = htons(port); if (invert) info->invert_flags |= XT_CONNTRACK_REPLDST_PORT; break; @@ -571,7 +611,7 @@ conntrack_mt_parse(int c, bool invert, unsigned int *flags, static int conntrack_mt4_parse(int c, bool invert, unsigned int *flags, - struct xt_conntrack_mtinfo2 *info) + struct xt_conntrack_mtinfo3 *info, bool v3) { struct in_addr *addr = NULL; unsigned int naddrs = 0; @@ -631,7 +671,7 @@ conntrack_mt4_parse(int c, bool invert, unsigned int *flags, default: - return conntrack_mt_parse(c, invert, flags, info); + return conntrack_mt_parse(c, invert, flags, info, v3); } *flags = info->match_flags; @@ -640,7 +680,7 @@ conntrack_mt4_parse(int c, bool invert, unsigned int *flags, static int conntrack_mt6_parse(int c, bool invert, unsigned int *flags, - struct xt_conntrack_mtinfo2 *info) + struct xt_conntrack_mtinfo3 *info, bool v3) { struct in6_addr *addr = NULL; unsigned int naddrs = 0; @@ -700,7 +740,7 @@ conntrack_mt6_parse(int c, bool invert, unsigned int *flags, default: - return conntrack_mt_parse(c, invert, flags, info); + return conntrack_mt_parse(c, invert, flags, info, v3); } *flags = info->match_flags; @@ -719,10 +759,10 @@ conntrack1_mt4_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data; - struct xt_conntrack_mtinfo2 up; + struct xt_conntrack_mtinfo3 up; cinfo_transform(&up, info); - if (!conntrack_mt4_parse(c, invert, flags, &up)) + if (!conntrack_mt4_parse(c, invert, flags, &up, false)) return false; cinfo_transform(info, &up); return true; @@ -733,10 +773,10 @@ conntrack1_mt6_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data; - struct xt_conntrack_mtinfo2 up; + struct xt_conntrack_mtinfo3 up; cinfo_transform(&up, info); - if (!conntrack_mt6_parse(c, invert, flags, &up)) + if (!conntrack_mt6_parse(c, invert, flags, &up, false)) return false; cinfo_transform(info, &up); return true; @@ -746,14 +786,28 @@ static int conntrack2_mt4_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { - return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data); + return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, false); } static int conntrack2_mt6_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { - return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data); + return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, false); +} + +static int +conntrack3_mt4_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, true); +} + +static int +conntrack3_mt6_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, true); } static void conntrack_mt_check(unsigned int flags) @@ -976,8 +1030,18 @@ matchinfo_print(const void *ip, const struct xt_entry_match *match, int numeric, } static void -conntrack_dump(const struct xt_conntrack_mtinfo2 *info, const char *prefix, - unsigned int family, bool numeric) +conntrack_dump_ports(const char *prefix, const char *opt, + u_int16_t port_low, u_int16_t port_high) +{ + if (port_high == 0 || port_low == port_high) + printf("%s%s %u ", prefix, opt, port_low); + else + printf("%s%s %u:%u ", prefix, opt, port_low, port_high); +} + +static void +conntrack_dump(const struct xt_conntrack_mtinfo3 *info, const char *prefix, + unsigned int family, bool numeric, bool v3) { if (info->match_flags & XT_CONNTRACK_STATE) { if (info->invert_flags & XT_CONNTRACK_STATE) @@ -1027,29 +1091,33 @@ conntrack_dump(const struct xt_conntrack_mtinfo2 *info, const char *prefix, if (info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) { if (info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT) printf("! "); - printf("%sctorigsrcport %u ", prefix, - ntohs(info->origsrc_port)); + conntrack_dump_ports(prefix, "ctorigsrcport", + v3 ? info->origsrc_port : ntohs(info->origsrc_port), + v3 ? info->origsrc_port_high : 0); } if (info->match_flags & XT_CONNTRACK_ORIGDST_PORT) { if (info->invert_flags & XT_CONNTRACK_ORIGDST_PORT) printf("! "); - printf("%sctorigdstport %u ", prefix, - ntohs(info->origdst_port)); + conntrack_dump_ports(prefix, "ctorigdstport", + v3 ? info->origdst_port : ntohs(info->origdst_port), + v3 ? info->origdst_port_high : 0); } if (info->match_flags & XT_CONNTRACK_REPLSRC_PORT) { if (info->invert_flags & XT_CONNTRACK_REPLSRC_PORT) printf("! "); - printf("%sctreplsrcport %u ", prefix, - ntohs(info->replsrc_port)); + conntrack_dump_ports(prefix, "ctreplsrcport", + v3 ? info->replsrc_port : ntohs(info->replsrc_port), + v3 ? info->replsrc_port_high : 0); } if (info->match_flags & XT_CONNTRACK_REPLDST_PORT) { if (info->invert_flags & XT_CONNTRACK_REPLDST_PORT) printf("! "); - printf("%sctrepldstport %u ", prefix, - ntohs(info->repldst_port)); + conntrack_dump_ports(prefix, "ctrepldstport", + v3 ? info->repldst_port : ntohs(info->repldst_port), + v3 ? info->repldst_port_high : 0); } if (info->match_flags & XT_CONNTRACK_STATUS) { @@ -1090,10 +1158,10 @@ conntrack1_mt4_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct xt_conntrack_mtinfo1 *info = (void *)match->data; - struct xt_conntrack_mtinfo2 up; + struct xt_conntrack_mtinfo3 up; cinfo_transform(&up, info); - conntrack_dump(&up, "", NFPROTO_IPV4, numeric); + conntrack_dump(&up, "", NFPROTO_IPV4, numeric, false); } static void @@ -1101,24 +1169,38 @@ conntrack1_mt6_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct xt_conntrack_mtinfo1 *info = (void *)match->data; - struct xt_conntrack_mtinfo2 up; + struct xt_conntrack_mtinfo3 up; cinfo_transform(&up, info); - conntrack_dump(&up, "", NFPROTO_IPV6, numeric); + conntrack_dump(&up, "", NFPROTO_IPV6, numeric, false); } static void -conntrack_mt_print(const void *ip, const struct xt_entry_match *match, - int numeric) +conntrack2_mt_print(const void *ip, const struct xt_entry_match *match, + int numeric) { - conntrack_dump((const void *)match->data, "", NFPROTO_IPV4, numeric); + conntrack_dump((const void *)match->data, "", NFPROTO_IPV4, numeric, false); } static void -conntrack_mt6_print(const void *ip, const struct xt_entry_match *match, +conntrack2_mt6_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + conntrack_dump((const void *)match->data, "", NFPROTO_IPV6, numeric, false); +} + +static void +conntrack3_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) { - conntrack_dump((const void *)match->data, "", NFPROTO_IPV6, numeric); + conntrack_dump((const void *)match->data, "", NFPROTO_IPV4, numeric, true); +} + +static void +conntrack3_mt6_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + conntrack_dump((const void *)match->data, "", NFPROTO_IPV6, numeric, true); } static void conntrack_save(const void *ip, const struct xt_entry_match *match) @@ -1126,36 +1208,48 @@ static void conntrack_save(const void *ip, const struct xt_entry_match *match) matchinfo_print(ip, match, 1, "--"); } -static void conntrack_mt_save(const void *ip, - const struct xt_entry_match *match) +static void conntrack3_mt_save(const void *ip, + const struct xt_entry_match *match) +{ + conntrack_dump((const void *)match->data, "--", NFPROTO_IPV4, true, true); +} + +static void conntrack3_mt6_save(const void *ip, + const struct xt_entry_match *match) { - conntrack_dump((const void *)match->data, "--", NFPROTO_IPV4, true); + conntrack_dump((const void *)match->data, "--", NFPROTO_IPV6, true, true); } -static void conntrack_mt6_save(const void *ip, +static void conntrack2_mt_save(const void *ip, const struct xt_entry_match *match) { - conntrack_dump((const void *)match->data, "--", NFPROTO_IPV6, true); + conntrack_dump((const void *)match->data, "--", NFPROTO_IPV4, true, false); +} + +static void conntrack2_mt6_save(const void *ip, + const struct xt_entry_match *match) +{ + conntrack_dump((const void *)match->data, "--", NFPROTO_IPV6, true, false); } static void conntrack1_mt4_save(const void *ip, const struct xt_entry_match *match) { const struct xt_conntrack_mtinfo1 *info = (void *)match->data; - struct xt_conntrack_mtinfo2 up; + struct xt_conntrack_mtinfo3 up; cinfo_transform(&up, info); - conntrack_dump(&up, "--", NFPROTO_IPV4, true); + conntrack_dump(&up, "--", NFPROTO_IPV4, true, false); } static void conntrack1_mt6_save(const void *ip, const struct xt_entry_match *match) { const struct xt_conntrack_mtinfo1 *info = (void *)match->data; - struct xt_conntrack_mtinfo2 up; + struct xt_conntrack_mtinfo3 up; cinfo_transform(&up, info); - conntrack_dump(&up, "--", NFPROTO_IPV6, true); + conntrack_dump(&up, "--", NFPROTO_IPV6, true, false); } static struct xtables_match conntrack_mt_reg[] = { @@ -1211,8 +1305,8 @@ static struct xtables_match conntrack_mt_reg[] = { .help = conntrack_mt_help, .parse = conntrack2_mt4_parse, .final_check = conntrack_mt_check, - .print = conntrack_mt_print, - .save = conntrack_mt_save, + .print = conntrack2_mt_print, + .save = conntrack2_mt_save, .extra_opts = conntrack_mt_opts, }, { @@ -1225,8 +1319,36 @@ static struct xtables_match conntrack_mt_reg[] = { .help = conntrack_mt_help, .parse = conntrack2_mt6_parse, .final_check = conntrack_mt_check, - .print = conntrack_mt6_print, - .save = conntrack_mt6_save, + .print = conntrack2_mt6_print, + .save = conntrack2_mt6_save, + .extra_opts = conntrack_mt_opts, + }, + { + .version = XTABLES_VERSION, + .name = "conntrack", + .revision = 3, + .family = NFPROTO_IPV4, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .help = conntrack_mt_help, + .parse = conntrack3_mt4_parse, + .final_check = conntrack_mt_check, + .print = conntrack3_mt_print, + .save = conntrack3_mt_save, + .extra_opts = conntrack_mt_opts, + }, + { + .version = XTABLES_VERSION, + .name = "conntrack", + .revision = 3, + .family = NFPROTO_IPV6, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .help = conntrack_mt_help, + .parse = conntrack3_mt6_parse, + .final_check = conntrack_mt_check, + .print = conntrack3_mt6_print, + .save = conntrack3_mt6_save, .extra_opts = conntrack_mt_opts, }, }; diff --git a/extensions/libxt_conntrack.man b/extensions/libxt_conntrack.man index d37ed171..c397f742 100644 --- a/extensions/libxt_conntrack.man +++ b/extensions/libxt_conntrack.man @@ -17,14 +17,15 @@ Layer-4 protocol to match (by number or name) [\fB!\fP] \fB\-\-ctrepldst\fP \fIaddress\fP[\fB/\fP\fImask\fP] Match against original/reply source/destination address .TP -[\fB!\fP] \fB\-\-ctorigsrcport\fP \fIport\fP +[\fB!\fP] \fB\-\-ctorigsrcport\fP \fIport\fP[\fB:\fP\fIport\fP] .TP -[\fB!\fP] \fB\-\-ctorigdstport\fP \fIport\fP +[\fB!\fP] \fB\-\-ctorigdstport\fP \fIport\fP[\fB:\fP\fIport\fP] .TP -[\fB!\fP] \fB\-\-ctreplsrcport\fP \fIport\fP +[\fB!\fP] \fB\-\-ctreplsrcport\fP \fIport\fP[\fB:\fP\fIport\fP] .TP -[\fB!\fP] \fB\-\-ctrepldstport\fP \fIport\fP +[\fB!\fP] \fB\-\-ctrepldstport\fP \fIport\fP[\fB:\fP\fIport\fP] Match against original/reply source/destination port (TCP/UDP/etc.) or GRE key. +Matching against port ranges is only supported in kernel versions above 2.6.38. .TP [\fB!\fP] \fB\-\-ctstatus\fP \fIstatelist\fP \fIstatuslist\fP is a comma separated list of the connection statuses to match. -- cgit v1.2.3