Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ctnetlink: add expectation deletion events

This patch allows to listen to events that inform about
expectations destroyed.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by

Pablo Neira Ayuso and committed by
Patrick McHardy
ebbf41df 43f974cd

+33 -12
+1
include/linux/netfilter/nf_conntrack_common.h
··· 98 98 99 99 enum ip_conntrack_expect_events { 100 100 IPEXP_NEW, /* new expectation */ 101 + IPEXP_DESTROY, /* destroyed expectation */ 101 102 }; 102 103 103 104 /* expectation flags */
+7 -1
include/net/netfilter/nf_conntrack_expect.h
··· 82 82 nf_ct_find_expectation(struct net *net, u16 zone, 83 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 92 void nf_ct_remove_expectations(struct nf_conn *ct); 87 93 void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); 88 94 void nf_ct_remove_userspace_expectations(void);
+4 -2
net/netfilter/nf_conntrack_expect.c
··· 41 41 static HLIST_HEAD(nf_ct_userspace_expect_list); 42 42 43 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 47 struct nf_conn_help *master_help = nfct_help(exp->master); 47 48 struct net *net = nf_ct_exp_net(exp); ··· 56 55 if (!(exp->flags & NF_CT_EXPECT_USERSPACE)) 57 56 master_help->expecting[exp->class]--; 58 57 58 + nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report); 59 59 nf_ct_expect_put(exp); 60 60 61 61 NF_CT_STAT_INC(net, expect_delete); 62 62 } 63 - EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); 63 + EXPORT_SYMBOL_GPL(nf_ct_unlink_expect_report); 64 64 65 65 static void nf_ct_expectation_timed_out(unsigned long ul_expect) 66 66 {
+21 -9
net/netfilter/nf_conntrack_netlink.c
··· 1632 1632 struct nlmsghdr *nlh; 1633 1633 struct nfgenmsg *nfmsg; 1634 1634 struct sk_buff *skb; 1635 - unsigned int type; 1635 + unsigned int type, group; 1636 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 1642 type = IPCTNL_MSG_EXP_NEW; 1640 1643 flags = NLM_F_CREATE|NLM_F_EXCL; 1644 + group = NFNLGRP_CONNTRACK_EXP_NEW; 1641 1645 } else 1642 1646 return 0; 1643 1647 1644 - if (!item->report && 1645 - !nfnetlink_has_listeners(net, NFNLGRP_CONNTRACK_EXP_NEW)) 1648 + if (!item->report && !nfnetlink_has_listeners(net, group)) 1646 1649 return 0; 1647 1650 1648 1651 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); ··· 1668 1665 rcu_read_unlock(); 1669 1666 1670 1667 nlmsg_end(skb, nlh); 1671 - nfnetlink_send(skb, net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, 1672 - item->report, GFP_ATOMIC); 1668 + nfnetlink_send(skb, net, item->pid, group, item->report, GFP_ATOMIC); 1673 1669 return 0; 1674 1670 1675 1671 nla_put_failure: ··· 1851 1849 } 1852 1850 1853 1851 /* after list removal, usage count == 1 */ 1854 - nf_ct_unexpect_related(exp); 1852 + spin_lock_bh(&nf_conntrack_lock); 1853 + if (del_timer(&exp->timeout)) { 1854 + nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).pid, 1855 + nlmsg_report(nlh)); 1856 + nf_ct_expect_put(exp); 1857 + } 1858 + spin_unlock_bh(&nf_conntrack_lock); 1855 1859 /* have to put what we 'get' above. 1856 1860 * after this line usage count == 0 */ 1857 1861 nf_ct_expect_put(exp); ··· 1874 1866 m_help = nfct_help(exp->master); 1875 1867 if (!strcmp(m_help->helper->name, name) && 1876 1868 del_timer(&exp->timeout)) { 1877 - nf_ct_unlink_expect(exp); 1869 + nf_ct_unlink_expect_report(exp, 1870 + NETLINK_CB(skb).pid, 1871 + nlmsg_report(nlh)); 1878 1872 nf_ct_expect_put(exp); 1879 1873 } 1880 1874 } ··· 1890 1880 &net->ct.expect_hash[i], 1891 1881 hnode) { 1892 1882 if (del_timer(&exp->timeout)) { 1893 - nf_ct_unlink_expect(exp); 1883 + nf_ct_unlink_expect_report(exp, 1884 + NETLINK_CB(skb).pid, 1885 + nlmsg_report(nlh)); 1894 1886 nf_ct_expect_put(exp); 1895 1887 } 1896 1888 }