From e44561766b025600e4af55a35166db46206dd42c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 4 Oct 2008 11:32:37 +0200 Subject: conntrack: fix filtering for unsupported protocol This patch fixes filtering for unsupported protocol. Thus, you can use -L -p 47 or -L -p gre to filter `gre' traffic. Based on an initial patch from Bryan Duff . Signed-off-by: Pablo Neira Ayuso --- src/Makefile.am | 2 +- src/conntrack.c | 66 +++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 805e50d..82f7dfe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ CLEANFILES = read_config_yy.c read_config_lex.c sbin_PROGRAMS = conntrack conntrackd conntrack_SOURCES = conntrack.c -conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la +conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_unknown.la conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ diff --git a/src/conntrack.c b/src/conntrack.c index 73c102b..eccaa7b 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -53,6 +53,7 @@ #endif #include #include +#include #include static const char cmdflags[NUMBER_OF_CMD] @@ -156,26 +157,61 @@ void register_proto(struct ctproto_handler *h) list_add(&h->head, &proto_list); } -static struct ctproto_handler *findproto(char *name) +extern struct ctproto_handler ct_proto_unknown; + +static struct ctproto_handler *findproto(char *name, int *pnum) { struct ctproto_handler *cur; + struct protoent *pent; + int protonum; - if (!name) - return NULL; - + /* is it in the list of supported protocol? */ list_for_each_entry(cur, &proto_list, head) { - if (strcmp(cur->name, name) == 0) + if (strcmp(cur->name, name) == 0) { + *pnum = cur->protonum; return cur; + } + } + /* using the protocol name for an unsupported protocol? */ + if ((pent = getprotobyname(name))) { + *pnum = pent->p_proto; + return &ct_proto_unknown; + } + /* using a protocol number? */ + protonum = atoi(name); + if (protonum > 0 && protonum <= IPPROTO_MAX) { + /* try lookup by number, perhaps this protocol is supported */ + list_for_each_entry(cur, &proto_list, head) { + if (cur->protonum == protonum) { + *pnum = protonum; + return cur; + } + } + *pnum = protonum; + return &ct_proto_unknown; } return NULL; } static void -extension_help(struct ctproto_handler *h) +extension_help(struct ctproto_handler *h, int protonum) { - fprintf(stdout, "\n"); - fprintf(stdout, "Proto `%s' help:\n", h->name); + const char *name; + + if (h == &ct_proto_unknown) { + struct protoent *pent; + + pent = getprotobynumber(protonum); + if (!pent) + name = h->name; + else + name = pent->p_name; + } else { + name = h->name; + } + + fprintf(stdout, "Proto `%s' help:\n", name); h->help(); } @@ -908,7 +944,7 @@ int main(int argc, char *argv[]) struct nf_conntrack *mask = (struct nf_conntrack *)(void*) __mask; char __exp[nfexp_maxsize()]; struct nf_expect *exp = (struct nf_expect *)(void*) __exp; - int l3protonum; + int l3protonum, protonum = 0; union ct_address ad; unsigned int command = 0; @@ -921,6 +957,7 @@ int main(int argc, char *argv[]) register_udp(); register_icmp(); register_icmpv6(); + register_unknown(); /* disable explicit missing arguments error output from getopt_long */ opterr = 0; @@ -990,7 +1027,7 @@ int main(int argc, char *argv[]) break; case 'p': options |= CT_OPT_PROTO; - h = findproto(optarg); + h = findproto(optarg, &protonum); if (!h) exit_error(PARAMETER_PROBLEM, "`%s' unsupported protocol", @@ -999,6 +1036,8 @@ int main(int argc, char *argv[]) opts = merge_options(opts, h->opts, &h->option_offset); if (opts == NULL) exit_error(OTHER_PROBLEM, "out of memory"); + + nfct_set_attr_u8(obj, ATTR_L4PROTO, protonum); break; case 't': options |= CT_OPT_TIMEOUT; @@ -1090,11 +1129,6 @@ int main(int argc, char *argv[]) if (family == AF_UNSPEC) family = AF_INET; - /* set the protocol number if we have seen -p with no parameters */ - if (h && !nfct_attr_is_set(obj, ATTR_ORIG_L4PROTO) && - !nfct_attr_is_set(obj, ATTR_REPL_L4PROTO)) - nfct_set_attr_u8(obj, ATTR_L4PROTO, h->protonum); - cmd = bit2cmd(command); generic_cmd_check(cmd, options); generic_opt_check(options, @@ -1304,7 +1338,7 @@ int main(int argc, char *argv[]) case CT_HELP: usage(argv[0]); if (options & CT_OPT_PROTO) - extension_help(h); + extension_help(h, protonum); break; default: usage(argv[0]); -- cgit v1.2.3