From a191125716fc49f6c9a7d6fa122318e80661aad7 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Sat, 14 Jan 2006 19:04:51 +0000 Subject: Introduce various API changes throughout the library stack 1) make libnfnetlink dynamically allocate it's handles 2) apply that change throughout libnetfilter_* 3) add {nfq,nflog,nfct}_open_nfnl() functions that open the specific subsystem on top of an existing nfnl_handle, which is required for upcoming libnetfilter_conntrack_helper The changes break ABI and API compatibility of libnfnetlink, but don't break ABI or API compatibility of the libnetfilter_* libraries. --- src/libnetfilter_conntrack.c | 168 ++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/libnetfilter_conntrack.c b/src/libnetfilter_conntrack.c index 0c7ba8a..4a72592 100644 --- a/src/libnetfilter_conntrack.c +++ b/src/libnetfilter_conntrack.c @@ -29,7 +29,9 @@ typedef int (*nfct_handler)(struct nfct_handle *cth, struct nlmsghdr *nlh, /* Harald says: "better for encapsulation" ;) */ struct nfct_handle { - struct nfnl_handle nfnlh; + struct nfnl_handle *nfnlh; + struct nfnl_subsys_handle *nfnlssh_ct; + struct nfnl_subsys_handle *nfnlssh_exp; nfct_callback callback; /* user callback */ void *callback_data; /* user data for callback */ nfct_handler handler; /* netlink handler */ @@ -75,44 +77,81 @@ static int callback_handler(struct sockaddr_nl *nladdr, return ret; } -struct nfct_handle *nfct_open(u_int8_t subsys_id, unsigned subscriptions) +struct nfct_handle *nfct_open_nfnl(struct nfnl_handle *nfnlh, + u_int8_t subsys_id, + unsigned int subscriptions) { - int err; - u_int8_t cb_count; struct nfct_handle *cth; - switch(subsys_id) { - case NFNL_SUBSYS_CTNETLINK: - cb_count = IPCTNL_MSG_MAX; - break; - case NFNL_SUBSYS_CTNETLINK_EXP: - cb_count = IPCTNL_MSG_EXP_MAX; - break; - default: - return NULL; - break; - } - cth = (struct nfct_handle *) - malloc(sizeof(struct nfct_handle)); + cth = (struct nfct_handle *) malloc(sizeof(struct nfct_handle)); if (!cth) return NULL; memset(cth, 0, sizeof(*cth)); + cth->nfnlh = nfnlh; + + if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK) { + cth->nfnlssh_ct = nfnl_subsys_open(cth->nfnlh, + NFNL_SUBSYS_CTNETLINK, + IPCTNL_MSG_MAX, + subscriptions); + if (!cth->nfnlssh_ct) + goto out_free; + } - err = nfnl_open(&cth->nfnlh, subsys_id, cb_count, subscriptions); - if (err < 0) { - free(cth); - return NULL; + if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK_EXP) { + cth->nfnlssh_exp = nfnl_subsys_open(cth->nfnlh, + NFNL_SUBSYS_CTNETLINK_EXP, + IPCTNL_MSG_EXP_MAX, + subscriptions); + if (!cth->nfnlssh_exp) + goto out_free; } return cth; + +out_free: + if (cth->nfnlssh_exp) { + nfnl_subsys_close(cth->nfnlssh_exp); + cth->nfnlssh_exp = NULL; + } + if (cth->nfnlssh_ct) { + nfnl_subsys_close(cth->nfnlssh_ct); + cth->nfnlssh_ct = NULL; + } + free(cth); + return NULL; +} + +struct nfct_handle *nfct_open(u_int8_t subsys_id, unsigned subscriptions) +{ + struct nfnl_handle *nfnlh = nfnl_open(); + struct nfct_handle *nfcth; + + if (!nfnlh) + return NULL; + + nfcth = nfct_open_nfnl(nfnlh, subsys_id, subscriptions); + if (!nfcth) + nfnl_close(nfnlh); + + return nfcth; } int nfct_close(struct nfct_handle *cth) { int err; - err = nfnl_close(&cth->nfnlh); + if (cth->nfnlssh_exp) { + nfnl_subsys_close(cth->nfnlssh_exp); + cth->nfnlssh_exp = NULL; + } + if (cth->nfnlssh_ct) { + nfnl_subsys_close(cth->nfnlssh_ct); + cth->nfnlssh_ct = NULL; + } + + err = nfnl_close(cth->nfnlh); free(cth); return err; @@ -120,7 +159,7 @@ int nfct_close(struct nfct_handle *cth) int nfct_fd(struct nfct_handle *cth) { - return nfnl_fd(&cth->nfnlh); + return nfnl_fd(cth->nfnlh); } void nfct_register_callback(struct nfct_handle *cth, nfct_callback callback, @@ -889,7 +928,8 @@ int nfct_create_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) memset(buf, 0, sizeof(buf)); - nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_CT_NEW, + nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, + IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL); nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_ORIGINAL], @@ -911,7 +951,7 @@ int nfct_create_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) if (ct->nat.min_ip != 0) nfct_build_nat(req, sizeof(buf), ct); - return nfnl_talk(&cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL); + return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL); } int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) @@ -928,8 +968,8 @@ int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) req = (void *) &buf; memset(&buf, 0, sizeof(buf)); - nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_CT_NEW, - NLM_F_REQUEST|NLM_F_ACK); + nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, + IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK); nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_ORIGINAL], CTA_TUPLE_ORIG); @@ -954,11 +994,11 @@ int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct) nfct_build_protoinfo(req, sizeof(buf), ct); - err = nfnl_send(&cth->nfnlh, &req->nlh); + err = nfnl_send(cth->nfnlh, &req->nlh); if (err < 0) return err; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, @@ -972,7 +1012,7 @@ int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, req = (void *) &buf; memset(&buf, 0, sizeof(buf)); - nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, + nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, IPCTNL_MSG_CT_DELETE, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK); @@ -984,7 +1024,7 @@ int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, sizeof(u_int32_t)); } - return nfnl_talk(&cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL); + return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL); } int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, @@ -1001,7 +1041,7 @@ int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, memset(&buf, 0, sizeof(buf)); req = (void *) &buf; - nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, + nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_ACK); @@ -1013,11 +1053,11 @@ int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, sizeof(u_int32_t)); } - err = nfnl_send(&cth->nfnlh, &req->nlh); + err = nfnl_send(cth->nfnlh, &req->nlh); if (err < 0) return err; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } static int __nfct_dump_conntrack_table(struct nfct_handle *cth, int zero, @@ -1034,14 +1074,14 @@ static int __nfct_dump_conntrack_table(struct nfct_handle *cth, int zero, else msg = IPCTNL_MSG_CT_GET; - nfnl_fill_hdr(&cth->nfnlh, &req.nlh, 0, family, 0, + nfnl_fill_hdr(cth->nfnlssh_ct, &req.nlh, 0, family, 0, msg, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_DUMP); - err = nfnl_send(&cth->nfnlh, &req.nlh); + err = nfnl_send(cth->nfnlh, &req.nlh); if (err < 0) return err; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } int nfct_dump_conntrack_table(struct nfct_handle *cth, int family) @@ -1064,7 +1104,7 @@ int nfct_event_conntrack(struct nfct_handle *cth) return -EPERM; cth->handler = nfct_conntrack_netlink_handler; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } void nfct_register_proto(struct nfct_proto *h) @@ -1095,14 +1135,14 @@ int nfct_dump_expect_list(struct nfct_handle *cth, int family) memset(&req, 0, sizeof(req)); cth->handler = nfct_expect_netlink_handler; - nfnl_fill_hdr(&cth->nfnlh, &req.nlh, 0, family, 0, + nfnl_fill_hdr(cth->nfnlssh_exp, &req.nlh, 0, family, 0, IPCTNL_MSG_EXP_GET, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST); - err = nfnl_send(&cth->nfnlh, &req.nlh); + err = nfnl_send(cth->nfnlh, &req.nlh); if (err < 0) return err; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } int nfct_flush_conntrack_table(struct nfct_handle *cth, int family) @@ -1111,11 +1151,11 @@ int nfct_flush_conntrack_table(struct nfct_handle *cth, int family) memset(&req, 0, sizeof(req)); - nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &req, + nfnl_fill_hdr(cth->nfnlssh_ct, (struct nlmsghdr *) &req, 0, family, 0, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK); - return nfnl_talk(&cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL); + return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL); } int nfct_get_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple, @@ -1129,7 +1169,8 @@ int nfct_get_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple, memset(&buf, 0, sizeof(buf)); req = (void *) &buf; - nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_EXP_GET, + nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 0, + IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_ACK); cth->handler = nfct_expect_netlink_handler; @@ -1139,11 +1180,11 @@ int nfct_get_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple, nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id, sizeof(u_int32_t)); - err = nfnl_send(&cth->nfnlh, &req->nlh); + err = nfnl_send(cth->nfnlh, &req->nlh); if (err < 0) return err; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } struct nfct_expect * @@ -1161,7 +1202,7 @@ nfct_expect_alloc(struct nfct_tuple *master, struct nfct_tuple *tuple, exp->master = *master; exp->tuple = *tuple; exp->mask = *mask; - exp->timeout = htonl(timeout); + exp->timeout = timeout; if (id != NFCT_ANY_ID) exp->id = htonl(id); @@ -1180,27 +1221,36 @@ int nfct_create_expectation(struct nfct_handle *cth, struct nfct_expect *exp) char buf[NFCT_BUFSIZE]; req = (void *) &buf; u_int8_t l3num = exp->tuple.l3protonum; + u_int32_t timeout; + u_int16_t queuenr; memset(&buf, 0, sizeof(buf)); - nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_EXP_NEW, + nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 0, + IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK); nfct_build_tuple(req, sizeof(buf), &exp->master, CTA_EXPECT_MASTER); nfct_build_tuple(req, sizeof(buf), &exp->tuple, CTA_EXPECT_TUPLE); nfct_build_tuple(req, sizeof(buf), &exp->mask, CTA_EXPECT_MASK); + timeout = htonl(exp->timeout); nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_TIMEOUT, - &exp->timeout, sizeof(u_int32_t)); - - err = nfnl_send(&cth->nfnlh, &req->nlh); + &timeout, sizeof(u_int32_t)); + + queuenr = htons(exp->expectfn_queue_id); + if (queuenr) + nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_QUEUENR, + &queuenr, sizeof(u_int16_t)); + + err = nfnl_send(cth->nfnlh, &req->nlh); if (err < 0) return err; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } -int nfct_delete_expectation(struct nfct_handle *cth,struct nfct_tuple *tuple, +int nfct_delete_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple, u_int32_t id) { int err; @@ -1211,7 +1261,7 @@ int nfct_delete_expectation(struct nfct_handle *cth,struct nfct_tuple *tuple, memset(&buf, 0, sizeof(buf)); req = (void *) &buf; - nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, + nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 0, IPCTNL_MSG_EXP_DELETE, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK); @@ -1221,11 +1271,11 @@ int nfct_delete_expectation(struct nfct_handle *cth,struct nfct_tuple *tuple, nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id, sizeof(u_int32_t)); - err = nfnl_send(&cth->nfnlh, &req->nlh); + err = nfnl_send(cth->nfnlh, &req->nlh); if (err < 0) return err; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } int nfct_event_expectation(struct nfct_handle *cth) @@ -1237,7 +1287,7 @@ int nfct_event_expectation(struct nfct_handle *cth) return -EPERM; cth->handler = nfct_expect_netlink_handler; - return nfnl_listen(&cth->nfnlh, &callback_handler, cth); + return nfnl_listen(cth->nfnlh, &callback_handler, cth); } int nfct_flush_expectation_table(struct nfct_handle *cth, int family) @@ -1246,9 +1296,9 @@ int nfct_flush_expectation_table(struct nfct_handle *cth, int family) memset(&req, 0, sizeof(req)); - nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &req, + nfnl_fill_hdr(cth->nfnlssh_exp, (struct nlmsghdr *) &req, 0, family, 0, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK); - return nfnl_talk(&cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL); + return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL); } -- cgit v1.2.3