aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h57
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h2
-rw-r--r--net/netfilter/nf_conntrack_core.c25
-rw-r--r--net/netfilter/nf_conntrack_ecache.c14
-rw-r--r--net/netfilter/nf_conntrack_expect.c43
-rw-r--r--net/netfilter/nf_conntrack_netlink.c88
7 files changed, 197 insertions, 34 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index f11255e1ea35..2e0c53641cbe 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -199,7 +199,7 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple);
199 199
200extern void nf_conntrack_hash_insert(struct nf_conn *ct); 200extern void nf_conntrack_hash_insert(struct nf_conn *ct);
201 201
202extern void nf_conntrack_flush(struct net *net); 202extern void nf_conntrack_flush(struct net *net, u32 pid, int report);
203 203
204extern bool nf_ct_get_tuplepr(const struct sk_buff *skb, 204extern bool nf_ct_get_tuplepr(const struct sk_buff *skb,
205 unsigned int nhoff, u_int16_t l3num, 205 unsigned int nhoff, u_int16_t l3num,
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 1285ff26a014..0ff0dc69ca4a 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -17,6 +17,13 @@ struct nf_conntrack_ecache {
17 unsigned int events; 17 unsigned int events;
18}; 18};
19 19
20/* This structure is passed to event handler */
21struct nf_ct_event {
22 struct nf_conn *ct;
23 u32 pid;
24 int report;
25};
26
20extern struct atomic_notifier_head nf_conntrack_chain; 27extern struct atomic_notifier_head nf_conntrack_chain;
21extern int nf_conntrack_register_notifier(struct notifier_block *nb); 28extern int nf_conntrack_register_notifier(struct notifier_block *nb);
22extern int nf_conntrack_unregister_notifier(struct notifier_block *nb); 29extern int nf_conntrack_unregister_notifier(struct notifier_block *nb);
@@ -39,22 +46,56 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
39 local_bh_enable(); 46 local_bh_enable();
40} 47}
41 48
42static inline void nf_conntrack_event(enum ip_conntrack_events event, 49static inline void
43 struct nf_conn *ct) 50nf_conntrack_event_report(enum ip_conntrack_events event,
51 struct nf_conn *ct,
52 u32 pid,
53 int report)
44{ 54{
55 struct nf_ct_event item = {
56 .ct = ct,
57 .pid = pid,
58 .report = report
59 };
45 if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) 60 if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
46 atomic_notifier_call_chain(&nf_conntrack_chain, event, ct); 61 atomic_notifier_call_chain(&nf_conntrack_chain, event, &item);
47} 62}
48 63
64static inline void
65nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
66{
67 nf_conntrack_event_report(event, ct, 0, 0);
68}
69
70struct nf_exp_event {
71 struct nf_conntrack_expect *exp;
72 u32 pid;
73 int report;
74};
75
49extern struct atomic_notifier_head nf_ct_expect_chain; 76extern struct atomic_notifier_head nf_ct_expect_chain;
50extern int nf_ct_expect_register_notifier(struct notifier_block *nb); 77extern int nf_ct_expect_register_notifier(struct notifier_block *nb);
51extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb); 78extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb);
52 79
53static inline void 80static inline void
81nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
82 struct nf_conntrack_expect *exp,
83 u32 pid,
84 int report)
85{
86 struct nf_exp_event item = {
87 .exp = exp,
88 .pid = pid,
89 .report = report
90 };
91 atomic_notifier_call_chain(&nf_ct_expect_chain, event, &item);
92}
93
94static inline void
54nf_ct_expect_event(enum ip_conntrack_expect_events event, 95nf_ct_expect_event(enum ip_conntrack_expect_events event,
55 struct nf_conntrack_expect *exp) 96 struct nf_conntrack_expect *exp)
56{ 97{
57 atomic_notifier_call_chain(&nf_ct_expect_chain, event, exp); 98 nf_ct_expect_event_report(event, exp, 0, 0);
58} 99}
59 100
60extern int nf_conntrack_ecache_init(struct net *net); 101extern int nf_conntrack_ecache_init(struct net *net);
@@ -66,9 +107,17 @@ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
66 struct nf_conn *ct) {} 107 struct nf_conn *ct) {}
67static inline void nf_conntrack_event(enum ip_conntrack_events event, 108static inline void nf_conntrack_event(enum ip_conntrack_events event,
68 struct nf_conn *ct) {} 109 struct nf_conn *ct) {}
110static inline void nf_conntrack_event_report(enum ip_conntrack_events event,
111 struct nf_conn *ct,
112 u32 pid,
113 int report) {}
69static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} 114static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
70static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, 115static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
71 struct nf_conntrack_expect *exp) {} 116 struct nf_conntrack_expect *exp) {}
117static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
118 struct nf_conntrack_expect *exp,
119 u32 pid,
120 int report) {}
72static inline void nf_ct_event_cache_flush(struct net *net) {} 121static inline void nf_ct_event_cache_flush(struct net *net) {}
73 122
74static inline int nf_conntrack_ecache_init(struct net *net) 123static inline int nf_conntrack_ecache_init(struct net *net)
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 37a7fc1164b0..ab17a159ac66 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -100,6 +100,8 @@ void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
100 u_int8_t, const __be16 *, const __be16 *); 100 u_int8_t, const __be16 *, const __be16 *);
101void nf_ct_expect_put(struct nf_conntrack_expect *exp); 101void nf_ct_expect_put(struct nf_conntrack_expect *exp);
102int nf_ct_expect_related(struct nf_conntrack_expect *expect); 102int nf_ct_expect_related(struct nf_conntrack_expect *expect);
103int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
104 u32 pid, int report);
103 105
104#endif /*_NF_CONNTRACK_EXPECT_H*/ 106#endif /*_NF_CONNTRACK_EXPECT_H*/
105 107
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 1e649fb9e0df..dc3fea09f3fc 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -181,7 +181,8 @@ destroy_conntrack(struct nf_conntrack *nfct)
181 NF_CT_ASSERT(atomic_read(&nfct->use) == 0); 181 NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
182 NF_CT_ASSERT(!timer_pending(&ct->timeout)); 182 NF_CT_ASSERT(!timer_pending(&ct->timeout));
183 183
184 nf_conntrack_event(IPCT_DESTROY, ct); 184 if (!test_bit(IPS_DYING_BIT, &ct->status))
185 nf_conntrack_event(IPCT_DESTROY, ct);
185 set_bit(IPS_DYING_BIT, &ct->status); 186 set_bit(IPS_DYING_BIT, &ct->status);
186 187
187 /* To make sure we don't get any weird locking issues here: 188 /* To make sure we don't get any weird locking issues here:
@@ -972,8 +973,20 @@ void nf_ct_iterate_cleanup(struct net *net,
972} 973}
973EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup); 974EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup);
974 975
976struct __nf_ct_flush_report {
977 u32 pid;
978 int report;
979};
980
975static int kill_all(struct nf_conn *i, void *data) 981static int kill_all(struct nf_conn *i, void *data)
976{ 982{
983 struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data;
984
985 /* get_next_corpse sets the dying bit for us */
986 nf_conntrack_event_report(IPCT_DESTROY,
987 i,
988 fr->pid,
989 fr->report);
977 return 1; 990 return 1;
978} 991}
979 992
@@ -987,9 +1000,13 @@ void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, unsigned int s
987} 1000}
988EXPORT_SYMBOL_GPL(nf_ct_free_hashtable); 1001EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
989 1002
990void nf_conntrack_flush(struct net *net) 1003void nf_conntrack_flush(struct net *net, u32 pid, int report)
991{ 1004{
992 nf_ct_iterate_cleanup(net, kill_all, NULL); 1005 struct __nf_ct_flush_report fr = {
1006 .pid = pid,
1007 .report = report,
1008 };
1009 nf_ct_iterate_cleanup(net, kill_all, &fr);
993} 1010}
994EXPORT_SYMBOL_GPL(nf_conntrack_flush); 1011EXPORT_SYMBOL_GPL(nf_conntrack_flush);
995 1012
@@ -1005,7 +1022,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
1005 nf_ct_event_cache_flush(net); 1022 nf_ct_event_cache_flush(net);
1006 nf_conntrack_ecache_fini(net); 1023 nf_conntrack_ecache_fini(net);
1007 i_see_dead_people: 1024 i_see_dead_people:
1008 nf_conntrack_flush(net); 1025 nf_conntrack_flush(net, 0, 0);
1009 if (atomic_read(&net->ct.count) != 0) { 1026 if (atomic_read(&net->ct.count) != 0) {
1010 schedule(); 1027 schedule();
1011 goto i_see_dead_people; 1028 goto i_see_dead_people;
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index a5f5e2e65d13..dee4190209cc 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -35,9 +35,17 @@ static inline void
35__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) 35__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
36{ 36{
37 if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) 37 if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
38 && ecache->events) 38 && ecache->events) {
39 atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events, 39 struct nf_ct_event item = {
40 ecache->ct); 40 .ct = ecache->ct,
41 .pid = 0,
42 .report = 0
43 };
44
45 atomic_notifier_call_chain(&nf_conntrack_chain,
46 ecache->events,
47 &item);
48 }
41 49
42 ecache->events = 0; 50 ecache->events = 0;
43 nf_ct_put(ecache->ct); 51 nf_ct_put(ecache->ct);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 37a703bc3b8e..3a8a34a6d37c 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -362,7 +362,7 @@ static inline int refresh_timer(struct nf_conntrack_expect *i)
362 return 1; 362 return 1;
363} 363}
364 364
365int nf_ct_expect_related(struct nf_conntrack_expect *expect) 365static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
366{ 366{
367 const struct nf_conntrack_expect_policy *p; 367 const struct nf_conntrack_expect_policy *p;
368 struct nf_conntrack_expect *i; 368 struct nf_conntrack_expect *i;
@@ -371,11 +371,8 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
371 struct net *net = nf_ct_exp_net(expect); 371 struct net *net = nf_ct_exp_net(expect);
372 struct hlist_node *n; 372 struct hlist_node *n;
373 unsigned int h; 373 unsigned int h;
374 int ret; 374 int ret = 0;
375
376 NF_CT_ASSERT(master_help);
377 375
378 spin_lock_bh(&nf_conntrack_lock);
379 if (!master_help->helper) { 376 if (!master_help->helper) {
380 ret = -ESHUTDOWN; 377 ret = -ESHUTDOWN;
381 goto out; 378 goto out;
@@ -409,18 +406,50 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
409 printk(KERN_WARNING 406 printk(KERN_WARNING
410 "nf_conntrack: expectation table full\n"); 407 "nf_conntrack: expectation table full\n");
411 ret = -EMFILE; 408 ret = -EMFILE;
412 goto out;
413 } 409 }
410out:
411 return ret;
412}
413
414int nf_ct_expect_related(struct nf_conntrack_expect *expect)
415{
416 int ret;
417
418 spin_lock_bh(&nf_conntrack_lock);
419 ret = __nf_ct_expect_check(expect);
420 if (ret < 0)
421 goto out;
414 422
415 nf_ct_expect_insert(expect); 423 nf_ct_expect_insert(expect);
424 atomic_inc(&expect->use);
425 spin_unlock_bh(&nf_conntrack_lock);
416 nf_ct_expect_event(IPEXP_NEW, expect); 426 nf_ct_expect_event(IPEXP_NEW, expect);
417 ret = 0; 427 nf_ct_expect_put(expect);
428 return ret;
418out: 429out:
419 spin_unlock_bh(&nf_conntrack_lock); 430 spin_unlock_bh(&nf_conntrack_lock);
420 return ret; 431 return ret;
421} 432}
422EXPORT_SYMBOL_GPL(nf_ct_expect_related); 433EXPORT_SYMBOL_GPL(nf_ct_expect_related);
423 434
435int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
436 u32 pid, int report)
437{
438 int ret;
439
440 spin_lock_bh(&nf_conntrack_lock);
441 ret = __nf_ct_expect_check(expect);
442 if (ret < 0)
443 goto out;
444 nf_ct_expect_insert(expect);
445out:
446 spin_unlock_bh(&nf_conntrack_lock);
447 if (ret == 0)
448 nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report);
449 return ret;
450}
451EXPORT_SYMBOL_GPL(nf_ct_expect_related_report);
452
424#ifdef CONFIG_PROC_FS 453#ifdef CONFIG_PROC_FS
425struct ct_expect_iter_state { 454struct ct_expect_iter_state {
426 struct seq_net_private p; 455 struct seq_net_private p;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 4f6486cfd337..ccc5ef1d7573 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -410,7 +410,8 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
410 struct nlmsghdr *nlh; 410 struct nlmsghdr *nlh;
411 struct nfgenmsg *nfmsg; 411 struct nfgenmsg *nfmsg;
412 struct nlattr *nest_parms; 412 struct nlattr *nest_parms;
413 struct nf_conn *ct = (struct nf_conn *)ptr; 413 struct nf_ct_event *item = (struct nf_ct_event *)ptr;
414 struct nf_conn *ct = item->ct;
414 struct sk_buff *skb; 415 struct sk_buff *skb;
415 unsigned int type; 416 unsigned int type;
416 sk_buff_data_t b; 417 sk_buff_data_t b;
@@ -443,7 +444,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
443 b = skb->tail; 444 b = skb->tail;
444 445
445 type |= NFNL_SUBSYS_CTNETLINK << 8; 446 type |= NFNL_SUBSYS_CTNETLINK << 8;
446 nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); 447 nlh = NLMSG_PUT(skb, item->pid, 0, type, sizeof(struct nfgenmsg));
447 nfmsg = NLMSG_DATA(nlh); 448 nfmsg = NLMSG_DATA(nlh);
448 449
449 nlh->nlmsg_flags = flags; 450 nlh->nlmsg_flags = flags;
@@ -511,7 +512,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
511 rcu_read_unlock(); 512 rcu_read_unlock();
512 513
513 nlh->nlmsg_len = skb->tail - b; 514 nlh->nlmsg_len = skb->tail - b;
514 nfnetlink_send(skb, 0, group, 0); 515 nfnetlink_send(skb, item->pid, group, item->report);
515 return NOTIFY_DONE; 516 return NOTIFY_DONE;
516 517
517nla_put_failure: 518nla_put_failure:
@@ -722,7 +723,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
722 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3); 723 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
723 else { 724 else {
724 /* Flush the whole table */ 725 /* Flush the whole table */
725 nf_conntrack_flush(&init_net); 726 nf_conntrack_flush(&init_net,
727 NETLINK_CB(skb).pid,
728 nlmsg_report(nlh));
726 return 0; 729 return 0;
727 } 730 }
728 731
@@ -743,6 +746,14 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
743 } 746 }
744 } 747 }
745 748
749 nf_conntrack_event_report(IPCT_DESTROY,
750 ct,
751 NETLINK_CB(skb).pid,
752 nlmsg_report(nlh));
753
754 /* death_by_timeout would report the event again */
755 set_bit(IPS_DYING_BIT, &ct->status);
756
746 nf_ct_kill(ct); 757 nf_ct_kill(ct);
747 nf_ct_put(ct); 758 nf_ct_put(ct);
748 759
@@ -1088,11 +1099,35 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
1088 return 0; 1099 return 0;
1089} 1100}
1090 1101
1102static inline void
1103ctnetlink_event_report(struct nf_conn *ct, u32 pid, int report)
1104{
1105 unsigned int events = 0;
1106
1107 if (test_bit(IPS_EXPECTED_BIT, &ct->status))
1108 events |= IPCT_RELATED;
1109 else
1110 events |= IPCT_NEW;
1111
1112 nf_conntrack_event_report(IPCT_STATUS |
1113 IPCT_HELPER |
1114 IPCT_REFRESH |
1115 IPCT_PROTOINFO |
1116 IPCT_NATSEQADJ |
1117 IPCT_MARK |
1118 events,
1119 ct,
1120 pid,
1121 report);
1122}
1123
1091static int 1124static int
1092ctnetlink_create_conntrack(struct nlattr *cda[], 1125ctnetlink_create_conntrack(struct nlattr *cda[],
1093 struct nf_conntrack_tuple *otuple, 1126 struct nf_conntrack_tuple *otuple,
1094 struct nf_conntrack_tuple *rtuple, 1127 struct nf_conntrack_tuple *rtuple,
1095 struct nf_conn *master_ct) 1128 struct nf_conn *master_ct,
1129 u32 pid,
1130 int report)
1096{ 1131{
1097 struct nf_conn *ct; 1132 struct nf_conn *ct;
1098 int err = -EINVAL; 1133 int err = -EINVAL;
@@ -1198,9 +1233,12 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
1198 ct->master = master_ct; 1233 ct->master = master_ct;
1199 } 1234 }
1200 1235
1236 nf_conntrack_get(&ct->ct_general);
1201 add_timer(&ct->timeout); 1237 add_timer(&ct->timeout);
1202 nf_conntrack_hash_insert(ct); 1238 nf_conntrack_hash_insert(ct);
1203 rcu_read_unlock(); 1239 rcu_read_unlock();
1240 ctnetlink_event_report(ct, pid, report);
1241 nf_ct_put(ct);
1204 1242
1205 return 0; 1243 return 0;
1206 1244
@@ -1265,7 +1303,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1265 err = ctnetlink_create_conntrack(cda, 1303 err = ctnetlink_create_conntrack(cda,
1266 &otuple, 1304 &otuple,
1267 &rtuple, 1305 &rtuple,
1268 master_ct); 1306 master_ct,
1307 NETLINK_CB(skb).pid,
1308 nlmsg_report(nlh));
1269 if (err < 0 && master_ct) 1309 if (err < 0 && master_ct)
1270 nf_ct_put(master_ct); 1310 nf_ct_put(master_ct);
1271 1311
@@ -1277,6 +1317,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1277 * so there's no need to increase the refcount */ 1317 * so there's no need to increase the refcount */
1278 err = -EEXIST; 1318 err = -EEXIST;
1279 if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { 1319 if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
1320 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
1321
1280 /* we only allow nat config for new conntracks */ 1322 /* we only allow nat config for new conntracks */
1281 if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { 1323 if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
1282 err = -EOPNOTSUPP; 1324 err = -EOPNOTSUPP;
@@ -1287,8 +1329,19 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1287 err = -EOPNOTSUPP; 1329 err = -EOPNOTSUPP;
1288 goto out_unlock; 1330 goto out_unlock;
1289 } 1331 }
1290 err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), 1332
1291 cda); 1333 err = ctnetlink_change_conntrack(ct, cda);
1334 if (err == 0) {
1335 nf_conntrack_get(&ct->ct_general);
1336 spin_unlock_bh(&nf_conntrack_lock);
1337 ctnetlink_event_report(ct,
1338 NETLINK_CB(skb).pid,
1339 nlmsg_report(nlh));
1340 nf_ct_put(ct);
1341 } else
1342 spin_unlock_bh(&nf_conntrack_lock);
1343
1344 return err;
1292 } 1345 }
1293 1346
1294out_unlock: 1347out_unlock:
@@ -1423,7 +1476,8 @@ static int ctnetlink_expect_event(struct notifier_block *this,
1423{ 1476{
1424 struct nlmsghdr *nlh; 1477 struct nlmsghdr *nlh;
1425 struct nfgenmsg *nfmsg; 1478 struct nfgenmsg *nfmsg;
1426 struct nf_conntrack_expect *exp = (struct nf_conntrack_expect *)ptr; 1479 struct nf_exp_event *item = (struct nf_exp_event *)ptr;
1480 struct nf_conntrack_expect *exp = item->exp;
1427 struct sk_buff *skb; 1481 struct sk_buff *skb;
1428 unsigned int type; 1482 unsigned int type;
1429 sk_buff_data_t b; 1483 sk_buff_data_t b;
@@ -1445,7 +1499,7 @@ static int ctnetlink_expect_event(struct notifier_block *this,
1445 b = skb->tail; 1499 b = skb->tail;
1446 1500
1447 type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; 1501 type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1448 nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); 1502 nlh = NLMSG_PUT(skb, item->pid, 0, type, sizeof(struct nfgenmsg));
1449 nfmsg = NLMSG_DATA(nlh); 1503 nfmsg = NLMSG_DATA(nlh);
1450 1504
1451 nlh->nlmsg_flags = flags; 1505 nlh->nlmsg_flags = flags;
@@ -1459,7 +1513,7 @@ static int ctnetlink_expect_event(struct notifier_block *this,
1459 rcu_read_unlock(); 1513 rcu_read_unlock();
1460 1514
1461 nlh->nlmsg_len = skb->tail - b; 1515 nlh->nlmsg_len = skb->tail - b;
1462 nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0); 1516 nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, item->report);
1463 return NOTIFY_DONE; 1517 return NOTIFY_DONE;
1464 1518
1465nla_put_failure: 1519nla_put_failure:
@@ -1673,7 +1727,7 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nlattr *cda[])
1673} 1727}
1674 1728
1675static int 1729static int
1676ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3) 1730ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3, u32 pid, int report)
1677{ 1731{
1678 struct nf_conntrack_tuple tuple, mask, master_tuple; 1732 struct nf_conntrack_tuple tuple, mask, master_tuple;
1679 struct nf_conntrack_tuple_hash *h = NULL; 1733 struct nf_conntrack_tuple_hash *h = NULL;
@@ -1720,7 +1774,7 @@ ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3)
1720 memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); 1774 memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3));
1721 exp->mask.src.u.all = mask.src.u.all; 1775 exp->mask.src.u.all = mask.src.u.all;
1722 1776
1723 err = nf_ct_expect_related(exp); 1777 err = nf_ct_expect_related_report(exp, pid, report);
1724 nf_ct_expect_put(exp); 1778 nf_ct_expect_put(exp);
1725 1779
1726out: 1780out:
@@ -1753,8 +1807,12 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
1753 if (!exp) { 1807 if (!exp) {
1754 spin_unlock_bh(&nf_conntrack_lock); 1808 spin_unlock_bh(&nf_conntrack_lock);
1755 err = -ENOENT; 1809 err = -ENOENT;
1756 if (nlh->nlmsg_flags & NLM_F_CREATE) 1810 if (nlh->nlmsg_flags & NLM_F_CREATE) {
1757 err = ctnetlink_create_expect(cda, u3); 1811 err = ctnetlink_create_expect(cda,
1812 u3,
1813 NETLINK_CB(skb).pid,
1814 nlmsg_report(nlh));
1815 }
1758 return err; 1816 return err;
1759 } 1817 }
1760 1818