diff options
| -rw-r--r-- | include/linux/netfilter/nf_conntrack_common.h | 1 | ||||
| -rw-r--r-- | include/net/netfilter/nf_conntrack_expect.h | 8 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 6 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 30 |
4 files changed, 33 insertions, 12 deletions
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 23a1a08578a8..50cdc2559a5a 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h | |||
| @@ -98,6 +98,7 @@ enum ip_conntrack_events { | |||
| 98 | 98 | ||
| 99 | enum ip_conntrack_expect_events { | 99 | enum ip_conntrack_expect_events { |
| 100 | IPEXP_NEW, /* new expectation */ | 100 | IPEXP_NEW, /* new expectation */ |
| 101 | IPEXP_DESTROY, /* destroyed expectation */ | ||
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | /* expectation flags */ | 104 | /* expectation flags */ |
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 416b83844485..0f8a8c587532 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h | |||
| @@ -82,7 +82,13 @@ struct nf_conntrack_expect * | |||
| 82 | nf_ct_find_expectation(struct net *net, u16 zone, | 82 | nf_ct_find_expectation(struct net *net, u16 zone, |
| 83 | const struct nf_conntrack_tuple *tuple); | 83 | const struct nf_conntrack_tuple *tuple); |
| 84 | 84 | ||
| 85 | void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); | 85 | void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, |
| 86 | u32 pid, int report); | ||
| 87 | static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) | ||
| 88 | { | ||
| 89 | nf_ct_unlink_expect_report(exp, 0, 0); | ||
| 90 | } | ||
| 91 | |||
| 86 | void nf_ct_remove_expectations(struct nf_conn *ct); | 92 | void nf_ct_remove_expectations(struct nf_conn *ct); |
| 87 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); | 93 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); |
| 88 | void nf_ct_remove_userspace_expectations(void); | 94 | void nf_ct_remove_userspace_expectations(void); |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index b30a1f2aac00..46e8966912b1 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
| @@ -41,7 +41,8 @@ static struct kmem_cache *nf_ct_expect_cachep __read_mostly; | |||
| 41 | static HLIST_HEAD(nf_ct_userspace_expect_list); | 41 | static HLIST_HEAD(nf_ct_userspace_expect_list); |
| 42 | 42 | ||
| 43 | /* nf_conntrack_expect helper functions */ | 43 | /* nf_conntrack_expect helper functions */ |
| 44 | void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) | 44 | void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, |
| 45 | u32 pid, int report) | ||
| 45 | { | 46 | { |
| 46 | struct nf_conn_help *master_help = nfct_help(exp->master); | 47 | struct nf_conn_help *master_help = nfct_help(exp->master); |
| 47 | struct net *net = nf_ct_exp_net(exp); | 48 | struct net *net = nf_ct_exp_net(exp); |
| @@ -55,11 +56,12 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) | |||
| 55 | if (!(exp->flags & NF_CT_EXPECT_USERSPACE)) | 56 | if (!(exp->flags & NF_CT_EXPECT_USERSPACE)) |
| 56 | master_help->expecting[exp->class]--; | 57 | master_help->expecting[exp->class]--; |
| 57 | 58 | ||
| 59 | nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report); | ||
| 58 | nf_ct_expect_put(exp); | 60 | nf_ct_expect_put(exp); |
| 59 | 61 | ||
| 60 | NF_CT_STAT_INC(net, expect_delete); | 62 | NF_CT_STAT_INC(net, expect_delete); |
| 61 | } | 63 | } |
| 62 | EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); | 64 | EXPORT_SYMBOL_GPL(nf_ct_unlink_expect_report); |
| 63 | 65 | ||
| 64 | static void nf_ct_expectation_timed_out(unsigned long ul_expect) | 66 | static void nf_ct_expectation_timed_out(unsigned long ul_expect) |
| 65 | { | 67 | { |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b4077be5f663..62bad229106b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -1632,17 +1632,20 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) | |||
| 1632 | struct nlmsghdr *nlh; | 1632 | struct nlmsghdr *nlh; |
| 1633 | struct nfgenmsg *nfmsg; | 1633 | struct nfgenmsg *nfmsg; |
| 1634 | struct sk_buff *skb; | 1634 | struct sk_buff *skb; |
| 1635 | unsigned int type; | 1635 | unsigned int type, group; |
| 1636 | int flags = 0; | 1636 | int flags = 0; |
| 1637 | 1637 | ||
| 1638 | if (events & (1 << IPEXP_NEW)) { | 1638 | if (events & (1 << IPEXP_DESTROY)) { |
| 1639 | type = IPCTNL_MSG_EXP_DELETE; | ||
| 1640 | group = NFNLGRP_CONNTRACK_EXP_DESTROY; | ||
| 1641 | } else if (events & (1 << IPEXP_NEW)) { | ||
| 1639 | type = IPCTNL_MSG_EXP_NEW; | 1642 | type = IPCTNL_MSG_EXP_NEW; |
| 1640 | flags = NLM_F_CREATE|NLM_F_EXCL; | 1643 | flags = NLM_F_CREATE|NLM_F_EXCL; |
| 1644 | group = NFNLGRP_CONNTRACK_EXP_NEW; | ||
| 1641 | } else | 1645 | } else |
| 1642 | return 0; | 1646 | return 0; |
| 1643 | 1647 | ||
| 1644 | if (!item->report && | 1648 | if (!item->report && !nfnetlink_has_listeners(net, group)) |
| 1645 | !nfnetlink_has_listeners(net, NFNLGRP_CONNTRACK_EXP_NEW)) | ||
| 1646 | return 0; | 1649 | return 0; |
| 1647 | 1650 | ||
| 1648 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | 1651 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
| @@ -1665,8 +1668,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) | |||
| 1665 | rcu_read_unlock(); | 1668 | rcu_read_unlock(); |
| 1666 | 1669 | ||
| 1667 | nlmsg_end(skb, nlh); | 1670 | nlmsg_end(skb, nlh); |
| 1668 | nfnetlink_send(skb, net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, | 1671 | nfnetlink_send(skb, net, item->pid, group, item->report, GFP_ATOMIC); |
| 1669 | item->report, GFP_ATOMIC); | ||
| 1670 | return 0; | 1672 | return 0; |
| 1671 | 1673 | ||
| 1672 | nla_put_failure: | 1674 | nla_put_failure: |
| @@ -1849,7 +1851,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1849 | } | 1851 | } |
| 1850 | 1852 | ||
| 1851 | /* after list removal, usage count == 1 */ | 1853 | /* after list removal, usage count == 1 */ |
| 1852 | nf_ct_unexpect_related(exp); | 1854 | spin_lock_bh(&nf_conntrack_lock); |
| 1855 | if (del_timer(&exp->timeout)) { | ||
| 1856 | nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).pid, | ||
| 1857 | nlmsg_report(nlh)); | ||
| 1858 | nf_ct_expect_put(exp); | ||
| 1859 | } | ||
| 1860 | spin_unlock_bh(&nf_conntrack_lock); | ||
| 1853 | /* have to put what we 'get' above. | 1861 | /* have to put what we 'get' above. |
| 1854 | * after this line usage count == 0 */ | 1862 | * after this line usage count == 0 */ |
| 1855 | nf_ct_expect_put(exp); | 1863 | nf_ct_expect_put(exp); |
| @@ -1866,7 +1874,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1866 | m_help = nfct_help(exp->master); | 1874 | m_help = nfct_help(exp->master); |
| 1867 | if (!strcmp(m_help->helper->name, name) && | 1875 | if (!strcmp(m_help->helper->name, name) && |
| 1868 | del_timer(&exp->timeout)) { | 1876 | del_timer(&exp->timeout)) { |
| 1869 | nf_ct_unlink_expect(exp); | 1877 | nf_ct_unlink_expect_report(exp, |
| 1878 | NETLINK_CB(skb).pid, | ||
| 1879 | nlmsg_report(nlh)); | ||
| 1870 | nf_ct_expect_put(exp); | 1880 | nf_ct_expect_put(exp); |
| 1871 | } | 1881 | } |
| 1872 | } | 1882 | } |
| @@ -1880,7 +1890,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1880 | &net->ct.expect_hash[i], | 1890 | &net->ct.expect_hash[i], |
| 1881 | hnode) { | 1891 | hnode) { |
| 1882 | if (del_timer(&exp->timeout)) { | 1892 | if (del_timer(&exp->timeout)) { |
| 1883 | nf_ct_unlink_expect(exp); | 1893 | nf_ct_unlink_expect_report(exp, |
| 1894 | NETLINK_CB(skb).pid, | ||
| 1895 | nlmsg_report(nlh)); | ||
| 1884 | nf_ct_expect_put(exp); | 1896 | nf_ct_expect_put(exp); |
| 1885 | } | 1897 | } |
| 1886 | } | 1898 | } |
