Index: src/libnetfilter_conntrack.c =================================================================== --- src/libnetfilter_conntrack.c (revision 4398) +++ src/libnetfilter_conntrack.c (working copy) @@ -431,66 +431,71 @@ 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));