From d894e26211f38db37015850afab6b7331edeecdb Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org" Date: Sun, 1 May 2005 23:19:42 +0000 Subject: o Created changelog file o Deleted libctnetlink.h and libnfnetlink.h from the include/ dir. o Added support for version (-V) and help (-h) o Added event mask based support o Added GPLv2 headers o Use fprintf instead of printf o Defined print_tuple and print_proto output interfaces o ctnl_[get|del]_conntrack handles return value from kernel via msgerr o Added support for conntrack table flushing o Added test case file (test.sh) o Improve dump output o Autoconf stuff for conntrack + some pablo's modifications. o Fixed packet counters formatting (use %llu instead of %lu) --- src/Makefile.am | 8 ++ src/conntrack.c | 255 ++++++++++++++++++++++++++++++++------------------------ src/libct.c | 174 +++++++++++++++++++++++--------------- 3 files changed, 261 insertions(+), 176 deletions(-) create mode 100644 src/Makefile.am (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..ae3f429 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,8 @@ +bin_PROGRAMS = conntrack +conntrack_SOURCES = conntrack.c libct.c + +INCLUDES= $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} +conntrack_LDFLAGS = $(all_libraries) -rdynamic + +#AM_CFLAGS = -g +#LINKOPTS=-ldl -lnfnetlink -lctnetlink -rdynamic diff --git a/src/conntrack.c b/src/conntrack.c index 2c716f7..ed97a86 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -46,7 +46,7 @@ #include "libct_proto.h" #define PROGNAME "conntrack" -#define VERSION "0.25" +#define VERSION "0.50" #if 0 #define DEBUGP printf @@ -78,9 +78,15 @@ enum action { CT_EVENT = (1 << CT_EVENT_BIT), CT_ACTION_BIT = 6, - CT_ACTION = (1 << CT_ACTION_BIT) + CT_ACTION = (1 << CT_ACTION_BIT), + + CT_VERSION_BIT = 7, + CT_VERSION = (1 << CT_VERSION_BIT), + + CT_HELP_BIT = 8, + CT_HELP = (1 << CT_HELP_BIT), }; -#define NUMBER_OF_CMD 7 +#define NUMBER_OF_CMD 9 enum options { CT_OPT_ORIG_SRC_BIT = 0, @@ -102,28 +108,29 @@ enum options { CT_OPT_PROTO_BIT = 4, CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT), - CT_OPT_ID_BIT = 5, - CT_OPT_ID = (1 << CT_OPT_ID_BIT), - - CT_OPT_TIMEOUT_BIT = 6, + CT_OPT_TIMEOUT_BIT = 5, CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT), - CT_OPT_STATUS_BIT = 7, + CT_OPT_STATUS_BIT = 6, CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT), - CT_OPT_ZERO_BIT = 8, + CT_OPT_ZERO_BIT = 7, CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT), - CT_OPT_DUMP_MASK_BIT = 9, + CT_OPT_DUMP_MASK_BIT = 8, CT_OPT_DUMP_MASK = (1 << CT_OPT_DUMP_MASK_BIT), + CT_OPT_GROUP_MASK_BIT = 9, + CT_OPT_GROUP_MASK = (1 << CT_OPT_GROUP_MASK_BIT), + CT_OPT_EVENT_MASK_BIT = 10, CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), + }; #define NUMBER_OF_OPT 11 static const char optflags[NUMBER_OF_OPT] -= { 's', 'd', 'r', 'q', 'p', 'i', 't', 'u', 'z','m','g'}; += { 's', 'd', 'r', 'q', 'p', 't', 'u', 'z','m','g','e'}; static struct option original_opts[] = { {"dump", 2, 0, 'L'}, @@ -133,17 +140,19 @@ static struct option original_opts[] = { {"flush", 1, 0, 'F'}, {"event", 1, 0, 'E'}, {"action", 1, 0, 'A'}, + {"version", 0, 0, 'V'}, + {"help", 0, 0, 'h'}, {"orig-src", 1, 0, 's'}, {"orig-dst", 1, 0, 'd'}, {"reply-src", 1, 0, 'r'}, {"reply-dst", 1, 0, 'q'}, {"protonum", 1, 0, 'p'}, {"timeout", 1, 0, 't'}, - {"id", 1, 0, 'i'}, {"status", 1, 0, 'u'}, {"zero", 0, 0, 'z'}, {"dump-mask", 1, 0, 'm'}, {"groups", 1, 0, 'g'}, + {"event-mask", 1, 0, 'e'}, {0, 0, 0, 0} }; @@ -164,19 +173,24 @@ 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 -i -t -u -z -m -g*/ -/*LIST*/ {'x','x','x','x','x','x','x','x',' ','x','x'}, -/*CREATE*/ {'+','+','+','+','+','x','+','+','x','x','x'}, -/*DELETE*/ {' ',' ',' ',' ',' ','+','x','x','x','x','x'}, -/*GET*/ {' ',' ',' ',' ','+','+','x','x','x','x','x'}, + /* -s -d -r -q -p -t -u -z -m -g -e */ +/*LIST*/ {'x','x','x','x','x','x','x',' ','x','x','x'}, +/*CREATE*/ {'+','+','+','+','+','+','+','x','x','x','x'}, +/*DELETE*/ {' ',' ',' ',' ',' ','x','x','x','x','x','x'}, +/*GET*/ {' ',' ',' ',' ','+','x','x','x','x','x','x'}, /*FLUSH*/ {'x','x','x','x','x','x','x','x','x','x','x'}, -/*EVENT*/ {'x','x','x','x','x','x','x','x','x','x',' '}, -/*ACTION*/ {'x','x','x','x','x','x','x','x',' ',' ','x'}, +/*EVENT*/ {'x','x','x','x','x','x','x','x','x',' ','x'}, +/*ACTION*/ {'x','x','x','x','x','x','x','x',' ','x',' '}, +/*VERSION*/ {'x','x','x','x','x','x','x','x','x','x','x'}, +/*HELP*/ {'x','x','x','x','x','x','x','x','x','x','x'}, }; +/* FIXME: hardcoded!, this must be defined during compilation time */ +char *lib_dir = CONNTRACK_LIB_DIR; + LIST_HEAD(proto_list); -char *proto2str[] = { +char *proto2str[IPPROTO_MAX] = { [IPPROTO_TCP] = "tcp", [IPPROTO_UDP] = "udp", [IPPROTO_ICMP] = "icmp", @@ -249,7 +263,7 @@ generic_opt_check(int command, int options) } } if (legal == -1) - exit_error(PARAMETER_PROBLEM, "Illegal option `-%c'" + exit_error(PARAMETER_PROBLEM, "Illegal option `-%c' " "with this command\n", optflags[i]); } } @@ -280,7 +294,7 @@ merge_options(struct option *oldopts, const struct option *newopts, static void dump_tuple(struct ip_conntrack_tuple *tp) { - fprintf(stderr, "tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", + fprintf(stdout, "tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", tp, tp->dst.protonum, NIPQUAD(tp->src.ip), ntohs(tp->src.u.all), NIPQUAD(tp->dst.ip), ntohs(tp->dst.u.all)); @@ -291,64 +305,67 @@ void not_implemented_yet() exit_error(OTHER_PROBLEM, "Sorry, not implemented yet :(\n"); } -static int -do_parse_status(const char *str, size_t strlen, unsigned int *status) -{ - if (strncasecmp(str, "ASSURED", strlen) == 0) - *status |= IPS_ASSURED; - else if (strncasecmp(str, "SEEN_REPLY", strlen) == 0) - *status |= IPS_SEEN_REPLY; - else if (strncasecmp(str, "UNSET", strlen) == 0) - *status |= 0; - else - return 0; - return 1; -} -static void -parse_status(const char *arg, unsigned int *status) -{ - const char *comma; - - while ((comma = strchr(arg, ',')) != NULL) { - if (comma == arg || !do_parse_status(arg, comma-arg, status)) - exit_error(PARAMETER_PROBLEM, "Bad status `%s'", arg); - arg = comma+1; - } - - if (strlen(arg) == 0 || !do_parse_status(arg, strlen(arg), status)) - exit_error(PARAMETER_PROBLEM, "Bad status `%s'", arg); -} +#define PARSE_STATUS 0 +#define PARSE_GROUP 1 +#define PARSE_EVENT 2 +#define PARSE_DUMP 3 +#define PARSE_MAX PARSE_DUMP+1 + +static struct parse_parameter { + char *parameter[10]; + size_t size; + unsigned int value[10]; +} parse_array[PARSE_MAX] = { + { {"ASSURED", "SEEN_REPLY", "UNSET"}, + 3, + { IPS_ASSURED, IPS_SEEN_REPLY, 0} }, + { {"ALL", "TCP", "UDP", "ICMP"}, + 4, + {~0U, NFGRP_IPV4_CT_TCP, NFGRP_IPV4_CT_UDP, NFGRP_IPV4_CT_ICMP} }, + { {"ALL", "NEW", "RELATED", "DESTROY", "REFRESH", "STATUS", + "PROTOINFO", "HELPER", "HELPINFO", "NATINFO"}, + 10, + {~0U, IPCT_NEW, IPCT_RELATED, IPCT_DESTROY, IPCT_REFRESH, IPCT_STATUS, + IPCT_PROTOINFO, IPCT_HELPER, IPCT_HELPINFO, IPCT_NATINFO} }, + { {"ALL", "TUPLE", "STATUS", "TIMEOUT", "PROTOINFO", "HELPINFO", + "COUNTERS", "MARK"}, 8, + {~0U, DUMP_TUPLE, DUMP_STATUS, DUMP_TIMEOUT, DUMP_PROTOINFO, + DUMP_HELPINFO, DUMP_COUNTERS, DUMP_MARK} } +}; static int -do_parse_group(const char *str, size_t strlen, unsigned int *group) +do_parse_parameter(const char *str, size_t strlen, unsigned int *value, + int parse_type) { - if (strncasecmp(str, "ALL", strlen) == 0) - *group |= ~0U; - else if (strncasecmp(str, "TCP", strlen) == 0) - *group |= NFGRP_IPV4_CT_TCP; - else if (strncasecmp(str, "UDP", strlen) == 0) - *group |= NFGRP_IPV4_CT_UDP; - else if (strncasecmp(str, "ICMP", strlen) == 0) - *group |= NFGRP_IPV4_CT_ICMP; - else - return 0; - return 1; + int i, ret = 0; + struct parse_parameter *p = &parse_array[parse_type]; + + for (i = 0; i < p->size; i++) + if (strncasecmp(str, p->parameter[i], strlen) == 0) { + *value |= p->value[i]; + ret = 1; + break; + } + + return ret; } static void -parse_group(const char *arg, unsigned int *group) +parse_parameter(const char *arg, unsigned int *status, int parse_type) { const char *comma; while ((comma = strchr(arg, ',')) != NULL) { - if (comma == arg || !do_parse_group(arg, comma-arg, group)) - exit_error(PARAMETER_PROBLEM, "Bad status `%s'", arg); + if (comma == arg + || !do_parse_parameter(arg, comma-arg, status, parse_type)) + exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg); arg = comma+1; } - if (strlen(arg) == 0 || !do_parse_group(arg, strlen(arg), group)) - exit_error(PARAMETER_PROBLEM, "Bad status `%s'", arg); + if (strlen(arg) == 0 + || !do_parse_parameter(arg, strlen(arg), status, parse_type)) + exit_error(PARAMETER_PROBLEM, "Bad parameter `%s'", arg); } unsigned int check_type(int argc, char *argv[]) @@ -442,27 +459,30 @@ int iptables_insmod(const char *modname, const char *modprobe) } void usage(char *prog) { -fprintf(stderr, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION); -fprintf(stderr, "Usage: %s [commands] [options]\n", prog); -fprintf(stderr, "\n"); -fprintf(stderr, "Commands:\n"); -fprintf(stderr, "-L table List conntrack or expectation table\n"); -fprintf(stderr, "-G table [options] Get conntrack or expectation\n"); -fprintf(stderr, "-D table [options] Delete conntrack or expectation\n"); -fprintf(stderr, "-I table [options] Create a conntrack or expectation\n"); -fprintf(stderr, "-E table Show events\n"); -fprintf(stderr, "-F table Flush table\n"); -fprintf(stderr, "\n"); -fprintf(stderr, "Options:\n"); -fprintf(stderr, "--orig-src Source address from original direction\n"); -fprintf(stderr, "--orig-dst Destination address from original direction\n"); -fprintf(stderr, "--reply-src Source addres from reply direction\n"); -fprintf(stderr, "--reply-dst Destination address from reply direction\n"); -fprintf(stderr, "-p Layer 4 Protocol\n"); -fprintf(stderr, "-t Timeout\n"); -fprintf(stderr, "-i Conntrack ID\n"); -fprintf(stderr, "-u Status\n"); -fprintf(stderr, "-z Zero Counters\n"); +fprintf(stdout, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION); +fprintf(stdout, "Usage: %s [commands] [options]\n", prog); +fprintf(stdout, "\n"); +fprintf(stdout, "Commands:\n"); +fprintf(stdout, "-L [table] [-z] List conntrack or expectation table\n"); +fprintf(stdout, "-G [table] parameters Get conntrack or expectation\n"); +fprintf(stdout, "-D [table] parameters Delete conntrack or expectation\n"); +fprintf(stdout, "-I [table] parameters Create a conntrack or expectation\n"); +fprintf(stdout, "-E [table] [options] Show events\n"); +fprintf(stdout, "-F [table] Flush table\n"); +fprintf(stdout, "-A [table] [options] Set action\n"); +fprintf(stdout, "\n"); +fprintf(stdout, "Options:\n"); +fprintf(stdout, "--orig-src ip Source address from original direction\n"); +fprintf(stdout, "--orig-dst ip Destination address from original direction\n"); +fprintf(stdout, "--reply-src ip Source addres from reply direction\n"); +fprintf(stdout, "--reply-dst ip Destination address from reply direction\n"); +fprintf(stdout, "-p proto Layer 4 Protocol\n"); +fprintf(stdout, "-t timeout Set timeout\n"); +fprintf(stdout, "-u status Set status\n"); +fprintf(stdout, "-m dumpmask Set dump mask\n"); +fprintf(stdout, "-g groupmask Set group mask\n"); +fprintf(stdout, "-e eventmask Set event mask\n"); +fprintf(stdout, "-z Zero Counters\n"); } int main(int argc, char *argv[]) @@ -473,11 +493,11 @@ int main(int argc, char *argv[]) struct ctproto_handler *h = NULL; union ip_conntrack_proto proto; unsigned long timeout = 0; - unsigned int status = 0; + unsigned int status = 0, group_mask = 0; unsigned long id = 0; - unsigned int type = 0, mask = 0, extra_flags = 0, event_mask = 0; + unsigned int type = 0, dump_mask = 0, extra_flags = 0, event_mask = 0; int res = 0, retry = 2; - + memset(&proto, 0, sizeof(union ip_conntrack_proto)); memset(&orig, 0, sizeof(struct ip_conntrack_tuple)); memset(&reply, 0, sizeof(struct ip_conntrack_tuple)); @@ -485,7 +505,7 @@ int main(int argc, char *argv[]) reply.dst.dir = IP_CT_DIR_REPLY; while ((c = getopt_long(argc, argv, - "L::I::D::G::E::A::s:d:r:q:p:i:t:u:m:g:z", + "L::I::D::G::E::A::F::hVs:d:r:q:p:t:u:m:g:e:z", opts, NULL)) != -1) { switch(c) { case 'L': @@ -515,12 +535,19 @@ int main(int argc, char *argv[]) case 'A': command |= CT_ACTION; type = check_type(argc, argv); + break; + case 'V': + command |= CT_VERSION; + break; + case 'h': + command |= CT_HELP; + break; case 'm': if (!optarg) continue; options |= CT_OPT_DUMP_MASK; - mask = atoi(optarg); + parse_parameter(optarg, &dump_mask, PARSE_DUMP); break; case 's': options |= CT_OPT_ORIG_SRC; @@ -552,10 +579,6 @@ int main(int argc, char *argv[]) opts = merge_options(opts, h->opts, &h->option_offset); break; - case 'i': - options |= CT_OPT_ID; - id = atoi(optarg); - break; case 't': options |= CT_OPT_TIMEOUT; if (optarg) @@ -567,14 +590,18 @@ int main(int argc, char *argv[]) continue; options |= CT_OPT_STATUS; - parse_status(optarg, &status); + parse_parameter(optarg, &status, PARSE_STATUS); /* Just insert confirmed conntracks */ status |= IPS_CONFIRMED; break; } case 'g': + options |= CT_OPT_GROUP_MASK; + parse_parameter(optarg, &group_mask, PARSE_GROUP); + break; + case 'e': options |= CT_OPT_EVENT_MASK; - parse_group(optarg, &event_mask); + parse_parameter(optarg, &event_mask, PARSE_EVENT); break; case 'z': options |= CT_OPT_ZERO; @@ -611,16 +638,14 @@ int main(int argc, char *argv[]) break; case CT_CREATE: - fprintf(stderr, "create\n"); if (type == 0) - create_conntrack(&orig, &reply, timeout, - &proto, status); + res = create_conntrack(&orig, &reply, timeout, + &proto, status); else not_implemented_yet(); break; case CT_DELETE: - fprintf(stderr, "delete\n"); if (type == 0) { if (options & CT_OPT_ORIG) res =delete_conntrack(&orig, CTA_ORIG, @@ -633,7 +658,6 @@ int main(int argc, char *argv[]) break; case CT_GET: - fprintf(stderr, "get\n"); if (type == 0) { if (options & CT_OPT_ORIG) res = get_conntrack(&orig, CTA_ORIG, @@ -646,26 +670,35 @@ int main(int argc, char *argv[]) break; case CT_FLUSH: - not_implemented_yet(); + if (type == 0) + res = flush_conntrack(); + else + not_implemented_yet(); break; case CT_EVENT: if (type == 0) { - if (options & CT_OPT_EVENT_MASK) - res = event_conntrack(event_mask); + if (options & CT_OPT_GROUP_MASK) + res = event_conntrack(group_mask); else res = event_conntrack(~0U); } else - /* and surely it won't ever... */ not_implemented_yet(); case CT_ACTION: if (type == 0) if (options & CT_OPT_DUMP_MASK) - res = set_dump_mask(mask); + res = set_mask(dump_mask, 0); + else if (options & CT_OPT_EVENT_MASK) + res = set_mask(event_mask, 1); break; - - default: + case CT_VERSION: + fprintf(stdout, "%s v%s\n", PROGNAME, VERSION); + break; + case CT_HELP: + usage(argv[0]); + break; + default: usage(argv[0]); break; } @@ -684,5 +717,5 @@ int main(int argc, char *argv[]) } if (res == -1) - fprintf(stderr, "Operations failed\n"); + fprintf(stderr, "Operation failed\n"); } diff --git a/src/libct.c b/src/libct.c index 143901b..d44b920 100644 --- a/src/libct.c +++ b/src/libct.c @@ -1,3 +1,11 @@ +/* + * (C) 2005 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ #include #include #include @@ -16,9 +24,18 @@ #define DEBUGP #endif +extern char *lib_dir; extern struct list_head proto_list; extern char *proto2str[]; +static void print_status(unsigned int status) +{ + if (status & IPS_ASSURED) + fprintf(stdout, "[ASSURED] "); + if (!(status & IPS_SEEN_REPLY)) + fprintf(stdout, "[UNREPLIED] "); +} + static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) { struct nfgenmsg *nfmsg; @@ -52,49 +69,48 @@ static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) switch(attr->nfa_type) { case CTA_ORIG: orig = NFA_DATA(attr); - printf("src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", NIPQUAD(orig->src.ip), NIPQUAD(orig->dst.ip)); h = findproto(proto2str[orig->dst.protonum]); - if (h && h->print) - h->print(orig); + if (h && h->print_tuple) + h->print_tuple(orig); break; case CTA_RPLY: reply = NFA_DATA(attr); - printf("src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", NIPQUAD(reply->src.ip), NIPQUAD(reply->dst.ip)); h = findproto(proto2str[reply->dst.protonum]); - if (h && h->print) - h->print(reply); + if (h && h->print_tuple) + h->print_tuple(reply); break; case CTA_STATUS: status = NFA_DATA(attr); - printf("status=%u ", *status); + print_status(*status); break; case CTA_PROTOINFO: proto = NFA_DATA(attr); - if (proto2str[proto->num_proto]) - printf("%s %d ", proto2str[proto->num_proto], proto->num_proto); - else - printf("unknown %d ", proto->num_proto); + if (proto2str[proto->num_proto]) { + fprintf(stdout, "%s %d ", proto2str[proto->num_proto], proto->num_proto); + h = findproto(proto2str[proto->num_proto]); + if (h && h->print_proto) + h->print_proto(&proto->proto); + } else + fprintf(stdout, "unknown %d ", proto->num_proto); break; case CTA_TIMEOUT: timeout = NFA_DATA(attr); - printf("timeout=%lu ", *timeout); + fprintf(stdout, "timeout=%lu ", *timeout); break; -/* case CTA_ID: - id = NFA_DATA(attr); - printf(" id:%lu ", *id); - break;*/ case CTA_MARK: mark = NFA_DATA(attr); - printf("mark=%lu ", *mark); + fprintf(stdout, "mark=%lu ", *mark); break; case CTA_COUNTERS: ctr = NFA_DATA(attr); - printf("orig_packets=%lu orig_bytes=%lu, " - "reply_packets=%lu reply_bytes=%lu ", + fprintf(stdout, "orig_packets=%llu orig_bytes=%llu, " + "reply_packets=%llu reply_bytes=%llu ", ctr->orig.packets, ctr->orig.bytes, ctr->reply.packets, ctr->reply.bytes); break; @@ -103,7 +119,7 @@ static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); attr = NFA_NEXT(attr, attrlen); } - printf("\n"); + fprintf(stdout, "\n"); return 0; } @@ -154,55 +170,54 @@ static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, DEBUGP("size:%d\n", nlh->nlmsg_len); - printf("type: [%s] ", typemsg2str(type, nlh->nlmsg_flags)); + fprintf(stdout, "[%s] ", typemsg2str(type, nlh->nlmsg_flags)); while (NFA_OK(attr, attrlen)) { switch(attr->nfa_type) { case CTA_ORIG: orig = NFA_DATA(attr); - printf("src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", NIPQUAD(orig->src.ip), NIPQUAD(orig->dst.ip)); h = findproto(proto2str[orig->dst.protonum]); - if (h && h->print) - h->print(orig); + if (h && h->print_tuple) + h->print_tuple(orig); break; case CTA_RPLY: reply = NFA_DATA(attr); - printf("src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", NIPQUAD(reply->src.ip), NIPQUAD(reply->dst.ip)); h = findproto(proto2str[reply->dst.protonum]); - if (h && h->print) - h->print(reply); + if (h && h->print_tuple) + h->print_tuple(reply); break; case CTA_STATUS: status = NFA_DATA(attr); - printf("status:%u ", *status); + print_status(*status); break; case CTA_PROTOINFO: proto = NFA_DATA(attr); - if (proto2str[proto->num_proto]) - printf("%s %d ", proto2str[proto->num_proto], proto->num_proto); - else - printf("unknown %d ", proto->num_proto); + if (proto2str[proto->num_proto]) { + fprintf(stdout, "%s %d ", proto2str[proto->num_proto], proto->num_proto); + h = findproto(proto2str[proto->num_proto]); + if (h && h->print_proto) + h->print_proto(&proto->proto); + } else + fprintf(stdout, "unknown %d ", proto->num_proto); break; case CTA_TIMEOUT: timeout = NFA_DATA(attr); - printf("timeout:%lu ", *timeout); + fprintf(stdout, "timeout:%lu ", *timeout); break; -/* case CTA_ID: - id = NFA_DATA(attr); - printf(" id:%lu ", *id); - break;*/ case CTA_MARK: mark = NFA_DATA(attr); - printf("mark=%lu ", *mark); + fprintf(stdout, "mark=%lu ", *mark); break; case CTA_COUNTERS: ctr = NFA_DATA(attr); - printf("orig_packets=%lu orig_bytes=%lu, " - "reply_packets=%lu reply_bytes=%lu ", + fprintf(stdout, "orig_packets=%llu orig_bytes=%llu, " + "reply_packets=%llu reply_bytes=%llu ", ctr->orig.packets, ctr->orig.bytes, ctr->reply.packets, ctr->reply.bytes); break; @@ -211,7 +226,7 @@ static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); attr = NFA_NEXT(attr, attrlen); } - printf("\n"); + fprintf(stdout, "\n"); return 0; } @@ -246,32 +261,32 @@ static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void * switch(attr->nfa_type) { case CTA_EXP_TUPLE: exp = NFA_DATA(attr); - printf("src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", NIPQUAD(exp->src.ip), NIPQUAD(exp->dst.ip)); h = findproto(proto2str[exp->dst.protonum]); - if (h && h->print) - h->print(exp); + if (h && h->print_tuple) + h->print_tuple(exp); break; case CTA_EXP_MASK: mask = NFA_DATA(attr); - printf("src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", NIPQUAD(mask->src.ip), NIPQUAD(mask->dst.ip)); h = findproto(proto2str[mask->dst.protonum]); - if (h && h->print) - h->print(mask); + if (h && h->print_tuple) + h->print_tuple(mask); break; case CTA_EXP_TIMEOUT: timeout = NFA_DATA(attr); - printf("timeout:%lu ", *timeout); + fprintf(stdout, "timeout:%lu ", *timeout); break; } DEBUGP("nfa->nfa_type: %d\n", attr->nfa_type); DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); attr = NFA_NEXT(attr, attrlen); } - printf("\n"); + fprintf(stdout, "\n"); return 0; } @@ -288,13 +303,11 @@ int create_conntrack(struct ip_conntrack_tuple *orig, cta.num_proto = orig->dst.protonum; memcpy(&cta.proto, proto, sizeof(*proto)); - if (ctnl_open(&cth, 0) < 0) { - printf("error\n"); - exit(0); - } + if (ctnl_open(&cth, 0) < 0) + return -1; /* FIXME: please unify returns values... */ - if (ctnl_new_conntrack(&cth, orig, reply, timeout, proto, status) < 0) + if (ctnl_new_conntrack(&cth, orig, reply, timeout, &cta, status) < 0) return -1; if (ctnl_close(&cth) < 0) @@ -304,8 +317,7 @@ int create_conntrack(struct ip_conntrack_tuple *orig, } int delete_conntrack(struct ip_conntrack_tuple *tuple, - enum ctattr_type_t t, - unsigned long id) + enum ctattr_type_t t) { struct nfattr *cda[CTA_MAX]; struct ctnl_handle cth; @@ -314,7 +326,7 @@ int delete_conntrack(struct ip_conntrack_tuple *tuple, return -1; /* FIXME: please unify returns values... */ - if (ctnl_del_conntrack(&cth, tuple, t, id) < 0) + if (ctnl_del_conntrack(&cth, tuple, t) < 0) return -1; if (ctnl_close(&cth) < 0) @@ -341,7 +353,7 @@ int get_conntrack(struct ip_conntrack_tuple *tuple, ctnl_register_handler(&cth, &h); /* FIXME!!!! get_conntrack_handler returns -100 */ - if (ctnl_get_conntrack(&cth, tuple, t, id) != -100) + if (ctnl_get_conntrack(&cth, tuple, t) != -100) return -1; if (ctnl_close(&cth) < 0) @@ -413,6 +425,10 @@ struct ctproto_handler *findproto(char *name) if (!name) return handler; + lib_dir = getenv("CONNTRACK_LIB_DIR"); + if (!lib_dir) + lib_dir = CONNTRACK_LIB_DIR; + list_for_each(i, &proto_list) { cur = (struct ctproto_handler *) i; if (strcmp(cur->name, name) == 0) { @@ -422,13 +438,13 @@ struct ctproto_handler *findproto(char *name) } if (!handler) { - char path[sizeof("extensions/libct_proto_.so") - + strlen(name)]; - sprintf(path, "extensions/libct_proto_%s.so", name); + char path[sizeof("libct_proto_.so") + + strlen(name) + strlen(lib_dir)]; + sprintf(path, "%s/libct_proto_%s.so", lib_dir, name); if (dlopen(path, RTLD_NOW)) handler = findproto(name); -/* else - fprintf (stderr, "%s\n", dlerror());*/ + else + DEBUGP(stderr, "%s\n", dlerror()); } return handler; @@ -466,16 +482,44 @@ int dump_expect_list() return 0; } -int set_dump_mask(unsigned int mask) +int set_mask(unsigned int mask, int type) { struct ctnl_handle cth; + enum ctattr_type_t cta_type; + + switch(type) { + case 0: + cta_type = CTA_DUMPMASK; + break; + case 1: + cta_type = CTA_EVENTMASK; + break; + default: + return -1; + } if (ctnl_open(&cth, 0) < 0) return -1; - if (ctnl_set_dumpmask(&cth, mask) < 0) + if (ctnl_set_mask(&cth, mask, cta_type) < 0) + return -1; + + if (ctnl_close(&cth) < 0) return -1; + + return 0; +} + +int flush_conntrack() +{ + struct ctnl_handle cth; + if (ctnl_open(&cth, 0) < 0) + return -1; + + if (ctnl_flush_conntrack(&cth) < 0) + return -1; + if (ctnl_close(&cth) < 0) return -1; -- cgit v1.2.3