diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 4f2e50952a12..73ab16bc7d40 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -400,6 +400,8 @@ static int ctnetlink_done(struct netlink_callback *cb) | |||
400 | return 0; | 400 | return 0; |
401 | } | 401 | } |
402 | 402 | ||
403 | #define L3PROTO(ct) ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num | ||
404 | |||
403 | static int | 405 | static int |
404 | ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | 406 | ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) |
405 | { | 407 | { |
@@ -407,6 +409,8 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
407 | struct nf_conntrack_tuple_hash *h; | 409 | struct nf_conntrack_tuple_hash *h; |
408 | struct list_head *i; | 410 | struct list_head *i; |
409 | u_int32_t *id = (u_int32_t *) &cb->args[1]; | 411 | u_int32_t *id = (u_int32_t *) &cb->args[1]; |
412 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); | ||
413 | u_int8_t l3proto = nfmsg->nfgen_family; | ||
410 | 414 | ||
411 | DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, | 415 | DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, |
412 | cb->args[0], *id); | 416 | cb->args[0], *id); |
@@ -418,6 +422,11 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
418 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 422 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
419 | continue; | 423 | continue; |
420 | ct = nf_ct_tuplehash_to_ctrack(h); | 424 | ct = nf_ct_tuplehash_to_ctrack(h); |
425 | /* Dump entries of a given L3 protocol number. | ||
426 | * If it is not specified, ie. l3proto == 0, | ||
427 | * then dump everything. */ | ||
428 | if (l3proto && L3PROTO(ct) != l3proto) | ||
429 | continue; | ||
421 | if (ct->id <= *id) | 430 | if (ct->id <= *id) |
422 | continue; | 431 | continue; |
423 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, | 432 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, |
@@ -444,6 +453,8 @@ ctnetlink_dump_table_w(struct sk_buff *skb, struct netlink_callback *cb) | |||
444 | struct nf_conntrack_tuple_hash *h; | 453 | struct nf_conntrack_tuple_hash *h; |
445 | struct list_head *i; | 454 | struct list_head *i; |
446 | u_int32_t *id = (u_int32_t *) &cb->args[1]; | 455 | u_int32_t *id = (u_int32_t *) &cb->args[1]; |
456 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); | ||
457 | u_int8_t l3proto = nfmsg->nfgen_family; | ||
447 | 458 | ||
448 | DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__, | 459 | DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__, |
449 | cb->args[0], *id); | 460 | cb->args[0], *id); |
@@ -455,6 +466,8 @@ ctnetlink_dump_table_w(struct sk_buff *skb, struct netlink_callback *cb) | |||
455 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 466 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
456 | continue; | 467 | continue; |
457 | ct = nf_ct_tuplehash_to_ctrack(h); | 468 | ct = nf_ct_tuplehash_to_ctrack(h); |
469 | if (l3proto && L3PROTO(ct) != l3proto) | ||
470 | continue; | ||
458 | if (ct->id <= *id) | 471 | if (ct->id <= *id) |
459 | continue; | 472 | continue; |
460 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, | 473 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, |
@@ -750,9 +763,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
750 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 763 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
751 | u32 rlen; | 764 | u32 rlen; |
752 | 765 | ||
753 | if (nfmsg->nfgen_family != AF_INET) | ||
754 | return -EAFNOSUPPORT; | ||
755 | |||
756 | if (NFNL_MSG_TYPE(nlh->nlmsg_type) == | 766 | if (NFNL_MSG_TYPE(nlh->nlmsg_type) == |
757 | IPCTNL_MSG_CT_GET_CTRZERO) { | 767 | IPCTNL_MSG_CT_GET_CTRZERO) { |
758 | #ifdef CONFIG_NF_CT_ACCT | 768 | #ifdef CONFIG_NF_CT_ACCT |
@@ -1251,12 +1261,16 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
1251 | struct nf_conntrack_expect *exp = NULL; | 1261 | struct nf_conntrack_expect *exp = NULL; |
1252 | struct list_head *i; | 1262 | struct list_head *i; |
1253 | u_int32_t *id = (u_int32_t *) &cb->args[0]; | 1263 | u_int32_t *id = (u_int32_t *) &cb->args[0]; |
1264 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); | ||
1265 | u_int8_t l3proto = nfmsg->nfgen_family; | ||
1254 | 1266 | ||
1255 | DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id); | 1267 | DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id); |
1256 | 1268 | ||
1257 | read_lock_bh(&nf_conntrack_lock); | 1269 | read_lock_bh(&nf_conntrack_lock); |
1258 | list_for_each_prev(i, &nf_conntrack_expect_list) { | 1270 | list_for_each_prev(i, &nf_conntrack_expect_list) { |
1259 | exp = (struct nf_conntrack_expect *) i; | 1271 | exp = (struct nf_conntrack_expect *) i; |
1272 | if (l3proto && exp->tuple.src.l3num != l3proto) | ||
1273 | continue; | ||
1260 | if (exp->id <= *id) | 1274 | if (exp->id <= *id) |
1261 | continue; | 1275 | continue; |
1262 | if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, | 1276 | if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, |
@@ -1298,9 +1312,6 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1298 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 1312 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
1299 | u32 rlen; | 1313 | u32 rlen; |
1300 | 1314 | ||
1301 | if (nfmsg->nfgen_family != AF_INET) | ||
1302 | return -EAFNOSUPPORT; | ||
1303 | |||
1304 | if ((*errp = netlink_dump_start(ctnl, skb, nlh, | 1315 | if ((*errp = netlink_dump_start(ctnl, skb, nlh, |
1305 | ctnetlink_exp_dump_table, | 1316 | ctnetlink_exp_dump_table, |
1306 | ctnetlink_done)) != 0) | 1317 | ctnetlink_done)) != 0) |