diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/conntrack.c | 365 | ||||
-rw-r--r-- | src/libct.c | 511 |
2 files changed, 518 insertions, 358 deletions
diff --git a/src/conntrack.c b/src/conntrack.c index d276c17..2c716f7 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -28,11 +28,16 @@ * */ #include <stdio.h> +#include <sys/wait.h> +#include <stdlib.h> #include <getopt.h> #include <stdlib.h> #include <stdarg.h> #include <errno.h> #include <netinet/in.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> #include <linux/netfilter_ipv4/ip_conntrack_tuple.h> #include <linux/netfilter_ipv4/ip_conntrack.h> #include "libctnetlink.h" @@ -41,7 +46,7 @@ #include "libct_proto.h" #define PROGNAME "conntrack" -#define VERSION "0.13" +#define VERSION "0.25" #if 0 #define DEBUGP printf @@ -49,6 +54,10 @@ #define DEBUGP #endif +#ifndef PROC_SYS_MODPROBE +#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" +#endif + enum action { CT_LIST_BIT = 0, CT_LIST = (1 << CT_LIST_BIT), @@ -66,9 +75,12 @@ enum action { CT_FLUSH = (1 << CT_FLUSH_BIT), CT_EVENT_BIT = 5, - CT_EVENT = (1 << CT_EVENT_BIT) + CT_EVENT = (1 << CT_EVENT_BIT), + + CT_ACTION_BIT = 6, + CT_ACTION = (1 << CT_ACTION_BIT) }; -#define NUMBER_OF_CMD 6 +#define NUMBER_OF_CMD 7 enum options { CT_OPT_ORIG_SRC_BIT = 0, @@ -101,19 +113,26 @@ enum options { CT_OPT_ZERO_BIT = 8, CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT), + + CT_OPT_DUMP_MASK_BIT = 9, + CT_OPT_DUMP_MASK = (1 << CT_OPT_DUMP_MASK_BIT), + + CT_OPT_EVENT_MASK_BIT = 10, + CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), }; -#define NUMBER_OF_OPT 9 +#define NUMBER_OF_OPT 11 static const char optflags[NUMBER_OF_OPT] -= { 's', 'd', 'r', 'q', 'p', 'i', 't', 'u', 'z'}; += { 's', 'd', 'r', 'q', 'p', 'i', 't', 'u', 'z','m','g'}; static struct option original_opts[] = { - {"dump", 1, 0, 'L'}, + {"dump", 2, 0, 'L'}, {"create", 1, 0, 'I'}, {"delete", 1, 0, 'D'}, {"get", 1, 0, 'G'}, {"flush", 1, 0, 'F'}, {"event", 1, 0, 'E'}, + {"action", 1, 0, 'A'}, {"orig-src", 1, 0, 's'}, {"orig-dst", 1, 0, 'd'}, {"reply-src", 1, 0, 'r'}, @@ -123,6 +142,8 @@ static struct option original_opts[] = { {"id", 1, 0, 'i'}, {"status", 1, 0, 'u'}, {"zero", 0, 0, 'z'}, + {"dump-mask", 1, 0, 'm'}, + {"groups", 1, 0, 'g'}, {0, 0, 0, 0} }; @@ -143,13 +164,14 @@ 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 */ -/*LIST*/ {'x','x','x','x','x','x','x','x',' '}, -/*CREATE*/ {'+','+','+','+','+','x','+','+','x'}, -/*DELETE*/ {' ',' ',' ',' ',' ','+','x','x','x'}, -/*GET*/ {' ',' ',' ',' ','+','+','x','x','x'}, -/*FLUSH*/ {'x','x','x','x','x','x','x','x','x'}, -/*EVENT*/ {'x','x','x','x','x','x','x','x','x'} + /* -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'}, +/*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'}, }; LIST_HEAD(proto_list); @@ -188,7 +210,7 @@ exit_error(enum exittype status, char *msg, ...) global_option_offset = 0; } va_start(args, msg); - fprintf(stderr, "%s v%s: ", PROGNAME, VERSION); + fprintf(stderr,"%s v%s: ", PROGNAME, VERSION); vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, "\n"); @@ -256,52 +278,191 @@ merge_options(struct option *oldopts, const struct option *newopts, return merge; } +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", + tp, tp->dst.protonum, + NIPQUAD(tp->src.ip), ntohs(tp->src.u.all), + NIPQUAD(tp->dst.ip), ntohs(tp->dst.u.all)); +} + void not_implemented_yet() { exit_error(OTHER_PROBLEM, "Sorry, not implemented yet :(\n"); } -unsigned int check_type() +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); +} + +static int +do_parse_group(const char *str, size_t strlen, unsigned int *group) +{ + 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; +} + +static void +parse_group(const char *arg, unsigned int *group) { - unsigned int type = 0; + 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); + arg = comma+1; + } - if (!optarg) - exit_error(PARAMETER_PROBLEM, "must specified `conntrack' or " - "`expect'\n"); + if (strlen(arg) == 0 || !do_parse_group(arg, strlen(arg), group)) + exit_error(PARAMETER_PROBLEM, "Bad status `%s'", arg); +} + +unsigned int check_type(int argc, char *argv[]) +{ + char *table = NULL; + + /* Nasty bug or feature in getopt_long ? + * It seems that it behaves badly with optional arguments. + * Fortunately, I just stole the fix from iptables ;) */ + if (optarg) + return 0; + else if (optind < argc && argv[optind][0] != '-' + && argv[optind][0] != '!') + table = argv[optind++]; - if (strncmp("conntrack", optarg, 9) == 0) - type = 0; - else if (strncmp("expect", optarg, 6) == 0) - type = 1; - else { - exit_error(PARAMETER_PROBLEM, "unknown type `%s'\n", optarg); + if (!table) + return 0; + + if (strncmp("expect", table, 6) == 0) + return 1; + else if (strncmp("conntrack", table, 9) == 0) + return 0; + else + exit_error(PARAMETER_PROBLEM, "unknown type `%s'\n", table); + + return 0; +} + +static char *get_modprobe(void) +{ + int procfile; + char *ret; + +#define PROCFILE_BUFSIZ 1024 + procfile = open(PROC_SYS_MODPROBE, O_RDONLY); + if (procfile < 0) + return NULL; + + ret = (char *) malloc(PROCFILE_BUFSIZ); + if (ret) { + memset(ret, 0, PROCFILE_BUFSIZ); + switch (read(procfile, ret, PROCFILE_BUFSIZ)) { + case -1: goto fail; + case PROCFILE_BUFSIZ: goto fail; /* Partial read. Weird */ + } + if (ret[strlen(ret)-1]=='\n') + ret[strlen(ret)-1]=0; + close(procfile); + return ret; + } + fail: + free(ret); + close(procfile); + return NULL; +} + +int iptables_insmod(const char *modname, const char *modprobe) +{ + char *buf = NULL; + char *argv[3]; + int status; + + /* If they don't explicitly set it, read out of kernel */ + if (!modprobe) { + buf = get_modprobe(); + if (!buf) + return -1; + modprobe = buf; } - return type; + switch (fork()) { + case 0: + argv[0] = (char *)modprobe; + argv[1] = (char *)modname; + argv[2] = NULL; + execv(argv[0], argv); + + /* not usually reached */ + exit(1); + case -1: + return -1; + + default: /* parent */ + wait(&status); + } + + free(buf); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + return 0; + return -1; } void usage(char *prog) { -printf("Tool to manipulate conntrack and expectations. Version %s\n", VERSION); -printf("Usage: %s [commands] [options]\n", prog); -printf("\n"); -printf("Commands:\n"); -printf("-L table List conntrack or expectation table\n"); -printf("-G table [options] Get conntrack or expectation\n"); -printf("-D table [options] Delete conntrack or expectation\n"); -printf("-I table [options] Create a conntrack or expectation\n"); -printf("-E table Show events\n"); -printf("-F table Flush table\n"); -printf("\n"); -printf("Options:\n"); -printf("--orig-src Source address from original direction\n"); -printf("--orig-dst Destination address from original direction\n"); -printf("--reply-src Source addres from reply direction\n"); -printf("--reply-dst Destination address from reply direction\n"); -printf("-p Layer 4 Protocol\n"); -printf("-t Timeout\n"); -printf("-i Conntrack ID\n"); -printf("-u Status\n"); -printf("-z Zero Counters\n"); +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"); } int main(int argc, char *argv[]) @@ -314,7 +475,8 @@ int main(int argc, char *argv[]) unsigned long timeout = 0; unsigned int status = 0; unsigned long id = 0; - unsigned int type = 0; + unsigned int type = 0, 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)); @@ -323,31 +485,42 @@ int main(int argc, char *argv[]) reply.dst.dir = IP_CT_DIR_REPLY; while ((c = getopt_long(argc, argv, - "L:I:D:G:E:s:d:r:q:p:i:t:u:z", opts, NULL)) != -1) { + "L::I::D::G::E::A::s:d:r:q:p:i:t:u:m:g:z", + opts, NULL)) != -1) { switch(c) { case 'L': command |= CT_LIST; - type = check_type(); + type = check_type(argc, argv); break; case 'I': command |= CT_CREATE; - type = check_type(); + type = check_type(argc, argv); break; case 'D': command |= CT_DELETE; - type = check_type(); + type = check_type(argc, argv); break; case 'G': command |= CT_GET; - type = check_type(); + type = check_type(argc, argv); break; case 'F': command |= CT_FLUSH; - type = check_type(); + type = check_type(argc, argv); break; case 'E': command |= CT_EVENT; - type = check_type(); + type = check_type(argc, argv); + break; + case 'A': + command |= CT_ACTION; + type = check_type(argc, argv); + case 'm': + if (!optarg) + continue; + + options |= CT_OPT_DUMP_MASK; + mask = atoi(optarg); break; case 's': options |= CT_OPT_ORIG_SRC; @@ -394,23 +567,22 @@ int main(int argc, char *argv[]) continue; options |= CT_OPT_STATUS; + parse_status(optarg, &status); /* Just insert confirmed conntracks */ status |= IPS_CONFIRMED; - if (strncmp("SEEN_REPLY", optarg, strlen("SEEN_REPLY")) == 0) - status |= IPS_SEEN_REPLY; - else if (strncmp("ASSURED", optarg, strlen("ASSURED")) == 0) - status |= IPS_ASSURED; - else - exit_error(PARAMETER_PROBLEM, "Invalid status" - "flag: %s\n", optarg); break; } + case 'g': + options |= CT_OPT_EVENT_MASK; + parse_group(optarg, &event_mask); + break; case 'z': options |= CT_OPT_ZERO; break; default: - if (h && !h->parse(c - h->option_offset, argv, - &orig, &reply)) + if (h && h->parse && !h->parse(c - h->option_offset, + argv, &orig, &reply, + &proto, &extra_flags)) exit_error(PARAMETER_PROBLEM, "parse error\n"); /* Unknown argument... */ @@ -425,58 +597,84 @@ int main(int argc, char *argv[]) generic_opt_check(command, options); - switch(command) { + while (retry > 0) { + retry--; + switch(command) { case CT_LIST: - printf("list\n"); if (type == 0) { if (options & CT_OPT_ZERO) - dump_conntrack_table(1); + res = dump_conntrack_table(1); else - dump_conntrack_table(0); - } else - dump_expect_list(); + res = dump_conntrack_table(0); + } else + res = dump_expect_list(); break; + case CT_CREATE: - printf("create\n"); + fprintf(stderr, "create\n"); if (type == 0) create_conntrack(&orig, &reply, timeout, &proto, status); else not_implemented_yet(); break; + case CT_DELETE: - printf("delete\n"); + fprintf(stderr, "delete\n"); if (type == 0) { if (options & CT_OPT_ORIG) - delete_conntrack(&orig, CTA_ORIG, id); + res =delete_conntrack(&orig, CTA_ORIG, + id); else if (options & CT_OPT_REPL) - delete_conntrack(&reply, CTA_RPLY, id); + res = delete_conntrack(&reply, CTA_RPLY, + id); } else not_implemented_yet(); break; + case CT_GET: - printf("get\n"); + fprintf(stderr, "get\n"); if (type == 0) { if (options & CT_OPT_ORIG) - get_conntrack(&orig, CTA_ORIG, id); + res = get_conntrack(&orig, CTA_ORIG, + id); else if (options & CT_OPT_REPL) - get_conntrack(&reply, CTA_RPLY, id); + res = get_conntrack(&reply, CTA_RPLY, + id); } else not_implemented_yet(); break; + case CT_FLUSH: not_implemented_yet(); break; + case CT_EVENT: - printf("event\n"); - if (type == 0) - event_conntrack(); - else + if (type == 0) { + if (options & CT_OPT_EVENT_MASK) + res = event_conntrack(event_mask); + else + res = event_conntrack(~0U); + } else /* and surely it won't ever... */ not_implemented_yet(); - default: + + case CT_ACTION: + if (type == 0) + if (options & CT_OPT_DUMP_MASK) + res = set_dump_mask(mask); + break; + + default: usage(argv[0]); break; + } + /* Maybe ip_conntrack_netlink isn't insmod'ed */ + if (res == -1 && retry) + /* Give it a try just once */ + iptables_insmod("ip_conntrack_netlink", NULL); + else + retry--; } if (opts != original_opts) { @@ -484,4 +682,7 @@ int main(int argc, char *argv[]) opts = original_opts; global_option_offset = 0; } + + if (res == -1) + fprintf(stderr, "Operations failed\n"); } diff --git a/src/libct.c b/src/libct.c index 47743d8..143901b 100644 --- a/src/libct.c +++ b/src/libct.c @@ -19,31 +19,20 @@ extern struct list_head proto_list; extern char *proto2str[]; -/* Built-in generic proto handler */ - -/* FIXME: This should die... */ -static int parse(char c, char *argv[], - struct ip_conntrack_tuple *orig, - struct ip_conntrack_tuple *reply) { - return 0; -} -/* FIXME: die die too... */ -static void print(struct ip_conntrack_tuple *t) {} - -static struct ctproto_handler generic_handler = { - .name = "generic", - .protonum = 0, - .parse = parse, - .print = print, - .opts = NULL -}; - static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) { struct nfgenmsg *nfmsg; struct nfattr *nfa; int min_len = 0; struct ctproto_handler *h = NULL; + struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); + int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); + + struct ip_conntrack_tuple *orig, *reply; + struct cta_counters *ctr; + unsigned long *status, *timeout; + struct cta_proto *proto; + unsigned long *id, *mark; DEBUGP("netlink header\n"); DEBUGP("len: %d type: %d flags: %d seq: %d pid: %d\n", @@ -59,76 +48,62 @@ static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) DEBUGP("size:%d\n", nlh->nlmsg_len); - while (nlh->nlmsg_len > min_len) { - struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); - int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - - struct ip_conntrack_tuple *orig, *reply; - struct cta_counters *ctr; - unsigned long *status, *timeout; - struct cta_proto *proto; - unsigned long *id, *mark; - - 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 ", - NIPQUAD(orig->src.ip), - NIPQUAD(orig->dst.ip)); - h = findproto(proto2str[orig->dst.protonum]); - if (h) - h->print(orig); - break; - case CTA_RPLY: - reply = NFA_DATA(attr); - printf("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(reply); - break; - case CTA_STATUS: - status = NFA_DATA(attr); - printf("status=%u ", *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); - break; - case CTA_TIMEOUT: - timeout = NFA_DATA(attr); - printf("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); - break; - case CTA_COUNTERS: - ctr = NFA_DATA(attr); - printf("orig_packets=%lu orig_bytes=%lu, " - "reply_packets=%lu reply_bytes=%lu ", - ctr->orig.packets, ctr->orig.bytes, - ctr->reply.packets, ctr->reply.bytes); - break; - } - DEBUGP("nfa->nfa_type: %d\n", attr->nfa_type); - DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); - attr = NFA_NEXT(attr, attrlen); + 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 ", + NIPQUAD(orig->src.ip), + NIPQUAD(orig->dst.ip)); + h = findproto(proto2str[orig->dst.protonum]); + if (h && h->print) + h->print(orig); + break; + case CTA_RPLY: + reply = NFA_DATA(attr); + printf("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); + break; + case CTA_STATUS: + status = NFA_DATA(attr); + printf("status=%u ", *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); + break; + case CTA_TIMEOUT: + timeout = NFA_DATA(attr); + printf("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); + break; + case CTA_COUNTERS: + ctr = NFA_DATA(attr); + printf("orig_packets=%lu orig_bytes=%lu, " + "reply_packets=%lu reply_bytes=%lu ", + ctr->orig.packets, ctr->orig.bytes, + ctr->reply.packets, ctr->reply.bytes); + break; } - min_len += nlh->nlmsg_len; - nlh = (struct nlmsghdr *) attr; - printf("\n"); + DEBUGP("nfa->nfa_type: %d\n", attr->nfa_type); + DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); + attr = NFA_NEXT(attr, attrlen); } - DEBUGP("exit from handler\n"); + printf("\n"); return 0; } @@ -156,6 +131,14 @@ static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, int min_len = 0; struct ctproto_handler *h = NULL; int type = NFNL_MSG_TYPE(nlh->nlmsg_type); + struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); + int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); + + struct ip_conntrack_tuple *orig, *reply; + struct cta_counters *ctr; + unsigned long *status, *timeout, *mark; + struct cta_proto *proto; + unsigned long *id; DEBUGP("netlink header\n"); DEBUGP("len: %d type: %d flags: %d seq: %d pid: %d\n", @@ -173,76 +156,62 @@ static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, printf("type: [%s] ", typemsg2str(type, nlh->nlmsg_flags)); - while (nlh->nlmsg_len > min_len) { - struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); - int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - - struct ip_conntrack_tuple *orig, *reply; - struct cta_counters *ctr; - unsigned long *status, *timeout, *mark; - struct cta_proto *proto; - unsigned long *id; - - 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 ", - NIPQUAD(orig->src.ip), - NIPQUAD(orig->dst.ip)); - h = findproto(proto2str[orig->dst.protonum]); - if (h) - h->print(orig); - break; - case CTA_RPLY: - reply = NFA_DATA(attr); - printf("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(reply); - break; - case CTA_STATUS: - status = NFA_DATA(attr); - printf("status:%u ", *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); - break; - case CTA_TIMEOUT: - timeout = NFA_DATA(attr); - printf("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); - break; - case CTA_COUNTERS: - ctr = NFA_DATA(attr); - printf("orig_packets=%lu orig_bytes=%lu, " - "reply_packets=%lu reply_bytes=%lu ", - ctr->orig.packets, ctr->orig.bytes, - ctr->reply.packets, ctr->reply.bytes); - break; - } - DEBUGP("nfa->nfa_type: %d\n", attr->nfa_type); - DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); - attr = NFA_NEXT(attr, attrlen); + 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 ", + NIPQUAD(orig->src.ip), + NIPQUAD(orig->dst.ip)); + h = findproto(proto2str[orig->dst.protonum]); + if (h && h->print) + h->print(orig); + break; + case CTA_RPLY: + reply = NFA_DATA(attr); + printf("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); + break; + case CTA_STATUS: + status = NFA_DATA(attr); + printf("status:%u ", *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); + break; + case CTA_TIMEOUT: + timeout = NFA_DATA(attr); + printf("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); + break; + case CTA_COUNTERS: + ctr = NFA_DATA(attr); + printf("orig_packets=%lu orig_bytes=%lu, " + "reply_packets=%lu reply_bytes=%lu ", + ctr->orig.packets, ctr->orig.bytes, + ctr->reply.packets, ctr->reply.bytes); + break; } - min_len += nlh->nlmsg_len; - nlh = (struct nlmsghdr *) attr; - printf("\n"); + DEBUGP("nfa->nfa_type: %d\n", attr->nfa_type); + DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); + attr = NFA_NEXT(attr, attrlen); } - DEBUGP("exit from handler\n"); + printf("\n"); return 0; } @@ -253,6 +222,11 @@ static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void * struct nfattr *nfa; int min_len = 0; struct ctproto_handler *h = NULL; + struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); + int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); + + struct ip_conntrack_tuple *exp, *mask; + unsigned long *timeout; DEBUGP("netlink header\n"); DEBUGP("len: %d type: %d flags: %d seq: %d pid: %d\n", @@ -268,56 +242,45 @@ static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void * DEBUGP("size:%d\n", nlh->nlmsg_len); - while (nlh->nlmsg_len > min_len) { - struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); - int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - - struct ip_conntrack_tuple *exp, *mask; - unsigned long *timeout; - - while (NFA_OK(attr, attrlen)) { - switch(attr->nfa_type) { - case CTA_EXP_TUPLE: - exp = NFA_DATA(attr); - printf("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(exp); - break; - case CTA_EXP_MASK: - mask = NFA_DATA(attr); - printf("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(mask); - break; - case CTA_EXP_TIMEOUT: - timeout = NFA_DATA(attr); - printf("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); + while (NFA_OK(attr, attrlen)) { + switch(attr->nfa_type) { + case CTA_EXP_TUPLE: + exp = NFA_DATA(attr); + printf("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); + break; + case CTA_EXP_MASK: + mask = NFA_DATA(attr); + printf("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); + break; + case CTA_EXP_TIMEOUT: + timeout = NFA_DATA(attr); + printf("timeout:%lu ", *timeout); + break; } - min_len += nlh->nlmsg_len; - nlh = (struct nlmsghdr *) attr; - printf("\n"); + DEBUGP("nfa->nfa_type: %d\n", attr->nfa_type); + DEBUGP("nfa->nfa_len: %d\n", attr->nfa_len); + attr = NFA_NEXT(attr, attrlen); } - DEBUGP("exit from handler\n"); + printf("\n"); return 0; } -void create_conntrack(struct ip_conntrack_tuple *orig, - struct ip_conntrack_tuple *reply, - unsigned long timeout, - union ip_conntrack_proto *proto, - unsigned int status) +int create_conntrack(struct ip_conntrack_tuple *orig, + struct ip_conntrack_tuple *reply, + unsigned long timeout, + union ip_conntrack_proto *proto, + unsigned int status) { struct cta_proto cta; struct nfattr *cda[CTA_MAX]; @@ -331,45 +294,39 @@ void create_conntrack(struct ip_conntrack_tuple *orig, } /* FIXME: please unify returns values... */ - if (ctnl_new_conntrack(&cth, orig, reply, timeout, proto, status) < 0) { - printf("error new conntrack\n"); - exit(0); - } + if (ctnl_new_conntrack(&cth, orig, reply, timeout, proto, status) < 0) + return -1; - if (ctnl_close(&cth) < 0) { - printf("error2"); - exit(0); - } + if (ctnl_close(&cth) < 0) + return -1; + + return 0; } -void delete_conntrack(struct ip_conntrack_tuple *tuple, - enum ctattr_type_t t, - unsigned long id) +int delete_conntrack(struct ip_conntrack_tuple *tuple, + enum ctattr_type_t t, + unsigned long id) { struct nfattr *cda[CTA_MAX]; struct ctnl_handle cth; - 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_del_conntrack(&cth, tuple, t, id) < 0) { - printf("error del conntrack\n"); - exit(0); - } + if (ctnl_del_conntrack(&cth, tuple, t, id) < 0) + return -1; - if (ctnl_close(&cth) < 0) { - printf("error2"); - exit(0); - } + if (ctnl_close(&cth) < 0) + return -1; + + return 0; } /* get_conntrack_handler */ -void get_conntrack(struct ip_conntrack_tuple *tuple, - enum ctattr_type_t t, - unsigned long id) +int get_conntrack(struct ip_conntrack_tuple *tuple, + enum ctattr_type_t t, + unsigned long id) { struct nfattr *cda[CTA_MAX]; struct ctnl_handle cth; @@ -378,26 +335,22 @@ void get_conntrack(struct ip_conntrack_tuple *tuple, .handler = handler }; - if (ctnl_open(&cth, 0) < 0) { - printf("error\n"); - exit(0); - } + if (ctnl_open(&cth, 0) < 0) + return -1; ctnl_register_handler(&cth, &h); /* FIXME!!!! get_conntrack_handler returns -100 */ - if (ctnl_get_conntrack(&cth, tuple, t, id) != -100) { - printf("error get conntrack\n"); - exit(0); - } + if (ctnl_get_conntrack(&cth, tuple, t, id) != -100) + return -1; - if (ctnl_close(&cth) < 0) { - printf("error2"); - exit(0); - } + if (ctnl_close(&cth) < 0) + return -1; + + return 0; } -void dump_conntrack_table(int zero) +int dump_conntrack_table(int zero) { int ret; struct ctnl_handle cth; @@ -406,10 +359,8 @@ void dump_conntrack_table(int zero) .handler = handler }; - if (ctnl_open(&cth, 0) < 0) { - printf("error\n"); - exit(0); - } + if (ctnl_open(&cth, 0) < 0) + return -1; ctnl_register_handler(&cth, &h); @@ -418,18 +369,16 @@ void dump_conntrack_table(int zero) } else ret = ctnl_list_conntrack(&cth, AF_INET); - if (ret != -100) { - printf("error list\n"); - exit(0); - } + if (ret != -100) + return -1; - if (ctnl_close(&cth) < 0) { - printf("error2\n"); - exit(0); - } + if (ctnl_close(&cth) < 0) + return -1; + + return 0; } -void event_conntrack() +int event_conntrack(unsigned int event_mask) { struct ctnl_handle cth; struct ctnl_msg_handler hnew = { @@ -441,19 +390,18 @@ void event_conntrack() .handler = event_handler }; - if (ctnl_open(&cth, NFGRP_IPV4_CT_TCP) < 0) { - printf("error\n"); - exit(0); - } + if (ctnl_open(&cth, event_mask) < 0) + return -1; ctnl_register_handler(&cth, &hnew); ctnl_register_handler(&cth, &hdestroy); - ctnl_event_conntrack(&cth, AF_INET); + if (ctnl_event_conntrack(&cth, AF_INET) < 0) + return -1; - if (ctnl_close(&cth) < 0) { - printf("error2\n"); - exit(0); - } + if (ctnl_close(&cth) < 0) + return -1; + + return 0; } struct ctproto_handler *findproto(char *name) @@ -462,6 +410,9 @@ struct ctproto_handler *findproto(char *name) struct list_head *i; struct ctproto_handler *cur = NULL, *handler = NULL; + if (!name) + return handler; + list_for_each(i, &proto_list) { cur = (struct ctproto_handler *) i; if (strcmp(cur->name, name) == 0) { @@ -480,9 +431,6 @@ struct ctproto_handler *findproto(char *name) fprintf (stderr, "%s\n", dlerror());*/ } - if (!handler) - handler = &generic_handler; - return handler; } @@ -496,7 +444,7 @@ void unregister_proto(struct ctproto_handler *h) list_del(&h->head); } -void dump_expect_list() +int dump_expect_list() { struct ctnl_handle cth; struct ctnl_msg_handler h = { @@ -504,21 +452,32 @@ void dump_expect_list() .handler = expect_handler }; - if (ctnl_open(&cth, 0) < 0) { - printf("error\n"); - exit(0); - } + if (ctnl_open(&cth, 0) < 0) + return -1; ctnl_register_handler(&cth, &h); - if (ctnl_list_expect(&cth, AF_INET) != -100) { - printf("error list\n"); - exit(0); - } + if (ctnl_list_expect(&cth, AF_INET) != -100) + return -1; - if (ctnl_close(&cth) < 0) { - printf("error2\n"); - exit(0); - } + if (ctnl_close(&cth) < 0) + return -1; + + return 0; } +int set_dump_mask(unsigned int mask) +{ + struct ctnl_handle cth; + + if (ctnl_open(&cth, 0) < 0) + return -1; + + if (ctnl_set_dumpmask(&cth, mask) < 0) + return -1; + + if (ctnl_close(&cth) < 0) + return -1; + + return 0; +} |