summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/libnetfilter_conntrack_icmp.c22
-rw-r--r--extensions/libnetfilter_conntrack_sctp.c22
-rw-r--r--extensions/libnetfilter_conntrack_tcp.c34
-rw-r--r--extensions/libnetfilter_conntrack_udp.c18
-rw-r--r--include/libnetfilter_conntrack/libnetfilter_conntrack.h2
-rw-r--r--include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h2
-rw-r--r--src/libnetfilter_conntrack.c213
7 files changed, 176 insertions, 137 deletions
diff --git a/extensions/libnetfilter_conntrack_icmp.c b/extensions/libnetfilter_conntrack_icmp.c
index 747fedf..07997d1 100644
--- a/extensions/libnetfilter_conntrack_icmp.c
+++ b/extensions/libnetfilter_conntrack_icmp.c
@@ -16,7 +16,7 @@
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack_extensions.h>
-void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
+static void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
{
if (cda[CTA_PROTO_ICMP_TYPE-1])
tuple->l4dst.icmp.type =
@@ -31,7 +31,20 @@ void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
*(u_int16_t *)NFA_DATA(cda[CTA_PROTO_ICMP_ID-1]);
}
-int print_proto(char *buf, struct nfct_tuple *t)
+static void build_tuple_proto(struct nfnlhdr *req, int size,
+ struct nfct_tuple *t)
+{
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_CODE,
+ &t->l4dst.icmp.code, sizeof(u_int8_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_TYPE,
+ &t->l4dst.icmp.type, sizeof(u_int8_t));
+ /* This is an ICMP echo */
+ if (t->l4dst.icmp.type == 8)
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_ID,
+ &t->l4src.icmp.id, sizeof(u_int16_t));
+}
+
+static int print_proto(char *buf, struct nfct_tuple *t)
{
int size = 0;
@@ -48,13 +61,14 @@ static struct nfct_proto icmp = {
.name = "icmp",
.protonum = IPPROTO_ICMP,
.parse_proto = parse_proto,
+ .build_tuple_proto = build_tuple_proto,
.print_proto = print_proto,
.version = LIBNETFILTER_CONNTRACK_VERSION
};
-void __attribute__ ((constructor)) init(void);
+static void __attribute__ ((constructor)) init(void);
-void init(void)
+static void init(void)
{
nfct_register_proto(&icmp);
}
diff --git a/extensions/libnetfilter_conntrack_sctp.c b/extensions/libnetfilter_conntrack_sctp.c
index f533287..564d641 100644
--- a/extensions/libnetfilter_conntrack_sctp.c
+++ b/extensions/libnetfilter_conntrack_sctp.c
@@ -16,7 +16,7 @@
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack_extensions.h>
-void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
+static void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
{
if (cda[CTA_PROTO_SRC_PORT-1])
tuple->l4src.sctp.port =
@@ -26,7 +26,7 @@ void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
*(u_int16_t *)NFA_DATA(cda[CTA_PROTO_DST_PORT-1]);
}
-void parse_protoinfo(struct nfattr *cda[], struct nfct_conntrack *ct)
+static void parse_protoinfo(struct nfattr *cda[], struct nfct_conntrack *ct)
{
/* if (cda[CTA_PROTOINFO_SCTP_STATE-1])
ct->protoinfo.sctp.state =
@@ -34,13 +34,22 @@ void parse_protoinfo(struct nfattr *cda[], struct nfct_conntrack *ct)
*/
}
-int print_protoinfo(char *buf, union nfct_protoinfo *protoinfo)
+static void build_tuple_proto(struct nfnlhdr *req, int size,
+ struct nfct_tuple *t)
+{
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
+ &t->l4src.tcp.port, sizeof(u_int16_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
+ &t->l4dst.tcp.port, sizeof(u_int16_t));
+}
+
+static int print_protoinfo(char *buf, union nfct_protoinfo *protoinfo)
{
/* fprintf(stdout, "%s ", states[protoinfo->sctp.state]); */
return 0;
}
-int print_proto(char *buf, struct nfct_tuple *tuple)
+static int print_proto(char *buf, struct nfct_tuple *tuple)
{
return(sprintf(buf, "sport=%u dport=%u ", htons(tuple->l4src.sctp.port),
htons(tuple->l4dst.sctp.port)));
@@ -51,14 +60,15 @@ static struct nfct_proto sctp = {
.protonum = IPPROTO_SCTP,
.parse_proto = parse_proto,
.parse_protoinfo = parse_protoinfo,
+ .build_tuple_proto = build_tuple_proto,
.print_proto = print_proto,
.print_protoinfo = print_protoinfo,
.version = LIBNETFILTER_CONNTRACK_VERSION
};
-void __attribute__ ((constructor)) init(void);
+static void __attribute__ ((constructor)) init(void);
-void init(void)
+static void init(void)
{
nfct_register_proto(&sctp);
}
diff --git a/extensions/libnetfilter_conntrack_tcp.c b/extensions/libnetfilter_conntrack_tcp.c
index ecb988f..32a0971 100644
--- a/extensions/libnetfilter_conntrack_tcp.c
+++ b/extensions/libnetfilter_conntrack_tcp.c
@@ -29,7 +29,7 @@ static const char *states[] = {
"LISTEN"
};
-void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
+static void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
{
if (cda[CTA_PROTO_SRC_PORT-1])
tuple->l4src.tcp.port =
@@ -39,7 +39,7 @@ void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
*(u_int16_t *)NFA_DATA(cda[CTA_PROTO_DST_PORT-1]);
}
-void parse_protoinfo(struct nfattr *cda[], struct nfct_conntrack *ct)
+static void parse_protoinfo(struct nfattr *cda[], struct nfct_conntrack *ct)
{
struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
@@ -50,12 +50,32 @@ void parse_protoinfo(struct nfattr *cda[], struct nfct_conntrack *ct)
*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
}
-int print_protoinfo(char *buf, union nfct_protoinfo *protoinfo)
+static void build_tuple_proto(struct nfnlhdr *req, int size,
+ struct nfct_tuple *t)
+{
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
+ &t->l4src.tcp.port, sizeof(u_int16_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
+ &t->l4dst.tcp.port, sizeof(u_int16_t));
+}
+
+static void build_protoinfo(struct nfnlhdr *req, int size,
+ struct nfct_conntrack *ct)
+{
+ struct nfattr *nest_proto;
+
+ nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP);
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTOINFO_TCP_STATE,
+ &ct->protoinfo.tcp.state, sizeof(u_int8_t));
+ nfnl_nest_end(&req->nlh, nest_proto);
+}
+
+static int print_protoinfo(char *buf, union nfct_protoinfo *protoinfo)
{
return(sprintf(buf, "%s ", states[protoinfo->tcp.state]));
}
-int print_proto(char *buf, struct nfct_tuple *tuple)
+static int print_proto(char *buf, struct nfct_tuple *tuple)
{
return(sprintf(buf, "sport=%u dport=%u ", htons(tuple->l4src.tcp.port),
htons(tuple->l4dst.tcp.port)));
@@ -66,14 +86,16 @@ static struct nfct_proto tcp = {
.protonum = IPPROTO_TCP,
.parse_protoinfo = parse_protoinfo,
.parse_proto = parse_proto,
+ .build_tuple_proto = build_tuple_proto,
+ .build_protoinfo = build_protoinfo,
.print_protoinfo = print_protoinfo,
.print_proto = print_proto,
.version = LIBNETFILTER_CONNTRACK_VERSION
};
-void __attribute__ ((constructor)) init(void);
+static void __attribute__ ((constructor)) init(void);
-void init(void)
+static void init(void)
{
nfct_register_proto(&tcp);
}
diff --git a/extensions/libnetfilter_conntrack_udp.c b/extensions/libnetfilter_conntrack_udp.c
index 44fd85c..2fe3da2 100644
--- a/extensions/libnetfilter_conntrack_udp.c
+++ b/extensions/libnetfilter_conntrack_udp.c
@@ -16,7 +16,7 @@
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack_extensions.h>
-void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
+static void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
{
if (cda[CTA_PROTO_SRC_PORT-1])
tuple->l4src.udp.port =
@@ -26,23 +26,33 @@ void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple)
*(u_int16_t *)NFA_DATA(cda[CTA_PROTO_DST_PORT-1]);
}
-int print_proto(char *buf, struct nfct_tuple *tuple)
+static int print_proto(char *buf, struct nfct_tuple *tuple)
{
return (sprintf(buf, "sport=%u dport=%u ", htons(tuple->l4src.udp.port),
htons(tuple->l4dst.udp.port)));
}
+static void build_tuple_proto(struct nfnlhdr *req, int size,
+ struct nfct_tuple *t)
+{
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
+ &t->l4src.tcp.port, sizeof(u_int16_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
+ &t->l4dst.tcp.port, sizeof(u_int16_t));
+}
+
static struct nfct_proto udp = {
.name = "udp",
.protonum = IPPROTO_UDP,
+ .build_tuple_proto = build_tuple_proto,
.parse_proto = parse_proto,
.print_proto = print_proto,
.version = LIBNETFILTER_CONNTRACK_VERSION,
};
-void __attribute__ ((constructor)) init(void);
+static void __attribute__ ((constructor)) init(void);
-void init(void)
+static void init(void)
{
nfct_register_proto(&udp);
}
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index 6d28b97..18d5b53 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -13,7 +13,7 @@
#include <linux/netfilter/nfnetlink_conntrack.h>
#include <libnfnetlink/libnfnetlink.h>
-#define LIBNETFILTER_CONNTRACK_VERSION "0.2.0"
+#define LIBNETFILTER_CONNTRACK_VERSION "0.2.1"
enum {
CONNTRACK = NFNL_SUBSYS_CTNETLINK,
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h b/include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h
index 4900541..3cb8efa 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h
@@ -19,6 +19,8 @@ struct nfct_proto {
void (*parse_proto)(struct nfattr **, struct nfct_tuple *);
void (*parse_protoinfo)(struct nfattr **, struct nfct_conntrack *);
+ void (*build_tuple_proto)(struct nfnlhdr *, int, struct nfct_tuple *);
+ void (*build_protoinfo)(struct nfnlhdr *, int, struct nfct_conntrack *);
int (*print_protoinfo)(char *, union nfct_protoinfo *);
int (*print_proto)(char *, struct nfct_tuple *);
};
diff --git a/src/libnetfilter_conntrack.c b/src/libnetfilter_conntrack.c
index 6204df9..330761f 100644
--- a/src/libnetfilter_conntrack.c
+++ b/src/libnetfilter_conntrack.c
@@ -42,6 +42,7 @@ static char *proto2str[IPPROTO_MAX] = {
[IPPROTO_ICMP] = "icmp",
[IPPROTO_SCTP] = "sctp"
};
+static struct nfct_proto *findproto(char *name);
/* handler used for nfnl_listen */
static int callback_handler(struct sockaddr_nl *nladdr,
@@ -139,6 +140,7 @@ static void nfct_build_tuple_ip(struct nfnlhdr *req, int size,
static void nfct_build_tuple_proto(struct nfnlhdr *req, int size,
struct nfct_tuple *t)
{
+ struct nfct_proto *h;
struct nfattr *nest;
nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_PROTO);
@@ -146,26 +148,11 @@ static void nfct_build_tuple_proto(struct nfnlhdr *req, int size,
nfnl_addattr_l(&req->nlh, size, CTA_PROTO_NUM, &t->protonum,
sizeof(u_int16_t));
- switch(t->protonum) {
- case IPPROTO_TCP:
- case IPPROTO_UDP:
- case IPPROTO_SCTP:
- nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
- &t->l4src.tcp.port, sizeof(u_int16_t));
- nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
- &t->l4dst.tcp.port, sizeof(u_int16_t));
- break;
- case IPPROTO_ICMP:
- nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_CODE,
- &t->l4dst.icmp.code, sizeof(u_int8_t));
- nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_TYPE,
- &t->l4dst.icmp.type, sizeof(u_int8_t));
- /* This is an ICMP echo */
- if (t->l4dst.icmp.type == 8)
- nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_ID,
- &t->l4src.icmp.id, sizeof(u_int16_t));
- break;
- }
+ h = findproto(proto2str[t->protonum]);
+
+ if (h && h->build_tuple_proto)
+ h->build_tuple_proto(req, size, t);
+
nfnl_nest_end(&req->nlh, nest);
}
@@ -186,23 +173,14 @@ static void nfct_build_protoinfo(struct nfnlhdr *req, int size,
struct nfct_conntrack *ct)
{
struct nfattr *nest;
+ struct nfct_proto *h;
- nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
-
- switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
- case IPPROTO_TCP: {
- struct nfattr *nest_proto;
- nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP);
- nfnl_addattr_l(&req->nlh, size, CTA_PROTOINFO_TCP_STATE,
- &ct->protoinfo.tcp.state, sizeof(u_int8_t));
- nfnl_nest_end(&req->nlh, nest_proto);
- break;
- }
- default:
- break;
+ h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]);
+ if (h && h->build_protoinfo) {
+ nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
+ h->build_protoinfo(req, size, ct);
+ nfnl_nest_end(&req->nlh, nest);
}
-
- nfnl_nest_end(&req->nlh, nest);
}
static void nfct_build_protonat(struct nfnlhdr *req, int size,
@@ -431,66 +409,71 @@ static int typemsg2enum(u_int8_t type, u_int8_t flags)
static int nfct_conntrack_netlink_handler(struct nfct_handle *cth,
struct nlmsghdr *nlh, void *arg)
{
- struct nfgenmsg *nfmsg;
- struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
- int attrlen = NLMSG_LENGTH(nlh->nlmsg_len) - NFNL_HEADER_LEN;
struct nfct_conntrack ct;
unsigned int flags = 0;
+ struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
int type = NFNL_MSG_TYPE(nlh->nlmsg_type), ret = 0;
+ int len = nlh->nlmsg_len;
+ struct nfattr *cda[CTA_MAX];
+
+ len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
+ if (len < 0)
+ return -EINVAL;
memset(&ct, 0, sizeof(struct nfct_conntrack));
- nfmsg = NLMSG_DATA(nlh);
+ nfnl_parse_attr(cda, CTA_MAX, NFA_DATA(nfhdr), len);
- if (NLMSG_LENGTH(nlh->nlmsg_len) < NFNL_HEADER_LEN)
- return -EINVAL;
+ if (cda[CTA_TUPLE_ORIG-1])
+ parse_tuple(cda[CTA_TUPLE_ORIG-1],
+ &ct.tuple[NFCT_DIR_ORIGINAL]);
+
+ if (cda[CTA_TUPLE_REPLY-1])
+ parse_tuple(cda[CTA_TUPLE_REPLY-1],
+ &ct.tuple[NFCT_DIR_REPLY]);
+
+ if (cda[CTA_STATUS-1]) {
+ ct.status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
+ flags |= NFCT_STATUS;
+ }
- while (NFA_OK(attr, attrlen)) {
- switch(NFA_TYPE(attr)) {
- case CTA_TUPLE_ORIG:
- parse_tuple(attr, &ct.tuple[NFCT_DIR_ORIGINAL]);
- break;
- case CTA_TUPLE_REPLY:
- parse_tuple(attr, &ct.tuple[NFCT_DIR_REPLY]);
- break;
- case CTA_STATUS:
- ct.status = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= NFCT_STATUS;
- break;
- case CTA_PROTOINFO:
- parse_protoinfo(attr, &ct);
- flags |= NFCT_PROTOINFO;
- break;
- case CTA_TIMEOUT:
- ct.timeout = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= NFCT_TIMEOUT;
- break;
- case CTA_MARK:
- ct.mark = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= NFCT_MARK;
- break;
- case CTA_COUNTERS_ORIG:
- nfct_parse_counters(attr, &ct, NFA_TYPE(attr)-1);
- flags |= NFCT_COUNTERS_ORIG;
- break;
- case CTA_COUNTERS_REPLY:
- nfct_parse_counters(attr, &ct, NFA_TYPE(attr)-1);
- flags |= NFCT_COUNTERS_RPLY;
- break;
- case CTA_USE:
- ct.use = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= NFCT_USE;
- break;
- case CTA_ID:
- ct.id = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= NFCT_ID;
- break;
- default:
- fprintf(stderr, "Unknown Attribute %d\n", NFA_TYPE(attr));
- break;
- }
- attr = NFA_NEXT(attr, attrlen);
+ if (cda[CTA_PROTOINFO-1]) {
+ parse_protoinfo(cda[CTA_PROTOINFO-1], &ct);
+ flags |= NFCT_PROTOINFO;
+ }
+
+ if (cda[CTA_TIMEOUT-1]) {
+ ct.timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+ flags |= NFCT_TIMEOUT;
+ }
+
+ if (cda[CTA_MARK-1]) {
+ ct.mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+ flags |= NFCT_MARK;
+ }
+
+ if (cda[CTA_COUNTERS_ORIG-1]) {
+ nfct_parse_counters(cda[CTA_COUNTERS_ORIG-1], &ct,
+ NFA_TYPE(cda[CTA_COUNTERS_ORIG-1])-1);
+ flags |= NFCT_COUNTERS_ORIG;
+ }
+
+ if (cda[CTA_COUNTERS_REPLY-1]) {
+ nfct_parse_counters(cda[CTA_COUNTERS_REPLY-1], &ct,
+ NFA_TYPE(cda[CTA_COUNTERS_REPLY-1])-1);
+ flags |= NFCT_COUNTERS_RPLY;
+ }
+
+ if (cda[CTA_USE-1]) {
+ ct.use = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_USE-1]));
+ flags |= NFCT_USE;
+ }
+
+ if (cda[CTA_ID-1]) {
+ ct.id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
+ flags |= NFCT_ID;
}
+
if (cth->callback)
ret = cth->callback((void *) &ct, flags,
typemsg2enum(type, nlh->nlmsg_flags));
@@ -645,16 +628,19 @@ int nfct_default_expect_display(void *arg, unsigned int flags, int type)
struct nfct_expect *exp = arg;
char buf[256];
int size = 0;
-
+ struct nfct_proto *h = NULL;
+
size += sprintf(buf, "%ld proto=%d ", exp->timeout, exp->tuple.protonum);
size += sprintf(buf+size, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
NIPQUAD(exp->tuple.src.v4),
NIPQUAD(exp->tuple.dst.v4));
- size += sprintf(buf+size, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
- NIPQUAD(exp->mask.src.v4),
- NIPQUAD(exp->mask.dst.v4));
+
+ h = findproto(proto2str[exp->tuple.protonum]);
+ if (h && h->print_proto)
+ size += h->print_proto(buf+size, &exp->tuple);
+
size += sprintf(buf+size, "id=%u ", exp->id);
- size += sprintf(buf, "\n");
+ size += sprintf(buf+size, "\n");
fprintf(stdout, buf);
return 0;
@@ -672,38 +658,33 @@ static int nfct_event_netlink_handler(struct nfct_handle *cth,
static int nfct_expect_netlink_handler(struct nfct_handle *cth,
struct nlmsghdr *nlh, void *arg)
{
- struct nfgenmsg *nfmsg;
- struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
- int attrlen = NLMSG_LENGTH(nlh->nlmsg_len) - NFNL_HEADER_LEN;
+ struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
struct nfct_expect exp;
int type = NFNL_MSG_TYPE(nlh->nlmsg_type), ret = 0;
+ int len = nlh->nlmsg_len;
+ struct nfattr *cda[CTA_EXPECT_MAX];
+ len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
+ if (len < 0)
+ return -EINVAL;
+
memset(&exp, 0, sizeof(struct nfct_expect));
- nfmsg = NLMSG_DATA(nlh);
+ nfnl_parse_attr(cda, CTA_EXPECT_MAX, NFA_DATA(nfhdr), len);
- if (NLMSG_LENGTH(nlh->nlmsg_len) < NFNL_HEADER_LEN)
- return -EINVAL;
+ if (cda[CTA_EXPECT_TUPLE-1])
+ parse_tuple(cda[CTA_EXPECT_TUPLE-1], &exp.tuple);
+
+ if (cda[CTA_EXPECT_MASK-1])
+ parse_tuple(cda[CTA_EXPECT_MASK-1], &exp.mask);
+
+ if (cda[CTA_EXPECT_TIMEOUT-1])
+ exp.timeout = htonl(*(unsigned long *)
+ NFA_DATA(cda[CTA_EXPECT_TIMEOUT-1]));
+
+ if (cda[CTA_EXPECT_ID-1])
+ exp.id = htonl(*(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]));
- while (NFA_OK(attr, attrlen)) {
- switch(NFA_TYPE(attr)) {
-
- case CTA_EXPECT_TUPLE:
- parse_tuple(attr, &exp.tuple);
- break;
- case CTA_EXPECT_MASK:
- parse_tuple(attr, &exp.mask);
- break;
- case CTA_EXPECT_TIMEOUT:
- exp.timeout = htonl(*(unsigned long *)
- NFA_DATA(attr));
- break;
- case CTA_EXPECT_ID:
- exp.id = htonl(*(u_int32_t *)NFA_DATA(attr));
- break;
- }
- attr = NFA_NEXT(attr, attrlen);
- }
if (cth->callback)
ret = cth->callback((void *)&exp, 0,
typemsg2enum(type, nlh->nlmsg_flags));