From c7c7bbb573e310ca6fa6040e11f86440c9380ad7 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: Fri, 28 Oct 2005 00:28:35 +0000 Subject: o Renamed nfct_[set|unset]_callback to nfct_[register|unregister]_callback o Added some very brief comments to libnetfilter_conntrack.h o Implemented the conntrack printers API nfct_sprintf_* o Now nfct_default_conntrack_display display the classical /proc output, and nfct_default_conntrack_display the classical + conntrack ids o Use nfnl_talk if there's no data expected from kernel space to be processed, that is the case of nfct_[get|delete]_conntrack o Added some missing memset's zeroing o Code simplification: killed some char *buf where struct nfnlhdr is enough o Killed protocol handler destructors (fini) and nfct_unregister_proto: The library is unloaded if something goes wrong (different library versions), the modules never gets inserted in the proto_list. Fixes a segfault. o Bumped version to 0.2.0 --- extensions/libnetfilter_conntrack_icmp.c | 6 - extensions/libnetfilter_conntrack_sctp.c | 6 - extensions/libnetfilter_conntrack_tcp.c | 6 - extensions/libnetfilter_conntrack_udp.c | 6 - .../libnetfilter_conntrack.h | 55 ++++- src/libnetfilter_conntrack.c | 224 +++++++++++++-------- utils/ctnl_test.c | 4 +- 7 files changed, 195 insertions(+), 112 deletions(-) diff --git a/extensions/libnetfilter_conntrack_icmp.c b/extensions/libnetfilter_conntrack_icmp.c index 38ad41a..8f1ccb1 100644 --- a/extensions/libnetfilter_conntrack_icmp.c +++ b/extensions/libnetfilter_conntrack_icmp.c @@ -52,14 +52,8 @@ static struct nfct_proto icmp = { }; void __attribute__ ((constructor)) init(void); -void __attribute__ ((destructor)) fini(void); void init(void) { nfct_register_proto(&icmp); } - -void fini(void) -{ - nfct_unregister_proto(&icmp); -} diff --git a/extensions/libnetfilter_conntrack_sctp.c b/extensions/libnetfilter_conntrack_sctp.c index a42a6c8..5b7f9e0 100644 --- a/extensions/libnetfilter_conntrack_sctp.c +++ b/extensions/libnetfilter_conntrack_sctp.c @@ -56,14 +56,8 @@ static struct nfct_proto sctp = { }; void __attribute__ ((constructor)) init(void); -void __attribute__ ((destructor)) fini(void); void init(void) { nfct_register_proto(&sctp); } - -void fini(void) -{ - nfct_unregister_proto(&sctp); -} diff --git a/extensions/libnetfilter_conntrack_tcp.c b/extensions/libnetfilter_conntrack_tcp.c index 5b53fd1..fe0e632 100644 --- a/extensions/libnetfilter_conntrack_tcp.c +++ b/extensions/libnetfilter_conntrack_tcp.c @@ -71,14 +71,8 @@ static struct nfct_proto tcp = { }; void __attribute__ ((constructor)) init(void); -void __attribute__ ((destructor)) fini(void); void init(void) { nfct_register_proto(&tcp); } - -void fini(void) -{ - nfct_unregister_proto(&tcp); -} diff --git a/extensions/libnetfilter_conntrack_udp.c b/extensions/libnetfilter_conntrack_udp.c index de7c9f7..940bf67 100644 --- a/extensions/libnetfilter_conntrack_udp.c +++ b/extensions/libnetfilter_conntrack_udp.c @@ -40,14 +40,8 @@ static struct nfct_proto udp = { }; void __attribute__ ((constructor)) init(void); -void __attribute__ ((destructor)) fini(void); void init(void) { nfct_register_proto(&udp); } - -void fini(void) -{ - nfct_unregister_proto(&udp); -} diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h index f642163..55391bb 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -17,7 +17,7 @@ #include #include "linux_list.h" -#define LIBNETFILTER_CONNTRACK_VERSION "0.1.3" +#define LIBNETFILTER_CONNTRACK_VERSION "0.2.0" enum { CONNTRACK = NFNL_SUBSYS_CTNETLINK, @@ -169,6 +169,11 @@ struct nfct_handle { nfct_handler handler; /* netlink handler */ }; +extern void nfct_register_proto(struct nfct_proto *h); + +/* + * [Allocate|free] a conntrack + */ extern struct nfct_conntrack * nfct_conntrack_alloc(struct nfct_tuple *orig, struct nfct_tuple *reply, unsigned long timeout, union nfct_protoinfo *proto, @@ -176,26 +181,38 @@ nfct_conntrack_alloc(struct nfct_tuple *orig, struct nfct_tuple *reply, unsigned int id, struct nfct_nat *range); extern void nfct_conntrack_free(struct nfct_conntrack *ct); +/* + * [Allocate|free] an expectation + */ extern struct nfct_expect * nfct_expect_alloc(struct nfct_tuple *master, struct nfct_tuple *tuple, struct nfct_tuple *mask, unsigned long timeout, unsigned int id); extern void nfct_expect_free(struct nfct_expect *exp); -extern void nfct_register_proto(struct nfct_proto *h); -extern void nfct_unregister_proto(struct nfct_proto *h); - +/* + * [Open|close] a conntrack handler + */ extern struct nfct_handle *nfct_open(u_int8_t, unsigned); extern int nfct_close(struct nfct_handle *cth); -extern void nfct_set_callback(struct nfct_handle *cth, nfct_callback callback); -extern void nfct_unset_callback(struct nfct_handle *cth); + +/* + * [Register|unregister] callbacks + */ +extern void nfct_register_callback(struct nfct_handle *cth, + nfct_callback callback); +extern void nfct_unregister_callback(struct nfct_handle *cth); /* * callback displayers */ extern int nfct_default_conntrack_display(void *arg, unsigned int, int); +extern int nfct_default_conntrack_display_id(void *arg, unsigned int, int); extern int nfct_default_expect_display(void *arg, unsigned int, int); +/* + * [Create|update|get|destroy] conntracks + */ extern int nfct_create_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct); extern int nfct_update_conntrack(struct nfct_handle *cth, @@ -206,10 +223,36 @@ extern int nfct_delete_conntrack(struct nfct_handle *cth, extern int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, int dir, unsigned int id); +/* + * Conntrack table dumping & zeroing + */ extern int nfct_dump_conntrack_table(struct nfct_handle *cth); extern int nfct_dump_conntrack_table_reset_counters(struct nfct_handle *cth); + +/* + * Conntrack event notification + */ extern int nfct_event_conntrack(struct nfct_handle *cth); +/* + * Conntrack printing functions + */ +extern int nfct_sprintf_conntrack(char *buf, struct nfct_conntrack *ct, + unsigned int flags); +extern int nfct_sprintf_conntrack_id(char *buf, struct nfct_conntrack *ct, + unsigned int flags); +extern int nfct_sprintf_address(char *buf, struct nfct_conntrack *ct, int dir); +extern int nfct_sprintf_proto(char *buf, struct nfct_conntrack *ct, int dir); +extern int nfct_sprintf_protoinfo(char *buf, struct nfct_conntrack *ct); +extern int nfct_sprintf_timeout(char *buf, struct nfct_conntrack *ct); +extern int nfct_sprintf_protocol(char *buf, struct nfct_conntrack *ct); +extern int nfct_sprintf_status_assured(char *buf, struct nfct_conntrack *ct); +extern int nfct_sprintf_status_seen_reply(char *buf, struct nfct_conntrack *ct); +extern int nfct_sprintf_counters(char *buf, struct nfct_conntrack *ct, int dir); +extern int nfct_sprintf_mark(char *buf, struct nfct_conntrack *ct); +extern int nfct_sprintf_use(char *buf, struct nfct_conntrack *ct); +extern int nfct_sprintf_id(char *buf, struct nfct_conntrack *ct); + /* * Expectations */ diff --git a/src/libnetfilter_conntrack.c b/src/libnetfilter_conntrack.c index 1dee547..cbef0db 100644 --- a/src/libnetfilter_conntrack.c +++ b/src/libnetfilter_conntrack.c @@ -102,12 +102,12 @@ int nfct_close(struct nfct_handle *cth) return err; } -void nfct_set_callback(struct nfct_handle *cth, nfct_callback callback) +void nfct_register_callback(struct nfct_handle *cth, nfct_callback callback) { cth->callback = callback; } -void nfct_unset_callback(struct nfct_handle *cth) +void nfct_unregister_callback(struct nfct_handle *cth) { cth->callback = NULL; } @@ -306,14 +306,22 @@ static struct nfct_proto *findproto(char *name) return handler; } -static int print_status(char *buf, unsigned int status) +int nfct_sprintf_status_assured(char *buf, struct nfct_conntrack *ct) { int size = 0; - if (status & IPS_ASSURED) + if (ct->status & IPS_ASSURED) size = sprintf(buf, "[ASSURED] "); - if (!(status & IPS_SEEN_REPLY)) - size += sprintf(buf+size, "[UNREPLIED] "); + + return size; +} + +int nfct_sprintf_status_seen_reply(char *buf, struct nfct_conntrack *ct) +{ + int size = 0; + + if (!(ct->status & IPS_SEEN_REPLY)) + size = sprintf(buf, "[UNREPLIED] "); return size; } @@ -483,60 +491,142 @@ static int nfct_conntrack_netlink_handler(struct nfct_handle *cth, return ret; } -int nfct_default_conntrack_display(void *arg, unsigned int flags, int type) +int nfct_sprintf_protocol(char *buf, struct nfct_conntrack *ct) { - struct nfct_conntrack *ct = arg; - struct nfct_proto *h = NULL; - char buf[512]; - int size = 0; - - size += sprintf(buf, "%-8s %u ", + return (sprintf(buf, "%-8s %u ", proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum] == NULL ? "unknown" : proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum], - ct->tuple[NFCT_DIR_ORIGINAL].protonum); + ct->tuple[NFCT_DIR_ORIGINAL].protonum)); +} - if (flags & NFCT_TIMEOUT) - size += sprintf(buf+size, "%lu ", ct->timeout); +int nfct_sprintf_timeout(char *buf, struct nfct_conntrack *ct) +{ + return sprintf(buf, "%lu ", ct->timeout); +} - h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]); - if ((flags & NFCT_PROTOINFO) && h && h->print_protoinfo) - size += h->print_protoinfo(buf+size, &ct->protoinfo); +int nfct_sprintf_protoinfo(char *buf, struct nfct_conntrack *ct) +{ + int size = 0; + struct nfct_proto *h = NULL; + + h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]); + if (h && h->print_protoinfo) + size += h->print_protoinfo(buf+size, &ct->protoinfo); + + return size; +} - size += sprintf(buf+size, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", - NIPQUAD(ct->tuple[NFCT_DIR_ORIGINAL].src.v4), - NIPQUAD(ct->tuple[NFCT_DIR_ORIGINAL].dst.v4)); +int nfct_sprintf_address(char *buf, struct nfct_conntrack *ct, int dir) +{ + return (sprintf(buf, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + NIPQUAD(ct->tuple[dir].src.v4), + NIPQUAD(ct->tuple[dir].dst.v4))); +} +int nfct_sprintf_proto(char *buf, struct nfct_conntrack *ct, int dir) +{ + int size = 0; + struct nfct_proto *h = NULL; + + h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]); if (h && h->print_proto) - size += h->print_proto(buf+size, &ct->tuple[NFCT_DIR_ORIGINAL]); + size += h->print_proto(buf, &ct->tuple[dir]); + + return size; +} + +int nfct_sprintf_counters(char *buf, struct nfct_conntrack *ct, int dir) +{ + return (sprintf(buf, "packets=%llu bytes=%llu ", + ct->counters[dir].packets, + ct->counters[dir].bytes)); +} + +int nfct_sprintf_mark(char *buf, struct nfct_conntrack *ct) +{ + return (sprintf(buf, "mark=%lu ", ct->mark)); +} + +int nfct_sprintf_use(char *buf, struct nfct_conntrack *ct) +{ + return (sprintf(buf, "use=%u ", ct->use)); +} + +int nfct_sprintf_id(char *buf, struct nfct_conntrack *ct) +{ + return (sprintf(buf, "id=%u ", ct->id)); +} + +int nfct_sprintf_conntrack(char *buf, struct nfct_conntrack *ct, + unsigned int flags) +{ + int size = 0; + + size += nfct_sprintf_protocol(buf, ct); + + if (flags & NFCT_TIMEOUT) + size += nfct_sprintf_timeout(buf+size, ct); + + if (flags & NFCT_PROTOINFO) + size += nfct_sprintf_protoinfo(buf+size, ct); + + size += nfct_sprintf_address(buf+size, ct, NFCT_DIR_ORIGINAL); + size += nfct_sprintf_proto(buf+size, ct, NFCT_DIR_ORIGINAL); if (flags & NFCT_COUNTERS_ORIG) - size += sprintf(buf+size, "packets=%llu bytes=%llu ", - ct->counters[NFCT_DIR_ORIGINAL].packets, - ct->counters[NFCT_DIR_ORIGINAL].bytes); + size += nfct_sprintf_counters(buf+size, ct, NFCT_DIR_ORIGINAL); - size += sprintf(buf+size, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", - NIPQUAD(ct->tuple[NFCT_DIR_REPLY].src.v4), - NIPQUAD(ct->tuple[NFCT_DIR_REPLY].dst.v4)); + if (flags & NFCT_STATUS) + size += nfct_sprintf_status_seen_reply(buf+size, ct); - h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]); - if (h && h->print_proto) - size += h->print_proto(buf+size, &ct->tuple[NFCT_DIR_REPLY]); + size += nfct_sprintf_address(buf+size, ct, NFCT_DIR_REPLY); + size += nfct_sprintf_proto(buf+size, ct, NFCT_DIR_REPLY); if (flags & NFCT_COUNTERS_RPLY) - size += sprintf(buf+size, "packets=%llu bytes=%llu ", - ct->counters[NFCT_DIR_REPLY].packets, - ct->counters[NFCT_DIR_REPLY].bytes); + size += nfct_sprintf_counters(buf+size, ct, NFCT_DIR_REPLY); if (flags & NFCT_STATUS) - size += print_status(buf+size, ct->status); + size += nfct_sprintf_status_assured(buf+size, ct); if (flags & NFCT_MARK) - size += sprintf(buf+size, "mark=%lu ", ct->mark); + size += nfct_sprintf_mark(buf+size, ct); + if (flags & NFCT_USE) - size += sprintf(buf+size, "use=%u ", ct->use); + size += nfct_sprintf_use(buf+size, ct); + + return size; +} + +int nfct_sprintf_conntrack_id(char *buf, struct nfct_conntrack *ct, + unsigned int flags) +{ + int size; + + size = nfct_sprintf_conntrack(buf, ct, flags); if (flags & NFCT_ID) - size += sprintf(buf+size, "id=%u ", ct->id); + size += nfct_sprintf_id(buf+size, ct); + return size; +} + +int nfct_default_conntrack_display(void *arg, unsigned int flags, int type) +{ + char buf[512]; + int size; + + size = nfct_sprintf_conntrack(buf, arg, flags); + sprintf(buf+size, "\n"); + fprintf(stdout, buf); + + return 0; +} + +int nfct_default_conntrack_display_id(void *arg, unsigned int flags, int type) +{ + char buf[512]; + int size; + + size = nfct_sprintf_conntrack_id(buf, arg, flags); sprintf(buf+size, "\n"); fprintf(stdout, buf); @@ -651,7 +741,6 @@ int nfct_create_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) { struct nfnlhdr *req; char buf[NFCT_BUFSIZE]; - int err; req = (void *) buf; @@ -662,11 +751,7 @@ int nfct_create_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) nfct_build_conntrack(req, sizeof(buf), ct); - err = nfnl_send(&cth->nfnlh, &req->nlh); - if (err < 0) - return err; - - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_talk(&cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL); } int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) @@ -679,7 +764,7 @@ int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) memset(&buf, 0, sizeof(buf)); nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, AF_INET, 0, IPCTNL_MSG_CT_NEW, - NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK); + NLM_F_REQUEST|NLM_F_ACK); nfct_build_conntrack(req, sizeof(buf), ct); @@ -693,7 +778,6 @@ int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, int dir, unsigned int id) { - int err; struct nfnlhdr *req; char buf[NFCT_BUFSIZE]; int type = dir ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG; @@ -711,11 +795,7 @@ int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id, sizeof(unsigned int)); - err = nfnl_send(&cth->nfnlh, &req->nlh); - if (err < 0) - return err; - - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_talk(&cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL); } int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, @@ -752,7 +832,8 @@ static int __nfct_dump_conntrack_table(struct nfct_handle *cth, int zero) { int err, msg; struct nfnlhdr req; - + + memset(&req, 0, sizeof(req)); cth->handler = nfct_conntrack_netlink_handler; if (zero) @@ -796,16 +877,13 @@ void nfct_register_proto(struct nfct_proto *h) list_add(&h->head, &proto_list); } -void nfct_unregister_proto(struct nfct_proto *h) -{ - list_del(&h->head); -} - int nfct_dump_expect_list(struct nfct_handle *cth) { int err; struct nfnlhdr req; + memset(&req, 0, sizeof(req)); + cth->handler = nfct_expect_netlink_handler; nfnl_fill_hdr(&cth->nfnlh, &req.nlh, 0, AF_INET, 0, IPCTNL_MSG_EXP_GET, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST); @@ -819,22 +897,15 @@ int nfct_dump_expect_list(struct nfct_handle *cth) int nfct_flush_conntrack_table(struct nfct_handle *cth) { - int err; - struct nfnlhdr *req; - char buf[sizeof(*req)]; + struct nfnlhdr req; - memset(&buf, 0, sizeof(buf)); - req = (void *) &buf; + memset(&req, 0, sizeof(req)); - nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &buf, + nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &req, 0, AF_INET, 0, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK); - err = nfnl_send(&cth->nfnlh, (struct nlmsghdr *)&buf); - if (err < 0) - return err; - - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_talk(&cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL); } int nfct_get_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple, @@ -952,20 +1023,13 @@ int nfct_event_expectation(struct nfct_handle *cth) int nfct_flush_expectation_table(struct nfct_handle *cth) { - int err; - struct nfnlhdr *req; - char buf[sizeof(*req)]; + struct nfnlhdr req; - memset(&buf, 0, sizeof(buf)); - req = (void *) &buf; + memset(&req, 0, sizeof(req)); - nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &buf, + nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &req, 0, AF_INET, 0, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK); - err = nfnl_send(&cth->nfnlh, (struct nlmsghdr *)&buf); - if (err < 0) - return err; - - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_talk(&cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL); } diff --git a/utils/ctnl_test.c b/utils/ctnl_test.c index fccadbe..360e118 100644 --- a/utils/ctnl_test.c +++ b/utils/ctnl_test.c @@ -90,7 +90,7 @@ int main(int argc, char **argv) if (ret < 0 && ret != -EEXIST) errors++; - nfct_set_callback(cth, nfct_default_conntrack_display); + nfct_register_callback(cth, nfct_default_conntrack_display); ret = nfct_dump_conntrack_table_reset_counters(cth); fprintf(stdout, "TEST 2: dump conntrack table and reset (%d)\n", ret); if (ret < 0) @@ -120,7 +120,7 @@ int main(int argc, char **argv) fprintf(stdout, "TEST 7: Waiting for 10 conntrack events\n"); signal(SIGINT, event_sighandler); - nfct_set_callback(cth, event_counter); + nfct_register_callback(cth, event_counter); ret = nfct_event_conntrack(cth); fprintf(stdout, "TEST 7: Received 10 conntrack events (%d)\n", ret); -- cgit v1.2.3