From 37ef0a638d19ca5145f6d4868e42b7aa2c735d46 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sun, 6 May 2007 17:36:13 +0000 Subject: - add warning note to ctnl_test.c: old API is deprecated - split expect_api_test.c into small example files expect_*.c - introduce alias tags for original tuple attributes - introduce nfexp_sizeof and nfexp_maxsize - build expectation attributes iif they are set - fix l3num setting in expect/build.c --- src/conntrack.c | 735 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 425 insertions(+), 310 deletions(-) (limited to 'src/conntrack.c') diff --git a/src/conntrack.c b/src/conntrack.c index b550c39..f3aa06f 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1,5 +1,5 @@ /* - * (C) 2005 by Pablo Neira Ayuso + * (C) 2005-2007 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 as published by @@ -29,6 +29,8 @@ * Add support for expect creation * 2005-09-24 Harald Welte : * Remove remaints of "-A" + * 2007-04-22 Pablo Neira Ayuso : + * Ported to the new libnetfilter_conntrack API * */ #include @@ -63,7 +65,7 @@ static const char cmd_need_param[NUMBER_OF_CMD] = { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2 }; static const char optflags[NUMBER_OF_OPT] -= {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f'}; += {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f','n','g','x'}; static struct option original_opts[] = { {"dump", 2, 0, 'L'}, @@ -88,10 +90,13 @@ static struct option original_opts[] = { {"tuple-dst", 1, 0, ']'}, {"mask-src", 1, 0, '{'}, {"mask-dst", 1, 0, '}'}, - {"nat-range", 1, 0, 'a'}, + {"nat-range", 1, 0, 'a'}, /* deprecated */ {"mark", 1, 0, 'm'}, - {"id", 2, 0, 'i'}, + {"id", 2, 0, 'i'}, /* deprecated */ {"family", 1, 0, 'f'}, + {"src-nat", 1, 0, 'n'}, + {"dst-nat", 1, 0, 'g'}, + {"xml", 0, 0, 'x'}, {0, 0, 0, 0} }; @@ -113,28 +118,33 @@ static unsigned int global_option_offset = 0; static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = /* Well, it's better than "Re: Linux vs FreeBSD" */ { - /* s d r q p t u z e x y k l a m i f*/ -/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2}, -/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0}, -/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0}, -/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0}, -/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0}, -/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0}, -/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*HELP*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, -/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0}, -/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + /* s d r q p t u z e x y k l a m i f n g x */ +/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2,0,0,2}, +/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0}, +/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0}, +/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0}, +/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2}, +/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,2}, +/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*HELP*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0}, +/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0}, +/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, }; static char *lib_dir = CONNTRACK_LIB_DIR; static LIST_HEAD(proto_list); +static unsigned int options; +static unsigned int command; + +#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK) + void register_proto(struct ctproto_handler *h) { if (strcmp(h->version, VERSION) != 0) { @@ -328,7 +338,7 @@ err2str(int err, enum action command) return table[i].message; } - return strerror(err); + return strerror(-err); } #define PARSE_STATUS 0 @@ -340,9 +350,8 @@ static struct parse_parameter { size_t size; unsigned int value[6]; } parse_array[PARSE_MAX] = { - { {"ASSURED", "SEEN_REPLY", "UNSET", "SRC_NAT", "DST_NAT","FIXED_TIMEOUT"}, 6, - { IPS_ASSURED, IPS_SEEN_REPLY, 0, - IPS_SRC_NAT_DONE, IPS_DST_NAT_DONE, IPS_FIXED_TIMEOUT} }, + { {"ASSURED", "SEEN_REPLY", "UNSET", "FIXED_TIMEOUT"}, 4, + { IPS_ASSURED, IPS_SEEN_REPLY, 0, IPS_FIXED_TIMEOUT} }, { {"ALL", "NEW", "UPDATES", "DESTROY"}, 4, {~0U, NF_NETLINK_CONNTRACK_NEW, NF_NETLINK_CONNTRACK_UPDATE, NF_NETLINK_CONNTRACK_DESTROY} }, @@ -354,7 +363,17 @@ do_parse_parameter(const char *str, size_t strlen, unsigned int *value, { int i, ret = 0; struct parse_parameter *p = &parse_array[parse_type]; - + + if (strncasecmp(str, "SRC_NAT", strlen) == 0) { + printf("skipping SRC_NAT, use --src-nat instead\n"); + return 1; + } + + if (strncasecmp(str, "DST_NAT", strlen) == 0) { + printf("skipping DST_NAT, use --dst-nat instead\n"); + return 1; + } + for (i = 0; i < p->size; i++) if (strncasecmp(str, p->parameter[i], strlen) == 0) { *value |= p->value[i]; @@ -430,7 +449,7 @@ struct addr_parse { unsigned int family; }; -int __parse_inetaddr(const char *cp, struct addr_parse *parse) +int parse_inetaddr(const char *cp, struct addr_parse *parse) { if (inet_aton(cp, &parse->addr)) return AF_INET; @@ -442,12 +461,17 @@ int __parse_inetaddr(const char *cp, struct addr_parse *parse) exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'.", cp); } -int parse_inetaddr(const char *cp, union nfct_address *address) +union ct_address { + u_int32_t v4; + u_int32_t v6[4]; +}; + +int parse_addr(const char *cp, union ct_address *address) { struct addr_parse parse; int ret; - - if ((ret = __parse_inetaddr(cp, &parse)) == AF_INET) + + if ((ret = parse_inetaddr(cp, &parse)) == AF_INET) address->v4 = parse.addr.s_addr; else if (ret == AF_INET6) memcpy(address->v6, &parse.addr6, sizeof(parse.addr6)); @@ -457,73 +481,43 @@ int parse_inetaddr(const char *cp, union nfct_address *address) /* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */ static void -nat_parse(char *arg, int portok, struct nfct_nat *range) +nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type) { char *colon, *dash, *error; - struct addr_parse parse; + union ct_address parse; - memset(range, 0, sizeof(range)); colon = strchr(arg, ':'); if (colon) { - int port; + u_int16_t port; if (!portok) exit_error(PARAMETER_PROBLEM, "Need TCP or UDP with port specification"); port = atoi(colon+1); - if (port == 0 || port > 65535) + if (port == 0) exit_error(PARAMETER_PROBLEM, "Port `%s' not valid\n", colon+1); error = strchr(colon+1, ':'); if (error) exit_error(PARAMETER_PROBLEM, - "Invalid port:port syntax - use dash\n"); - - dash = strchr(colon, '-'); - if (!dash) { - range->l4min.tcp.port - = range->l4max.tcp.port - = htons(port); - } else { - int maxport; - - maxport = atoi(dash + 1); - if (maxport == 0 || maxport > 65535) - exit_error(PARAMETER_PROBLEM, - "Port `%s' not valid\n", dash+1); - if (maxport < port) - /* People are stupid. */ - exit_error(PARAMETER_PROBLEM, - "Port range `%s' funky\n", colon+1); - range->l4min.tcp.port = htons(port); - range->l4max.tcp.port = htons(maxport); - } - /* Starts with a colon? No IP info... */ - if (colon == arg) - return; - *colon = '\0'; - } + "Invalid port:port syntax\n"); - dash = strchr(arg, '-'); - if (colon && dash && dash > colon) - dash = NULL; - - if (dash) - *dash = '\0'; + if (type == CT_OPT_SRC_NAT) + nfct_set_attr_u16(obj, ATTR_SNAT_PORT, port); + else if (type == CT_OPT_DST_NAT) + nfct_set_attr_u16(obj, ATTR_DNAT_PORT, port); + } - if (__parse_inetaddr(arg, &parse) != AF_INET) + if (parse_addr(arg, &parse) != AF_INET) return; - range->min_ip = parse.addr.s_addr; - if (dash) { - if (__parse_inetaddr(dash+1, &parse) != AF_INET) - return; - range->max_ip = parse.addr.s_addr; - } else - range->max_ip = parse.addr.s_addr; + if (type == CT_OPT_SRC_NAT) + nfct_set_attr_u32(obj, ATTR_SNAT_IPV4, parse.v4); + else if (type == CT_OPT_DST_NAT) + nfct_set_attr_u32(obj, ATTR_DNAT_IPV4, parse.v4); } static void event_sighandler(int s) @@ -548,10 +542,12 @@ static const char usage_tables[] = static const char usage_conntrack_parameters[] = "Conntrack parameters and options:\n" - " -a, --nat-range min_ip[-max_ip]\tNAT ip range\n" + " -n, --src-nat ip\tsource NAT ip\n" + " -g, --dst-nat ip\tdestination NAT ip\n" " -m, --mark mark\t\t\tSet mark\n" " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n" " -z, --zero \t\t\t\tZero counters while listing\n" + " -x, --xml \t\t\t\tDisplay output in XML format\n"; ; static const char usage_expectation_parameters[] = @@ -571,7 +567,6 @@ static const char usage_parameters[] = " -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n" " -t, --timeout timeout\t\tSet timeout\n" " -u, --status status\t\tSet status, eg. ASSURED\n" - " -i, --id [id]\t\t\tShow or set conntrack ID\n" ; @@ -586,33 +581,78 @@ void usage(char *prog) { fprintf(stdout, "\n%s", usage_parameters); } -#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK) +unsigned int output_flags = NFCT_O_DEFAULT; + +static int event_cb(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + char buf[1024]; + struct nf_conntrack *obj = data; + + if (options & CT_COMPARISON && !nfct_compare(obj, ct)) + return NFCT_CB_CONTINUE; + + nfct_snprintf(buf, 1024, ct, type, output_flags, 0); + printf("%s\n", buf); + + return NFCT_CB_CONTINUE; +} + +static int dump_cb(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + char buf[1024]; + struct nf_conntrack *obj = data; + + if (options & CT_COMPARISON && !nfct_compare(obj, ct)) + return NFCT_CB_CONTINUE; + + nfct_snprintf(buf, 1024, ct, NFCT_T_UNKNOWN, output_flags, 0); + printf("%s\n", buf); + + return NFCT_CB_CONTINUE; +} + +static int dump_exp_cb(enum nf_conntrack_msg_type type, + struct nf_expect *exp, + void *data) +{ + char buf[1024]; + + nfexp_snprintf(buf, 1024, exp, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0); + printf("%s\n", buf); + + return NFCT_CB_CONTINUE; +} -static struct nfct_tuple orig, reply, mask; -static struct nfct_tuple exptuple; static struct ctproto_handler *h; -static union nfct_protoinfo proto; -static struct nfct_nat range; -static struct nfct_conntrack *ct; -static struct nfct_expect *exp; -static unsigned long timeout; -static unsigned int status; -static unsigned int mark; -static unsigned int id = NFCT_ANY_ID; -static struct nfct_conntrack_compare cmp; int main(int argc, char *argv[]) { int c; - unsigned int command = 0, options = 0; - unsigned int type = 0, event_mask = 0; - unsigned int l3flags = 0, l4flags = 0, metaflags = 0; + unsigned int type = 0, event_mask = 0, l4flags = 0, status = 0; int res = 0; int family = AF_UNSPEC; - struct nfct_conntrack_compare *pcmp; + char __obj[nfct_maxsize()]; + char __exptuple[nfct_maxsize()]; + char __mask[nfct_maxsize()]; + struct nf_conntrack *obj = (struct nf_conntrack *) __obj; + struct nf_conntrack *exptuple = (struct nf_conntrack *) __exptuple; + struct nf_conntrack *mask = (struct nf_conntrack *) __mask; + char __exp[nfexp_maxsize()]; + struct nf_expect *exp = (struct nf_expect *) __exp; + int l3protonum; + union ct_address ad; + + memset(__obj, 0, sizeof(__obj)); + memset(__exptuple, 0, sizeof(__exptuple)); + memset(__mask, 0, sizeof(__mask)); + memset(__exp, 0, sizeof(__exp)); while ((c = getopt_long(argc, argv, - "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:", + "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:x", opts, NULL)) != -1) { switch(c) { case 'L': @@ -673,68 +713,99 @@ int main(int argc, char *argv[]) break; case 's': options |= CT_OPT_ORIG_SRC; - if (optarg) { - orig.l3protonum = - parse_inetaddr(optarg, &orig.src); - set_family(&family, orig.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_ORIG_SRC; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_ORIG_SRC; + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_ORIG_IPV4_SRC, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(obj, + ATTR_ORIG_IPV6_SRC, + &ad.v6); } + nfct_set_attr_u8(obj, ATTR_ORIG_L3PROTO, l3protonum); break; case 'd': options |= CT_OPT_ORIG_DST; - if (optarg) { - orig.l3protonum = - parse_inetaddr(optarg, &orig.dst); - set_family(&family, orig.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_ORIG_DST; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_ORIG_DST; + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_ORIG_IPV4_DST, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(obj, + ATTR_ORIG_IPV6_DST, + &ad.v6); } + nfct_set_attr_u8(obj, ATTR_ORIG_L3PROTO, l3protonum); break; case 'r': options |= CT_OPT_REPL_SRC; - if (optarg) { - reply.l3protonum = - parse_inetaddr(optarg, &reply.src); - set_family(&family, reply.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_REPL_SRC; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_REPL_SRC; + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_REPL_IPV4_SRC, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(obj, + ATTR_REPL_IPV6_SRC, + &ad.v6); } + nfct_set_attr_u8(obj, ATTR_REPL_L3PROTO, l3protonum); break; case 'q': options |= CT_OPT_REPL_DST; - if (optarg) { - reply.l3protonum = - parse_inetaddr(optarg, &reply.dst); - set_family(&family, reply.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_REPL_DST; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_REPL_DST; + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_REPL_IPV4_DST, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(obj, + ATTR_REPL_IPV6_DST, + &ad.v6); } + nfct_set_attr_u8(obj, ATTR_REPL_L3PROTO, l3protonum); break; case 'p': options |= CT_OPT_PROTO; h = findproto(optarg); if (!h) exit_error(PARAMETER_PROBLEM, "proto needed\n"); - orig.protonum = h->protonum; - reply.protonum = h->protonum; - exptuple.protonum = h->protonum; - mask.protonum = h->protonum; - opts = merge_options(opts, h->opts, - &h->option_offset); + + nfct_set_attr_u8(obj, ATTR_ORIG_L4PROTO, h->protonum); + nfct_set_attr_u8(obj, ATTR_REPL_L4PROTO, h->protonum); + nfct_set_attr_u8(exptuple, + ATTR_ORIG_L4PROTO, + h->protonum); + nfct_set_attr_u8(mask, + ATTR_ORIG_L4PROTO, + h->protonum); + opts = merge_options(opts, h->opts, &h->option_offset); break; case 't': options |= CT_OPT_TIMEOUT; - if (optarg) - timeout = atol(optarg); + if (!optarg) + continue; + + nfct_set_attr_u32(obj, ATTR_TIMEOUT, atol(optarg)); + nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, atol(optarg)); break; case 'u': { if (!optarg) @@ -742,6 +813,7 @@ int main(int argc, char *argv[]) options |= CT_OPT_STATUS; parse_parameter(optarg, &status, PARSE_STATUS); + nfct_set_attr_u32(obj, ATTR_STATUS, status); break; } case 'e': @@ -753,59 +825,102 @@ int main(int argc, char *argv[]) break; case '{': options |= CT_OPT_MASK_SRC; - if (optarg) { - mask.l3protonum = - parse_inetaddr(optarg, &mask.src); - set_family(&family, mask.l3protonum); + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(mask, + ATTR_ORIG_IPV4_SRC, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(mask, + ATTR_ORIG_IPV6_SRC, + &ad.v6); } + nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum); break; case '}': options |= CT_OPT_MASK_DST; - if (optarg) { - mask.l3protonum = - parse_inetaddr(optarg, &mask.dst); - set_family(&family, mask.l3protonum); + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(mask, + ATTR_ORIG_IPV4_DST, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(mask, + ATTR_ORIG_IPV6_DST, + &ad.v6); } + nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum); break; case '[': options |= CT_OPT_EXP_SRC; - if (optarg) { - exptuple.l3protonum = - parse_inetaddr(optarg, &exptuple.src); - set_family(&family, exptuple.l3protonum); + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(exptuple, + ATTR_ORIG_IPV4_SRC, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(exptuple, + ATTR_ORIG_IPV6_SRC, + &ad.v6); } + nfct_set_attr_u8(exptuple, + ATTR_ORIG_L3PROTO, + l3protonum); break; case ']': options |= CT_OPT_EXP_DST; - if (optarg) { - exptuple.l3protonum = - parse_inetaddr(optarg, &exptuple.dst); - set_family(&family, exptuple.l3protonum); + if (!optarg) + break; + + l3protonum = parse_addr(optarg, &ad); + set_family(&family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(exptuple, + ATTR_ORIG_IPV4_DST, + ad.v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(exptuple, + ATTR_ORIG_IPV6_DST, + &ad.v6); } + nfct_set_attr_u8(exptuple, + ATTR_ORIG_L3PROTO, + l3protonum); break; case 'a': - options |= CT_OPT_NATRANGE; + printf("warning: ignoring --nat-range, " + "use --src-nat or --dst-nat instead.\n"); + break; + case 'n': + options |= CT_OPT_SRC_NAT; set_family(&family, AF_INET); - nat_parse(optarg, 1, &range); + nat_parse(optarg, 1, obj, CT_OPT_SRC_NAT); break; + case 'g': + options |= CT_OPT_DST_NAT; + set_family(&family, AF_INET); + nat_parse(optarg, 1, obj, CT_OPT_DST_NAT); case 'm': options |= CT_OPT_MARK; - mark = atol(optarg); - metaflags |= NFCT_MARK; + if (!optarg) + continue; + nfct_set_attr_u32(obj, ATTR_MARK, atol(optarg)); break; - case 'i': { - char *s = NULL; - options |= CT_OPT_ID; - if (optarg) - break; - else if (optind < argc && argv[optind][0] != '-' - && argv[optind][0] != '!') - s = argv[optind++]; - - if (s) - id = atol(s); + case 'i': + printf("warning: ignoring --id. deprecated option.\n"); break; - } case 'f': options |= CT_OPT_FAMILY; if (strncmp(optarg, "ipv4", strlen("ipv4")) == 0) @@ -816,11 +931,14 @@ int main(int argc, char *argv[]) exit_error(PARAMETER_PROBLEM, "Unknown " "protocol family\n"); break; + case 'x': + options |= CT_OPT_XML; + output_flags = NFCT_O_XML; + break; default: if (h && h->parse_opts - &&!h->parse_opts(c - h->option_offset, argv, &orig, - &reply, &exptuple, &mask, &proto, - &l4flags)) + &&!h->parse_opts(c - h->option_offset, argv, obj, + exptuple, mask, &l4flags)) exit_error(PARAMETER_PROBLEM, "parse error\n"); /* Unknown argument... */ @@ -842,7 +960,7 @@ int main(int argc, char *argv[]) if (!(command & CT_HELP) && h && h->final_check - && !h->final_check(l4flags, command, &orig, &reply)) { + && !h->final_check(l4flags, command, obj)) { usage(argv[0]); extension_help(h); exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n"); @@ -855,39 +973,18 @@ int main(int argc, char *argv[]) if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_COMPARISON) { + if (options & CT_COMPARISON && + options & CT_OPT_ZERO) + exit_error(PARAMETER_PROBLEM, "Can't use -z with " + "filtering parameters"); - if (options & CT_OPT_ZERO) - exit_error(PARAMETER_PROBLEM, "Can't use -z " - "with filtering parameters"); + nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj); - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cmp.ct = ct; - cmp.flags = metaflags; - cmp.l3flags = l3flags; - cmp.l4flags = l4flags; - pcmp = &cmp; - } - - if (options & CT_OPT_ID) - nfct_register_callback(cth, - nfct_default_conntrack_display_id, - (void *) pcmp); - else - nfct_register_callback(cth, - nfct_default_conntrack_display, - (void *) pcmp); - if (options & CT_OPT_ZERO) - res = - nfct_dump_conntrack_table_reset_counters(cth, family); + res = nfct_query(cth, NFCT_Q_DUMP_RESET, &family); else - res = nfct_dump_conntrack_table(cth, family); + res = nfct_query(cth, NFCT_Q_DUMP, &family); + nfct_close(cth); break; @@ -895,96 +992,144 @@ int main(int argc, char *argv[]) cth = nfct_open(EXPECT, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ID) - nfct_register_callback(cth, - nfct_default_expect_display_id, - NULL); - else - nfct_register_callback(cth, - nfct_default_expect_display, - NULL); - res = nfct_dump_expect_list(cth, family); + + nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL); + res = nfexp_query(cth, NFCT_Q_DUMP, &family); nfct_close(cth); break; case CT_CREATE: if ((options & CT_OPT_ORIG) && !(options & CT_OPT_REPL)) { - reply.l3protonum = orig.l3protonum; - memcpy(&reply.src, &orig.dst, sizeof(reply.src)); - memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); + nfct_set_attr_u8(obj, + ATTR_REPL_L3PROTO, + nfct_get_attr_u8(obj, + ATTR_ORIG_L3PROTO)); + if (family == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_REPL_IPV4_SRC, + nfct_get_attr_u32(obj, + ATTR_ORIG_IPV4_DST)); + nfct_set_attr_u32(obj, + ATTR_REPL_IPV4_DST, + nfct_get_attr_u32(obj, + ATTR_ORIG_IPV4_SRC)); + } else if (family == AF_INET6) { + nfct_set_attr(obj, + ATTR_REPL_IPV6_SRC, + nfct_get_attr(obj, + ATTR_ORIG_IPV6_DST)); + nfct_set_attr(obj, + ATTR_REPL_IPV6_DST, + nfct_get_attr(obj, + ATTR_ORIG_IPV6_SRC)); + } } else if (!(options & CT_OPT_ORIG) && (options & CT_OPT_REPL)) { - orig.l3protonum = reply.l3protonum; - memcpy(&orig.src, &reply.dst, sizeof(orig.src)); - memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); + nfct_set_attr_u8(obj, + ATTR_ORIG_L3PROTO, + nfct_get_attr_u8(obj, + ATTR_REPL_L3PROTO)); + if (family == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_ORIG_IPV4_SRC, + nfct_get_attr_u32(obj, + ATTR_REPL_IPV4_DST)); + nfct_set_attr_u32(obj, + ATTR_ORIG_IPV4_DST, + nfct_get_attr_u32(obj, + ATTR_REPL_IPV4_SRC)); + } else if (family == AF_INET6) { + nfct_set_attr(obj, + ATTR_ORIG_IPV6_SRC, + nfct_get_attr(obj, + ATTR_REPL_IPV6_DST)); + nfct_set_attr(obj, + ATTR_ORIG_IPV6_DST, + nfct_get_attr(obj, + ATTR_REPL_IPV6_SRC)); + } } - if (options & CT_OPT_NATRANGE) - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - &range); - else - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not Enough memory"); - + cth = nfct_open(CONNTRACK, 0); - if (!cth) { - nfct_conntrack_free(ct); + if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_create_conntrack(cth, ct); + + res = nfct_query(cth, NFCT_Q_CREATE, obj); nfct_close(cth); - nfct_conntrack_free(ct); break; case EXP_CREATE: - if (options & CT_OPT_ORIG) - exp = nfct_expect_alloc(&orig, &exptuple, - &mask, timeout, id); - else if (options & CT_OPT_REPL) - exp = nfct_expect_alloc(&reply, &exptuple, - &mask, timeout, id); - if (!exp) - exit_error(OTHER_PROBLEM, "Not enough memory"); + nfexp_set_attr(exp, ATTR_EXP_MASTER, obj); + nfexp_set_attr(exp, ATTR_EXP_EXPECTED, exptuple); + nfexp_set_attr(exp, ATTR_EXP_MASK, mask); cth = nfct_open(EXPECT, 0); - if (!cth) { - nfct_expect_free(exp); + if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_create_expectation(cth, exp); - nfct_expect_free(exp); + + res = nfexp_query(cth, NFCT_Q_CREATE, exp); nfct_close(cth); break; case CT_UPDATE: if ((options & CT_OPT_ORIG) && !(options & CT_OPT_REPL)) { - reply.l3protonum = orig.l3protonum; - memcpy(&reply.src, &orig.dst, sizeof(reply.src)); - memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); + nfct_set_attr_u8(obj, + ATTR_REPL_L3PROTO, + nfct_get_attr_u8(obj, + ATTR_ORIG_L3PROTO)); + if (family == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_REPL_IPV4_SRC, + nfct_get_attr_u32(obj, + ATTR_ORIG_IPV4_DST)); + nfct_set_attr_u32(obj, + ATTR_REPL_IPV4_DST, + nfct_get_attr_u32(obj, + ATTR_ORIG_IPV4_SRC)); + } else if (family == AF_INET6) { + nfct_set_attr(obj, + ATTR_REPL_IPV6_SRC, + nfct_get_attr(obj, + ATTR_ORIG_IPV6_DST)); + nfct_set_attr(obj, + ATTR_REPL_IPV6_DST, + nfct_get_attr(obj, + ATTR_ORIG_IPV6_SRC)); + } } else if (!(options & CT_OPT_ORIG) && (options & CT_OPT_REPL)) { - orig.l3protonum = reply.l3protonum; - memcpy(&orig.src, &reply.dst, sizeof(orig.src)); - memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); + nfct_set_attr_u8(obj, + ATTR_ORIG_L3PROTO, + nfct_get_attr_u8(obj, + ATTR_REPL_L3PROTO)); + if (family == AF_INET) { + nfct_set_attr_u32(obj, + ATTR_ORIG_IPV4_SRC, + nfct_get_attr_u32(obj, + ATTR_REPL_IPV4_DST)); + nfct_set_attr_u32(obj, + ATTR_ORIG_IPV4_DST, + nfct_get_attr_u32(obj, + ATTR_REPL_IPV4_SRC)); + } else if (family == AF_INET6) { + nfct_set_attr(obj, + ATTR_ORIG_IPV6_SRC, + nfct_get_attr(obj, + ATTR_REPL_IPV6_DST)); + nfct_set_attr(obj, + ATTR_ORIG_IPV6_DST, + nfct_get_attr(obj, + ATTR_REPL_IPV6_SRC)); + } } - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - + cth = nfct_open(CONNTRACK, 0); - if (!cth) { - nfct_conntrack_free(ct); + if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_update_conntrack(cth, ct); - nfct_conntrack_free(ct); + + res = nfct_query(cth, NFCT_Q_UPDATE, obj); nfct_close(cth); break; @@ -995,25 +1140,19 @@ int main(int argc, char *argv[]) cth = nfct_open(CONNTRACK, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ORIG) - res = nfct_delete_conntrack(cth, &orig, - NFCT_DIR_ORIGINAL, - id); - else if (options & CT_OPT_REPL) - res = nfct_delete_conntrack(cth, &reply, - NFCT_DIR_REPLY, - id); + + res = nfct_query(cth, NFCT_Q_DESTROY, obj); nfct_close(cth); break; case EXP_DELETE: + nfexp_set_attr(exp, ATTR_EXP_EXPECTED, obj); + cth = nfct_open(EXPECT, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ORIG) - res = nfct_delete_expectation(cth, &orig, id); - else if (options & CT_OPT_REPL) - res = nfct_delete_expectation(cth, &reply, id); + + res = nfexp_query(cth, NFCT_Q_DESTROY, exp); nfct_close(cth); break; @@ -1021,27 +1160,21 @@ int main(int argc, char *argv[]) cth = nfct_open(CONNTRACK, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - nfct_register_callback(cth, nfct_default_conntrack_display, - NULL); - if (options & CT_OPT_ORIG) - res = nfct_get_conntrack(cth, &orig, - NFCT_DIR_ORIGINAL, id); - else if (options & CT_OPT_REPL) - res = nfct_get_conntrack(cth, &reply, - NFCT_DIR_REPLY, id); + + nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj); + res = nfct_query(cth, NFCT_Q_GET, obj); nfct_close(cth); break; case EXP_GET: + nfexp_set_attr(exp, ATTR_EXP_MASTER, obj); + cth = nfct_open(EXPECT, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - nfct_register_callback(cth, nfct_default_expect_display, - NULL); - if (options & CT_OPT_ORIG) - res = nfct_get_expectation(cth, &orig, id); - else if (options & CT_OPT_REPL) - res = nfct_get_expectation(cth, &reply, id); + + nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL); + res = nfexp_query(cth, NFCT_Q_GET, exp); nfct_close(cth); break; @@ -1049,7 +1182,7 @@ int main(int argc, char *argv[]) cth = nfct_open(CONNTRACK, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - res = nfct_flush_conntrack_table(cth, AF_INET); + res = nfct_query(cth, NFCT_Q_FLUSH, &family); nfct_close(cth); break; @@ -1057,7 +1190,7 @@ int main(int argc, char *argv[]) cth = nfct_open(EXPECT, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - res = nfct_flush_expectation_table(cth, AF_INET); + res = nfexp_query(cth, NFCT_Q_FLUSH, &family); nfct_close(cth); break; @@ -1070,25 +1203,8 @@ int main(int argc, char *argv[]) if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); signal(SIGINT, event_sighandler); - - if (options & CT_COMPARISON) { - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cmp.ct = ct; - cmp.flags = metaflags; - cmp.l3flags = l3flags; - cmp.l4flags = l4flags; - pcmp = &cmp; - } - - nfct_register_callback(cth, - nfct_default_conntrack_event_display, - (void *) pcmp); - res = nfct_event_conntrack(cth); + nfct_callback_register(cth, NFCT_T_ALL, event_cb, obj); + res = nfct_catch(cth); nfct_close(cth); break; @@ -1097,9 +1213,8 @@ int main(int argc, char *argv[]) if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); signal(SIGINT, event_sighandler); - nfct_register_callback(cth, nfct_default_expect_display, - NULL); - res = nfct_event_expectation(cth); + nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL); + res = nfexp_catch(cth); nfct_close(cth); break; @@ -1123,7 +1238,7 @@ int main(int argc, char *argv[]) } if (res < 0) { - fprintf(stderr, "Operation failed: %s\n", err2str(res, command)); + fprintf(stderr, "Operation failed: %s\n", err2str(-errno, command)); exit(OTHER_PROBLEM); } -- cgit v1.2.3