summaryrefslogtreecommitdiffstats
path: root/src/libnetfilter_conntrack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnetfilter_conntrack.c')
-rw-r--r--src/libnetfilter_conntrack.c168
1 files changed, 109 insertions, 59 deletions
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);
}