diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-06-03 04:32:06 -0400 |
---|---|---|
committer | pablo <pablo@1984.(none)> | 2009-06-03 04:32:06 -0400 |
commit | e34d5c1a4f9919a81b4ea4591d7383245f35cb8e (patch) | |
tree | 0a19bfe3e162b2b8de9b9414dcc2bef0a07e7133 | |
parent | 17e6e4eac070607a35464ea7e2c5eceac32e5eca (diff) |
netfilter: conntrack: replace notify chain by function pointer
This patch removes the notify chain infrastructure and replace it
by a simple function pointer. This issue has been mentioned in the
mailing list several times: the use of the notify chain adds
too much overhead for something that is only used by ctnetlink.
This patch also changes nfnetlink_send(). It seems that gfp_any()
returns GFP_KERNEL for user-context request, like those via
ctnetlink, inside the RCU read-side section which is not valid.
Using GFP_KERNEL is also evil since netlink may schedule(),
this leads to "scheduling while atomic" bug reports.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | include/linux/netfilter/nfnetlink.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_ecache.h | 68 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_ecache.c | 83 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 42 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 5 |
5 files changed, 139 insertions, 61 deletions
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index c600083cbdf5..2214e5161461 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h | |||
@@ -75,7 +75,7 @@ extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); | |||
75 | 75 | ||
76 | extern int nfnetlink_has_listeners(unsigned int group); | 76 | extern int nfnetlink_has_listeners(unsigned int group); |
77 | extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, | 77 | extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, |
78 | int echo); | 78 | int echo, gfp_t flags); |
79 | extern void nfnetlink_set_err(u32 pid, u32 group, int error); | 79 | extern void nfnetlink_set_err(u32 pid, u32 group, int error); |
80 | extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); | 80 | extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); |
81 | 81 | ||
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 2e17a2d0eb3b..1afb907e015a 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h | |||
@@ -6,7 +6,6 @@ | |||
6 | #define _NF_CONNTRACK_ECACHE_H | 6 | #define _NF_CONNTRACK_ECACHE_H |
7 | #include <net/netfilter/nf_conntrack.h> | 7 | #include <net/netfilter/nf_conntrack.h> |
8 | 8 | ||
9 | #include <linux/notifier.h> | ||
10 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
11 | #include <net/net_namespace.h> | 10 | #include <net/net_namespace.h> |
12 | #include <net/netfilter/nf_conntrack_expect.h> | 11 | #include <net/netfilter/nf_conntrack_expect.h> |
@@ -69,9 +68,13 @@ struct nf_ct_event { | |||
69 | int report; | 68 | int report; |
70 | }; | 69 | }; |
71 | 70 | ||
72 | extern struct atomic_notifier_head nf_conntrack_chain; | 71 | struct nf_ct_event_notifier { |
73 | extern int nf_conntrack_register_notifier(struct notifier_block *nb); | 72 | int (*fcn)(unsigned int events, struct nf_ct_event *item); |
74 | extern int nf_conntrack_unregister_notifier(struct notifier_block *nb); | 73 | }; |
74 | |||
75 | extern struct nf_ct_event_notifier *nf_conntrack_event_cb; | ||
76 | extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); | ||
77 | extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); | ||
75 | 78 | ||
76 | extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); | 79 | extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); |
77 | extern void __nf_ct_event_cache_init(struct nf_conn *ct); | 80 | extern void __nf_ct_event_cache_init(struct nf_conn *ct); |
@@ -97,13 +100,23 @@ nf_conntrack_event_report(enum ip_conntrack_events event, | |||
97 | u32 pid, | 100 | u32 pid, |
98 | int report) | 101 | int report) |
99 | { | 102 | { |
100 | struct nf_ct_event item = { | 103 | struct nf_ct_event_notifier *notify; |
101 | .ct = ct, | 104 | |
102 | .pid = pid, | 105 | rcu_read_lock(); |
103 | .report = report | 106 | notify = rcu_dereference(nf_conntrack_event_cb); |
104 | }; | 107 | if (notify == NULL) |
105 | if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) | 108 | goto out_unlock; |
106 | atomic_notifier_call_chain(&nf_conntrack_chain, event, &item); | 109 | |
110 | if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { | ||
111 | struct nf_ct_event item = { | ||
112 | .ct = ct, | ||
113 | .pid = pid, | ||
114 | .report = report | ||
115 | }; | ||
116 | notify->fcn(event, &item); | ||
117 | } | ||
118 | out_unlock: | ||
119 | rcu_read_unlock(); | ||
107 | } | 120 | } |
108 | 121 | ||
109 | static inline void | 122 | static inline void |
@@ -118,9 +131,13 @@ struct nf_exp_event { | |||
118 | int report; | 131 | int report; |
119 | }; | 132 | }; |
120 | 133 | ||
121 | extern struct atomic_notifier_head nf_ct_expect_chain; | 134 | struct nf_exp_event_notifier { |
122 | extern int nf_ct_expect_register_notifier(struct notifier_block *nb); | 135 | int (*fcn)(unsigned int events, struct nf_exp_event *item); |
123 | extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb); | 136 | }; |
137 | |||
138 | extern struct nf_exp_event_notifier *nf_expect_event_cb; | ||
139 | extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb); | ||
140 | extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb); | ||
124 | 141 | ||
125 | static inline void | 142 | static inline void |
126 | nf_ct_expect_event_report(enum ip_conntrack_expect_events event, | 143 | nf_ct_expect_event_report(enum ip_conntrack_expect_events event, |
@@ -128,12 +145,23 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, | |||
128 | u32 pid, | 145 | u32 pid, |
129 | int report) | 146 | int report) |
130 | { | 147 | { |
131 | struct nf_exp_event item = { | 148 | struct nf_exp_event_notifier *notify; |
132 | .exp = exp, | 149 | |
133 | .pid = pid, | 150 | rcu_read_lock(); |
134 | .report = report | 151 | notify = rcu_dereference(nf_expect_event_cb); |
135 | }; | 152 | if (notify == NULL) |
136 | atomic_notifier_call_chain(&nf_ct_expect_chain, event, &item); | 153 | goto out_unlock; |
154 | |||
155 | { | ||
156 | struct nf_exp_event item = { | ||
157 | .exp = exp, | ||
158 | .pid = pid, | ||
159 | .report = report | ||
160 | }; | ||
161 | notify->fcn(event, &item); | ||
162 | } | ||
163 | out_unlock: | ||
164 | rcu_read_unlock(); | ||
137 | } | 165 | } |
138 | 166 | ||
139 | static inline void | 167 | static inline void |
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index dee4190209cc..5516b3e64b43 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c | |||
@@ -16,24 +16,32 @@ | |||
16 | #include <linux/stddef.h> | 16 | #include <linux/stddef.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/percpu.h> | 18 | #include <linux/percpu.h> |
19 | #include <linux/notifier.h> | ||
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
21 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
22 | 21 | ||
23 | #include <net/netfilter/nf_conntrack.h> | 22 | #include <net/netfilter/nf_conntrack.h> |
24 | #include <net/netfilter/nf_conntrack_core.h> | 23 | #include <net/netfilter/nf_conntrack_core.h> |
25 | 24 | ||
26 | ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); | 25 | static DEFINE_MUTEX(nf_ct_ecache_mutex); |
27 | EXPORT_SYMBOL_GPL(nf_conntrack_chain); | ||
28 | 26 | ||
29 | ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain); | 27 | struct nf_ct_event_notifier *nf_conntrack_event_cb __read_mostly; |
30 | EXPORT_SYMBOL_GPL(nf_ct_expect_chain); | 28 | EXPORT_SYMBOL_GPL(nf_conntrack_event_cb); |
29 | |||
30 | struct nf_exp_event_notifier *nf_expect_event_cb __read_mostly; | ||
31 | EXPORT_SYMBOL_GPL(nf_expect_event_cb); | ||
31 | 32 | ||
32 | /* deliver cached events and clear cache entry - must be called with locally | 33 | /* deliver cached events and clear cache entry - must be called with locally |
33 | * disabled softirqs */ | 34 | * disabled softirqs */ |
34 | static inline void | 35 | static inline void |
35 | __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) | 36 | __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) |
36 | { | 37 | { |
38 | struct nf_ct_event_notifier *notify; | ||
39 | |||
40 | rcu_read_lock(); | ||
41 | notify = rcu_dereference(nf_conntrack_event_cb); | ||
42 | if (notify == NULL) | ||
43 | goto out_unlock; | ||
44 | |||
37 | if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) | 45 | if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) |
38 | && ecache->events) { | 46 | && ecache->events) { |
39 | struct nf_ct_event item = { | 47 | struct nf_ct_event item = { |
@@ -42,14 +50,15 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) | |||
42 | .report = 0 | 50 | .report = 0 |
43 | }; | 51 | }; |
44 | 52 | ||
45 | atomic_notifier_call_chain(&nf_conntrack_chain, | 53 | notify->fcn(ecache->events, &item); |
46 | ecache->events, | ||
47 | &item); | ||
48 | } | 54 | } |
49 | 55 | ||
50 | ecache->events = 0; | 56 | ecache->events = 0; |
51 | nf_ct_put(ecache->ct); | 57 | nf_ct_put(ecache->ct); |
52 | ecache->ct = NULL; | 58 | ecache->ct = NULL; |
59 | |||
60 | out_unlock: | ||
61 | rcu_read_unlock(); | ||
53 | } | 62 | } |
54 | 63 | ||
55 | /* Deliver all cached events for a particular conntrack. This is called | 64 | /* Deliver all cached events for a particular conntrack. This is called |
@@ -111,26 +120,68 @@ void nf_conntrack_ecache_fini(struct net *net) | |||
111 | free_percpu(net->ct.ecache); | 120 | free_percpu(net->ct.ecache); |
112 | } | 121 | } |
113 | 122 | ||
114 | int nf_conntrack_register_notifier(struct notifier_block *nb) | 123 | int nf_conntrack_register_notifier(struct nf_ct_event_notifier *new) |
115 | { | 124 | { |
116 | return atomic_notifier_chain_register(&nf_conntrack_chain, nb); | 125 | int ret = 0; |
126 | struct nf_ct_event_notifier *notify; | ||
127 | |||
128 | mutex_lock(&nf_ct_ecache_mutex); | ||
129 | notify = rcu_dereference(nf_conntrack_event_cb); | ||
130 | if (notify != NULL) { | ||
131 | ret = -EBUSY; | ||
132 | goto out_unlock; | ||
133 | } | ||
134 | rcu_assign_pointer(nf_conntrack_event_cb, new); | ||
135 | mutex_unlock(&nf_ct_ecache_mutex); | ||
136 | return ret; | ||
137 | |||
138 | out_unlock: | ||
139 | mutex_unlock(&nf_ct_ecache_mutex); | ||
140 | return ret; | ||
117 | } | 141 | } |
118 | EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); | 142 | EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); |
119 | 143 | ||
120 | int nf_conntrack_unregister_notifier(struct notifier_block *nb) | 144 | void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *new) |
121 | { | 145 | { |
122 | return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb); | 146 | struct nf_ct_event_notifier *notify; |
147 | |||
148 | mutex_lock(&nf_ct_ecache_mutex); | ||
149 | notify = rcu_dereference(nf_conntrack_event_cb); | ||
150 | BUG_ON(notify != new); | ||
151 | rcu_assign_pointer(nf_conntrack_event_cb, NULL); | ||
152 | mutex_unlock(&nf_ct_ecache_mutex); | ||
123 | } | 153 | } |
124 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); | 154 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); |
125 | 155 | ||
126 | int nf_ct_expect_register_notifier(struct notifier_block *nb) | 156 | int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *new) |
127 | { | 157 | { |
128 | return atomic_notifier_chain_register(&nf_ct_expect_chain, nb); | 158 | int ret = 0; |
159 | struct nf_exp_event_notifier *notify; | ||
160 | |||
161 | mutex_lock(&nf_ct_ecache_mutex); | ||
162 | notify = rcu_dereference(nf_expect_event_cb); | ||
163 | if (notify != NULL) { | ||
164 | ret = -EBUSY; | ||
165 | goto out_unlock; | ||
166 | } | ||
167 | rcu_assign_pointer(nf_expect_event_cb, new); | ||
168 | mutex_unlock(&nf_ct_ecache_mutex); | ||
169 | return ret; | ||
170 | |||
171 | out_unlock: | ||
172 | mutex_unlock(&nf_ct_ecache_mutex); | ||
173 | return ret; | ||
129 | } | 174 | } |
130 | EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier); | 175 | EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier); |
131 | 176 | ||
132 | int nf_ct_expect_unregister_notifier(struct notifier_block *nb) | 177 | void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *new) |
133 | { | 178 | { |
134 | return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb); | 179 | struct nf_exp_event_notifier *notify; |
180 | |||
181 | mutex_lock(&nf_ct_ecache_mutex); | ||
182 | notify = rcu_dereference(nf_expect_event_cb); | ||
183 | BUG_ON(notify != new); | ||
184 | rcu_assign_pointer(nf_expect_event_cb, NULL); | ||
185 | mutex_unlock(&nf_ct_ecache_mutex); | ||
135 | } | 186 | } |
136 | EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); | 187 | EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b1b9e4fb7ded..4448b062de0c 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/netlink.h> | 27 | #include <linux/netlink.h> |
28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/notifier.h> | ||
31 | 30 | ||
32 | #include <linux/netfilter.h> | 31 | #include <linux/netfilter.h> |
33 | #include <net/netlink.h> | 32 | #include <net/netlink.h> |
@@ -454,13 +453,12 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct) | |||
454 | ; | 453 | ; |
455 | } | 454 | } |
456 | 455 | ||
457 | static int ctnetlink_conntrack_event(struct notifier_block *this, | 456 | static int |
458 | unsigned long events, void *ptr) | 457 | ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) |
459 | { | 458 | { |
460 | struct nlmsghdr *nlh; | 459 | struct nlmsghdr *nlh; |
461 | struct nfgenmsg *nfmsg; | 460 | struct nfgenmsg *nfmsg; |
462 | struct nlattr *nest_parms; | 461 | struct nlattr *nest_parms; |
463 | struct nf_ct_event *item = (struct nf_ct_event *)ptr; | ||
464 | struct nf_conn *ct = item->ct; | 462 | struct nf_conn *ct = item->ct; |
465 | struct sk_buff *skb; | 463 | struct sk_buff *skb; |
466 | unsigned int type; | 464 | unsigned int type; |
@@ -468,7 +466,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
468 | 466 | ||
469 | /* ignore our fake conntrack entry */ | 467 | /* ignore our fake conntrack entry */ |
470 | if (ct == &nf_conntrack_untracked) | 468 | if (ct == &nf_conntrack_untracked) |
471 | return NOTIFY_DONE; | 469 | return 0; |
472 | 470 | ||
473 | if (events & IPCT_DESTROY) { | 471 | if (events & IPCT_DESTROY) { |
474 | type = IPCTNL_MSG_CT_DELETE; | 472 | type = IPCTNL_MSG_CT_DELETE; |
@@ -481,10 +479,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
481 | type = IPCTNL_MSG_CT_NEW; | 479 | type = IPCTNL_MSG_CT_NEW; |
482 | group = NFNLGRP_CONNTRACK_UPDATE; | 480 | group = NFNLGRP_CONNTRACK_UPDATE; |
483 | } else | 481 | } else |
484 | return NOTIFY_DONE; | 482 | return 0; |
485 | 483 | ||
486 | if (!item->report && !nfnetlink_has_listeners(group)) | 484 | if (!item->report && !nfnetlink_has_listeners(group)) |
487 | return NOTIFY_DONE; | 485 | return 0; |
488 | 486 | ||
489 | skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC); | 487 | skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC); |
490 | if (skb == NULL) | 488 | if (skb == NULL) |
@@ -560,8 +558,8 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
560 | rcu_read_unlock(); | 558 | rcu_read_unlock(); |
561 | 559 | ||
562 | nlmsg_end(skb, nlh); | 560 | nlmsg_end(skb, nlh); |
563 | nfnetlink_send(skb, item->pid, group, item->report); | 561 | nfnetlink_send(skb, item->pid, group, item->report, GFP_ATOMIC); |
564 | return NOTIFY_DONE; | 562 | return 0; |
565 | 563 | ||
566 | nla_put_failure: | 564 | nla_put_failure: |
567 | rcu_read_unlock(); | 565 | rcu_read_unlock(); |
@@ -570,7 +568,7 @@ nlmsg_failure: | |||
570 | kfree_skb(skb); | 568 | kfree_skb(skb); |
571 | errout: | 569 | errout: |
572 | nfnetlink_set_err(0, group, -ENOBUFS); | 570 | nfnetlink_set_err(0, group, -ENOBUFS); |
573 | return NOTIFY_DONE; | 571 | return 0; |
574 | } | 572 | } |
575 | #endif /* CONFIG_NF_CONNTRACK_EVENTS */ | 573 | #endif /* CONFIG_NF_CONNTRACK_EVENTS */ |
576 | 574 | ||
@@ -1507,12 +1505,11 @@ nla_put_failure: | |||
1507 | } | 1505 | } |
1508 | 1506 | ||
1509 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 1507 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
1510 | static int ctnetlink_expect_event(struct notifier_block *this, | 1508 | static int |
1511 | unsigned long events, void *ptr) | 1509 | ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) |
1512 | { | 1510 | { |
1513 | struct nlmsghdr *nlh; | 1511 | struct nlmsghdr *nlh; |
1514 | struct nfgenmsg *nfmsg; | 1512 | struct nfgenmsg *nfmsg; |
1515 | struct nf_exp_event *item = (struct nf_exp_event *)ptr; | ||
1516 | struct nf_conntrack_expect *exp = item->exp; | 1513 | struct nf_conntrack_expect *exp = item->exp; |
1517 | struct sk_buff *skb; | 1514 | struct sk_buff *skb; |
1518 | unsigned int type; | 1515 | unsigned int type; |
@@ -1522,11 +1519,11 @@ static int ctnetlink_expect_event(struct notifier_block *this, | |||
1522 | type = IPCTNL_MSG_EXP_NEW; | 1519 | type = IPCTNL_MSG_EXP_NEW; |
1523 | flags = NLM_F_CREATE|NLM_F_EXCL; | 1520 | flags = NLM_F_CREATE|NLM_F_EXCL; |
1524 | } else | 1521 | } else |
1525 | return NOTIFY_DONE; | 1522 | return 0; |
1526 | 1523 | ||
1527 | if (!item->report && | 1524 | if (!item->report && |
1528 | !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) | 1525 | !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) |
1529 | return NOTIFY_DONE; | 1526 | return 0; |
1530 | 1527 | ||
1531 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | 1528 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
1532 | if (skb == NULL) | 1529 | if (skb == NULL) |
@@ -1548,8 +1545,9 @@ static int ctnetlink_expect_event(struct notifier_block *this, | |||
1548 | rcu_read_unlock(); | 1545 | rcu_read_unlock(); |
1549 | 1546 | ||
1550 | nlmsg_end(skb, nlh); | 1547 | nlmsg_end(skb, nlh); |
1551 | nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, item->report); | 1548 | nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, |
1552 | return NOTIFY_DONE; | 1549 | item->report, GFP_ATOMIC); |
1550 | return 0; | ||
1553 | 1551 | ||
1554 | nla_put_failure: | 1552 | nla_put_failure: |
1555 | rcu_read_unlock(); | 1553 | rcu_read_unlock(); |
@@ -1558,7 +1556,7 @@ nlmsg_failure: | |||
1558 | kfree_skb(skb); | 1556 | kfree_skb(skb); |
1559 | errout: | 1557 | errout: |
1560 | nfnetlink_set_err(0, 0, -ENOBUFS); | 1558 | nfnetlink_set_err(0, 0, -ENOBUFS); |
1561 | return NOTIFY_DONE; | 1559 | return 0; |
1562 | } | 1560 | } |
1563 | #endif | 1561 | #endif |
1564 | static int ctnetlink_exp_done(struct netlink_callback *cb) | 1562 | static int ctnetlink_exp_done(struct netlink_callback *cb) |
@@ -1864,12 +1862,12 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1864 | } | 1862 | } |
1865 | 1863 | ||
1866 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 1864 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
1867 | static struct notifier_block ctnl_notifier = { | 1865 | static struct nf_ct_event_notifier ctnl_notifier = { |
1868 | .notifier_call = ctnetlink_conntrack_event, | 1866 | .fcn = ctnetlink_conntrack_event, |
1869 | }; | 1867 | }; |
1870 | 1868 | ||
1871 | static struct notifier_block ctnl_notifier_exp = { | 1869 | static struct nf_exp_event_notifier ctnl_notifier_exp = { |
1872 | .notifier_call = ctnetlink_expect_event, | 1870 | .fcn = ctnetlink_expect_event, |
1873 | }; | 1871 | }; |
1874 | #endif | 1872 | #endif |
1875 | 1873 | ||
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 9dbd5709aad7..92761a988375 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -107,9 +107,10 @@ int nfnetlink_has_listeners(unsigned int group) | |||
107 | } | 107 | } |
108 | EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); | 108 | EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); |
109 | 109 | ||
110 | int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) | 110 | int nfnetlink_send(struct sk_buff *skb, u32 pid, |
111 | unsigned group, int echo, gfp_t flags) | ||
111 | { | 112 | { |
112 | return nlmsg_notify(nfnl, skb, pid, group, echo, gfp_any()); | 113 | return nlmsg_notify(nfnl, skb, pid, group, echo, flags); |
113 | } | 114 | } |
114 | EXPORT_SYMBOL_GPL(nfnetlink_send); | 115 | EXPORT_SYMBOL_GPL(nfnetlink_send); |
115 | 116 | ||