diff options
author | David S. Miller <davem@davemloft.net> | 2008-11-28 05:19:15 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-28 05:19:15 -0500 |
commit | ed77a89c30fa03dcb234a84ddea710b3fb7b62da (patch) | |
tree | 69f3e2c2bbf2fdd4f742e891441f01307d1d1f49 /net/netfilter | |
parent | 475ad8e2172d7f8b73af5532a8dad265b51339c2 (diff) | |
parent | d6e8cc6cc7ac77b0f9118f78c453a2e834e62709 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Conflicts:
net/netfilter/nf_conntrack_netlink.c
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_conntrack_amanda.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 61 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_ecache.c | 14 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 43 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_ftp.c | 9 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_h323_main.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_helper.c | 32 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_irc.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netbios_ns.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 201 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_pptp.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_gre.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_sctp.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_sane.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_sip.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_tftp.c | 1 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 4 | ||||
-rw-r--r-- | net/netfilter/xt_NFLOG.c | 5 | ||||
-rw-r--r-- | net/netfilter/xt_recent.c | 22 |
19 files changed, 289 insertions, 114 deletions
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 38aedeeaf4e..4f8fcf49854 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -30,6 +30,7 @@ MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); | |||
30 | MODULE_DESCRIPTION("Amanda connection tracking module"); | 30 | MODULE_DESCRIPTION("Amanda connection tracking module"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | MODULE_ALIAS("ip_conntrack_amanda"); | 32 | MODULE_ALIAS("ip_conntrack_amanda"); |
33 | MODULE_ALIAS_NFCT_HELPER("amanda"); | ||
33 | 34 | ||
34 | module_param(master_timeout, uint, 0600); | 35 | module_param(master_timeout, uint, 0600); |
35 | MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); | 36 | MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 233fdd2d7d2..7e83f74cd5d 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -39,13 +39,13 @@ | |||
39 | #include <net/netfilter/nf_conntrack_extend.h> | 39 | #include <net/netfilter/nf_conntrack_extend.h> |
40 | #include <net/netfilter/nf_conntrack_acct.h> | 40 | #include <net/netfilter/nf_conntrack_acct.h> |
41 | #include <net/netfilter/nf_nat.h> | 41 | #include <net/netfilter/nf_nat.h> |
42 | #include <net/netfilter/nf_nat_core.h> | ||
42 | 43 | ||
43 | #define NF_CONNTRACK_VERSION "0.5.0" | 44 | #define NF_CONNTRACK_VERSION "0.5.0" |
44 | 45 | ||
45 | unsigned int | 46 | int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, |
46 | (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, | 47 | enum nf_nat_manip_type manip, |
47 | enum nf_nat_manip_type manip, | 48 | struct nlattr *attr) __read_mostly; |
48 | struct nlattr *attr) __read_mostly; | ||
49 | EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook); | 49 | EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook); |
50 | 50 | ||
51 | DEFINE_SPINLOCK(nf_conntrack_lock); | 51 | DEFINE_SPINLOCK(nf_conntrack_lock); |
@@ -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: |
@@ -586,14 +587,7 @@ init_conntrack(struct net *net, | |||
586 | nf_conntrack_get(&ct->master->ct_general); | 587 | nf_conntrack_get(&ct->master->ct_general); |
587 | NF_CT_STAT_INC(net, expect_new); | 588 | NF_CT_STAT_INC(net, expect_new); |
588 | } else { | 589 | } else { |
589 | struct nf_conntrack_helper *helper; | 590 | __nf_ct_try_assign_helper(ct, GFP_ATOMIC); |
590 | |||
591 | helper = __nf_ct_helper_find(&repl_tuple); | ||
592 | if (helper) { | ||
593 | help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); | ||
594 | if (help) | ||
595 | rcu_assign_pointer(help->helper, helper); | ||
596 | } | ||
597 | NF_CT_STAT_INC(net, new); | 591 | NF_CT_STAT_INC(net, new); |
598 | } | 592 | } |
599 | 593 | ||
@@ -770,7 +764,6 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, | |||
770 | const struct nf_conntrack_tuple *newreply) | 764 | const struct nf_conntrack_tuple *newreply) |
771 | { | 765 | { |
772 | struct nf_conn_help *help = nfct_help(ct); | 766 | struct nf_conn_help *help = nfct_help(ct); |
773 | struct nf_conntrack_helper *helper; | ||
774 | 767 | ||
775 | /* Should be unconfirmed, so not in hash table yet */ | 768 | /* Should be unconfirmed, so not in hash table yet */ |
776 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 769 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
@@ -783,23 +776,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, | |||
783 | return; | 776 | return; |
784 | 777 | ||
785 | rcu_read_lock(); | 778 | rcu_read_lock(); |
786 | helper = __nf_ct_helper_find(newreply); | 779 | __nf_ct_try_assign_helper(ct, GFP_ATOMIC); |
787 | if (helper == NULL) { | ||
788 | if (help) | ||
789 | rcu_assign_pointer(help->helper, NULL); | ||
790 | goto out; | ||
791 | } | ||
792 | |||
793 | if (help == NULL) { | ||
794 | help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); | ||
795 | if (help == NULL) | ||
796 | goto out; | ||
797 | } else { | ||
798 | memset(&help->help, 0, sizeof(help->help)); | ||
799 | } | ||
800 | |||
801 | rcu_assign_pointer(help->helper, helper); | ||
802 | out: | ||
803 | rcu_read_unlock(); | 780 | rcu_read_unlock(); |
804 | } | 781 | } |
805 | EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); | 782 | EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); |
@@ -994,8 +971,20 @@ void nf_ct_iterate_cleanup(struct net *net, | |||
994 | } | 971 | } |
995 | EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup); | 972 | EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup); |
996 | 973 | ||
974 | struct __nf_ct_flush_report { | ||
975 | u32 pid; | ||
976 | int report; | ||
977 | }; | ||
978 | |||
997 | static int kill_all(struct nf_conn *i, void *data) | 979 | static int kill_all(struct nf_conn *i, void *data) |
998 | { | 980 | { |
981 | struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data; | ||
982 | |||
983 | /* get_next_corpse sets the dying bit for us */ | ||
984 | nf_conntrack_event_report(IPCT_DESTROY, | ||
985 | i, | ||
986 | fr->pid, | ||
987 | fr->report); | ||
999 | return 1; | 988 | return 1; |
1000 | } | 989 | } |
1001 | 990 | ||
@@ -1009,9 +998,13 @@ void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, unsigned int s | |||
1009 | } | 998 | } |
1010 | EXPORT_SYMBOL_GPL(nf_ct_free_hashtable); | 999 | EXPORT_SYMBOL_GPL(nf_ct_free_hashtable); |
1011 | 1000 | ||
1012 | void nf_conntrack_flush(struct net *net) | 1001 | void nf_conntrack_flush(struct net *net, u32 pid, int report) |
1013 | { | 1002 | { |
1014 | nf_ct_iterate_cleanup(net, kill_all, NULL); | 1003 | struct __nf_ct_flush_report fr = { |
1004 | .pid = pid, | ||
1005 | .report = report, | ||
1006 | }; | ||
1007 | nf_ct_iterate_cleanup(net, kill_all, &fr); | ||
1015 | } | 1008 | } |
1016 | EXPORT_SYMBOL_GPL(nf_conntrack_flush); | 1009 | EXPORT_SYMBOL_GPL(nf_conntrack_flush); |
1017 | 1010 | ||
@@ -1027,7 +1020,7 @@ static void nf_conntrack_cleanup_net(struct net *net) | |||
1027 | nf_ct_event_cache_flush(net); | 1020 | nf_ct_event_cache_flush(net); |
1028 | nf_conntrack_ecache_fini(net); | 1021 | nf_conntrack_ecache_fini(net); |
1029 | i_see_dead_people: | 1022 | i_see_dead_people: |
1030 | nf_conntrack_flush(net); | 1023 | nf_conntrack_flush(net, 0, 0); |
1031 | if (atomic_read(&net->ct.count) != 0) { | 1024 | if (atomic_read(&net->ct.count) != 0) { |
1032 | schedule(); | 1025 | schedule(); |
1033 | goto i_see_dead_people; | 1026 | goto i_see_dead_people; |
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index a5f5e2e65d1..dee4190209c 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 37a703bc3b8..3a8a34a6d37 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 | ||
365 | int nf_ct_expect_related(struct nf_conntrack_expect *expect) | 365 | static 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 | } |
410 | out: | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | int 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; | ||
418 | out: | 429 | out: |
419 | spin_unlock_bh(&nf_conntrack_lock); | 430 | spin_unlock_bh(&nf_conntrack_lock); |
420 | return ret; | 431 | return ret; |
421 | } | 432 | } |
422 | EXPORT_SYMBOL_GPL(nf_ct_expect_related); | 433 | EXPORT_SYMBOL_GPL(nf_ct_expect_related); |
423 | 434 | ||
435 | int 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); | ||
445 | out: | ||
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 | } | ||
451 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); | ||
452 | |||
424 | #ifdef CONFIG_PROC_FS | 453 | #ifdef CONFIG_PROC_FS |
425 | struct ct_expect_iter_state { | 454 | struct ct_expect_iter_state { |
426 | struct seq_net_private p; | 455 | struct seq_net_private p; |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 629500901bd..00fecc385f9 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL"); | |||
29 | MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); | 29 | MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); |
30 | MODULE_DESCRIPTION("ftp connection tracking helper"); | 30 | MODULE_DESCRIPTION("ftp connection tracking helper"); |
31 | MODULE_ALIAS("ip_conntrack_ftp"); | 31 | MODULE_ALIAS("ip_conntrack_ftp"); |
32 | MODULE_ALIAS_NFCT_HELPER("ftp"); | ||
32 | 33 | ||
33 | /* This is slow, but it's simple. --RR */ | 34 | /* This is slow, but it's simple. --RR */ |
34 | static char *ftp_buffer; | 35 | static char *ftp_buffer; |
@@ -357,7 +358,7 @@ static int help(struct sk_buff *skb, | |||
357 | int ret; | 358 | int ret; |
358 | u32 seq; | 359 | u32 seq; |
359 | int dir = CTINFO2DIR(ctinfo); | 360 | int dir = CTINFO2DIR(ctinfo); |
360 | unsigned int matchlen, matchoff; | 361 | unsigned int uninitialized_var(matchlen), uninitialized_var(matchoff); |
361 | struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; | 362 | struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; |
362 | struct nf_conntrack_expect *exp; | 363 | struct nf_conntrack_expect *exp; |
363 | union nf_inet_addr *daddr; | 364 | union nf_inet_addr *daddr; |
@@ -427,10 +428,8 @@ static int help(struct sk_buff *skb, | |||
427 | connection tracking, not packet filtering. | 428 | connection tracking, not packet filtering. |
428 | However, it is necessary for accurate tracking in | 429 | However, it is necessary for accurate tracking in |
429 | this case. */ | 430 | this case. */ |
430 | if (net_ratelimit()) | 431 | pr_debug("conntrack_ftp: partial %s %u+%u\n", |
431 | printk("conntrack_ftp: partial %s %u+%u\n", | 432 | search[dir][i].pattern, ntohl(th->seq), datalen); |
432 | search[dir][i].pattern, | ||
433 | ntohl(th->seq), datalen); | ||
434 | ret = NF_DROP; | 433 | ret = NF_DROP; |
435 | goto out; | 434 | goto out; |
436 | } else if (found == 0) { /* No match */ | 435 | } else if (found == 0) { /* No match */ |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 99bc803d1dd..687bd633c3d 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -1827,3 +1827,4 @@ MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); | |||
1827 | MODULE_DESCRIPTION("H.323 connection tracking helper"); | 1827 | MODULE_DESCRIPTION("H.323 connection tracking helper"); |
1828 | MODULE_LICENSE("GPL"); | 1828 | MODULE_LICENSE("GPL"); |
1829 | MODULE_ALIAS("ip_conntrack_h323"); | 1829 | MODULE_ALIAS("ip_conntrack_h323"); |
1830 | MODULE_ALIAS_NFCT_HELPER("h323"); | ||
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index c39b6a99413..a51bdac9f3a 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -45,7 +45,7 @@ static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple) | |||
45 | (__force __u16)tuple->src.u.all) % nf_ct_helper_hsize; | 45 | (__force __u16)tuple->src.u.all) % nf_ct_helper_hsize; |
46 | } | 46 | } |
47 | 47 | ||
48 | struct nf_conntrack_helper * | 48 | static struct nf_conntrack_helper * |
49 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) | 49 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) |
50 | { | 50 | { |
51 | struct nf_conntrack_helper *helper; | 51 | struct nf_conntrack_helper *helper; |
@@ -63,7 +63,6 @@ __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) | |||
63 | } | 63 | } |
64 | return NULL; | 64 | return NULL; |
65 | } | 65 | } |
66 | EXPORT_SYMBOL_GPL(__nf_ct_helper_find); | ||
67 | 66 | ||
68 | struct nf_conntrack_helper * | 67 | struct nf_conntrack_helper * |
69 | __nf_conntrack_helper_find_byname(const char *name) | 68 | __nf_conntrack_helper_find_byname(const char *name) |
@@ -95,6 +94,35 @@ struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) | |||
95 | } | 94 | } |
96 | EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); | 95 | EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); |
97 | 96 | ||
97 | int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags) | ||
98 | { | ||
99 | int ret = 0; | ||
100 | struct nf_conntrack_helper *helper; | ||
101 | struct nf_conn_help *help = nfct_help(ct); | ||
102 | |||
103 | helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); | ||
104 | if (helper == NULL) { | ||
105 | if (help) | ||
106 | rcu_assign_pointer(help->helper, NULL); | ||
107 | goto out; | ||
108 | } | ||
109 | |||
110 | if (help == NULL) { | ||
111 | help = nf_ct_helper_ext_add(ct, flags); | ||
112 | if (help == NULL) { | ||
113 | ret = -ENOMEM; | ||
114 | goto out; | ||
115 | } | ||
116 | } else { | ||
117 | memset(&help->help, 0, sizeof(help->help)); | ||
118 | } | ||
119 | |||
120 | rcu_assign_pointer(help->helper, helper); | ||
121 | out: | ||
122 | return ret; | ||
123 | } | ||
124 | EXPORT_SYMBOL_GPL(__nf_ct_try_assign_helper); | ||
125 | |||
98 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, | 126 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, |
99 | const struct nf_conntrack_helper *me) | 127 | const struct nf_conntrack_helper *me) |
100 | { | 128 | { |
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 4d681a04447..409c8be58e7 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
@@ -41,6 +41,7 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |||
41 | MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); | 41 | MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | MODULE_ALIAS("ip_conntrack_irc"); | 43 | MODULE_ALIAS("ip_conntrack_irc"); |
44 | MODULE_ALIAS_NFCT_HELPER("irc"); | ||
44 | 45 | ||
45 | module_param_array(ports, ushort, &ports_c, 0400); | 46 | module_param_array(ports, ushort, &ports_c, 0400); |
46 | MODULE_PARM_DESC(ports, "port numbers of IRC servers"); | 47 | MODULE_PARM_DESC(ports, "port numbers of IRC servers"); |
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 08404e6755f..5af4273b466 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c | |||
@@ -37,6 +37,7 @@ MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | |||
37 | MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper"); | 37 | MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper"); |
38 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
39 | MODULE_ALIAS("ip_conntrack_netbios_ns"); | 39 | MODULE_ALIAS("ip_conntrack_netbios_ns"); |
40 | MODULE_ALIAS_NFCT_HELPER("netbios_ns"); | ||
40 | 41 | ||
41 | static unsigned int timeout __read_mostly = 3; | 42 | static unsigned int timeout __read_mostly = 3; |
42 | module_param(timeout, uint, 0400); | 43 | module_param(timeout, uint, 0400); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 5f4a6516b3b..00e8c27130f 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -105,16 +105,14 @@ ctnetlink_dump_tuples(struct sk_buff *skb, | |||
105 | struct nf_conntrack_l3proto *l3proto; | 105 | struct nf_conntrack_l3proto *l3proto; |
106 | struct nf_conntrack_l4proto *l4proto; | 106 | struct nf_conntrack_l4proto *l4proto; |
107 | 107 | ||
108 | l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); | 108 | l3proto = __nf_ct_l3proto_find(tuple->src.l3num); |
109 | ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto); | 109 | ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto); |
110 | nf_ct_l3proto_put(l3proto); | ||
111 | 110 | ||
112 | if (unlikely(ret < 0)) | 111 | if (unlikely(ret < 0)) |
113 | return ret; | 112 | return ret; |
114 | 113 | ||
115 | l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); | 114 | l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum); |
116 | ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto); | 115 | ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto); |
117 | nf_ct_l4proto_put(l4proto); | ||
118 | 116 | ||
119 | return ret; | 117 | return ret; |
120 | } | 118 | } |
@@ -151,11 +149,9 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct) | |||
151 | struct nlattr *nest_proto; | 149 | struct nlattr *nest_proto; |
152 | int ret; | 150 | int ret; |
153 | 151 | ||
154 | l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct)); | 152 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); |
155 | if (!l4proto->to_nlattr) { | 153 | if (!l4proto->to_nlattr) |
156 | nf_ct_l4proto_put(l4proto); | ||
157 | return 0; | 154 | return 0; |
158 | } | ||
159 | 155 | ||
160 | nest_proto = nla_nest_start(skb, CTA_PROTOINFO | NLA_F_NESTED); | 156 | nest_proto = nla_nest_start(skb, CTA_PROTOINFO | NLA_F_NESTED); |
161 | if (!nest_proto) | 157 | if (!nest_proto) |
@@ -163,14 +159,11 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct) | |||
163 | 159 | ||
164 | ret = l4proto->to_nlattr(skb, nest_proto, ct); | 160 | ret = l4proto->to_nlattr(skb, nest_proto, ct); |
165 | 161 | ||
166 | nf_ct_l4proto_put(l4proto); | ||
167 | |||
168 | nla_nest_end(skb, nest_proto); | 162 | nla_nest_end(skb, nest_proto); |
169 | 163 | ||
170 | return ret; | 164 | return ret; |
171 | 165 | ||
172 | nla_put_failure: | 166 | nla_put_failure: |
173 | nf_ct_l4proto_put(l4proto); | ||
174 | return -1; | 167 | return -1; |
175 | } | 168 | } |
176 | 169 | ||
@@ -184,7 +177,6 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) | |||
184 | if (!help) | 177 | if (!help) |
185 | return 0; | 178 | return 0; |
186 | 179 | ||
187 | rcu_read_lock(); | ||
188 | helper = rcu_dereference(help->helper); | 180 | helper = rcu_dereference(help->helper); |
189 | if (!helper) | 181 | if (!helper) |
190 | goto out; | 182 | goto out; |
@@ -199,11 +191,9 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) | |||
199 | 191 | ||
200 | nla_nest_end(skb, nest_helper); | 192 | nla_nest_end(skb, nest_helper); |
201 | out: | 193 | out: |
202 | rcu_read_unlock(); | ||
203 | return 0; | 194 | return 0; |
204 | 195 | ||
205 | nla_put_failure: | 196 | nla_put_failure: |
206 | rcu_read_unlock(); | ||
207 | return -1; | 197 | return -1; |
208 | } | 198 | } |
209 | 199 | ||
@@ -420,7 +410,8 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
420 | struct nlmsghdr *nlh; | 410 | struct nlmsghdr *nlh; |
421 | struct nfgenmsg *nfmsg; | 411 | struct nfgenmsg *nfmsg; |
422 | struct nlattr *nest_parms; | 412 | struct nlattr *nest_parms; |
423 | 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; | ||
424 | struct sk_buff *skb; | 415 | struct sk_buff *skb; |
425 | unsigned int type; | 416 | unsigned int type; |
426 | sk_buff_data_t b; | 417 | sk_buff_data_t b; |
@@ -453,7 +444,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
453 | b = skb->tail; | 444 | b = skb->tail; |
454 | 445 | ||
455 | type |= NFNL_SUBSYS_CTNETLINK << 8; | 446 | type |= NFNL_SUBSYS_CTNETLINK << 8; |
456 | nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); | 447 | nlh = NLMSG_PUT(skb, item->pid, 0, type, sizeof(struct nfgenmsg)); |
457 | nfmsg = NLMSG_DATA(nlh); | 448 | nfmsg = NLMSG_DATA(nlh); |
458 | 449 | ||
459 | nlh->nlmsg_flags = flags; | 450 | nlh->nlmsg_flags = flags; |
@@ -461,6 +452,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
461 | nfmsg->version = NFNETLINK_V0; | 452 | nfmsg->version = NFNETLINK_V0; |
462 | nfmsg->res_id = 0; | 453 | nfmsg->res_id = 0; |
463 | 454 | ||
455 | rcu_read_lock(); | ||
464 | nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED); | 456 | nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED); |
465 | if (!nest_parms) | 457 | if (!nest_parms) |
466 | goto nla_put_failure; | 458 | goto nla_put_failure; |
@@ -517,13 +509,15 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
517 | && ctnetlink_dump_mark(skb, ct) < 0) | 509 | && ctnetlink_dump_mark(skb, ct) < 0) |
518 | goto nla_put_failure; | 510 | goto nla_put_failure; |
519 | #endif | 511 | #endif |
512 | rcu_read_unlock(); | ||
520 | 513 | ||
521 | nlh->nlmsg_len = skb->tail - b; | 514 | nlh->nlmsg_len = skb->tail - b; |
522 | nfnetlink_send(skb, 0, group, 0); | 515 | nfnetlink_send(skb, item->pid, group, item->report); |
523 | return NOTIFY_DONE; | 516 | return NOTIFY_DONE; |
524 | 517 | ||
525 | nlmsg_failure: | ||
526 | nla_put_failure: | 518 | nla_put_failure: |
519 | rcu_read_unlock(); | ||
520 | nlmsg_failure: | ||
527 | kfree_skb(skb); | 521 | kfree_skb(skb); |
528 | return NOTIFY_DONE; | 522 | return NOTIFY_DONE; |
529 | } | 523 | } |
@@ -729,7 +723,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
729 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3); | 723 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3); |
730 | else { | 724 | else { |
731 | /* Flush the whole table */ | 725 | /* Flush the whole table */ |
732 | nf_conntrack_flush(&init_net); | 726 | nf_conntrack_flush(&init_net, |
727 | NETLINK_CB(skb).pid, | ||
728 | nlmsg_report(nlh)); | ||
733 | return 0; | 729 | return 0; |
734 | } | 730 | } |
735 | 731 | ||
@@ -750,6 +746,14 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
750 | } | 746 | } |
751 | } | 747 | } |
752 | 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 | |||
753 | nf_ct_kill(ct); | 757 | nf_ct_kill(ct); |
754 | nf_ct_put(ct); | 758 | nf_ct_put(ct); |
755 | 759 | ||
@@ -795,8 +799,10 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
795 | return -ENOMEM; | 799 | return -ENOMEM; |
796 | } | 800 | } |
797 | 801 | ||
802 | rcu_read_lock(); | ||
798 | err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, | 803 | err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, |
799 | IPCTNL_MSG_CT_NEW, 1, ct); | 804 | IPCTNL_MSG_CT_NEW, 1, ct); |
805 | rcu_read_unlock(); | ||
800 | nf_ct_put(ct); | 806 | nf_ct_put(ct); |
801 | if (err <= 0) | 807 | if (err <= 0) |
802 | goto free; | 808 | goto free; |
@@ -922,8 +928,22 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[]) | |||
922 | } | 928 | } |
923 | 929 | ||
924 | helper = __nf_conntrack_helper_find_byname(helpname); | 930 | helper = __nf_conntrack_helper_find_byname(helpname); |
925 | if (helper == NULL) | 931 | if (helper == NULL) { |
932 | #ifdef CONFIG_MODULES | ||
933 | spin_unlock_bh(&nf_conntrack_lock); | ||
934 | |||
935 | if (request_module("nfct-helper-%s", helpname) < 0) { | ||
936 | spin_lock_bh(&nf_conntrack_lock); | ||
937 | return -EOPNOTSUPP; | ||
938 | } | ||
939 | |||
940 | spin_lock_bh(&nf_conntrack_lock); | ||
941 | helper = __nf_conntrack_helper_find_byname(helpname); | ||
942 | if (helper) | ||
943 | return -EAGAIN; | ||
944 | #endif | ||
926 | return -EOPNOTSUPP; | 945 | return -EOPNOTSUPP; |
946 | } | ||
927 | 947 | ||
928 | if (help) { | 948 | if (help) { |
929 | if (help->helper == helper) | 949 | if (help->helper == helper) |
@@ -1079,15 +1099,38 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[]) | |||
1079 | return 0; | 1099 | return 0; |
1080 | } | 1100 | } |
1081 | 1101 | ||
1102 | static inline void | ||
1103 | ctnetlink_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 | |||
1082 | static int | 1124 | static int |
1083 | ctnetlink_create_conntrack(struct nlattr *cda[], | 1125 | ctnetlink_create_conntrack(struct nlattr *cda[], |
1084 | struct nf_conntrack_tuple *otuple, | 1126 | struct nf_conntrack_tuple *otuple, |
1085 | struct nf_conntrack_tuple *rtuple, | 1127 | struct nf_conntrack_tuple *rtuple, |
1086 | struct nf_conn *master_ct) | 1128 | struct nf_conn *master_ct, |
1129 | u32 pid, | ||
1130 | int report) | ||
1087 | { | 1131 | { |
1088 | struct nf_conn *ct; | 1132 | struct nf_conn *ct; |
1089 | int err = -EINVAL; | 1133 | int err = -EINVAL; |
1090 | struct nf_conn_help *help; | ||
1091 | struct nf_conntrack_helper *helper; | 1134 | struct nf_conntrack_helper *helper; |
1092 | 1135 | ||
1093 | ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC); | 1136 | ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC); |
@@ -1102,16 +1145,55 @@ ctnetlink_create_conntrack(struct nlattr *cda[], | |||
1102 | ct->status |= IPS_CONFIRMED; | 1145 | ct->status |= IPS_CONFIRMED; |
1103 | 1146 | ||
1104 | rcu_read_lock(); | 1147 | rcu_read_lock(); |
1105 | helper = __nf_ct_helper_find(rtuple); | 1148 | if (cda[CTA_HELP]) { |
1106 | if (helper) { | 1149 | char *helpname; |
1107 | help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); | 1150 | |
1108 | if (help == NULL) { | 1151 | err = ctnetlink_parse_help(cda[CTA_HELP], &helpname); |
1152 | if (err < 0) { | ||
1153 | rcu_read_unlock(); | ||
1154 | goto err; | ||
1155 | } | ||
1156 | |||
1157 | helper = __nf_conntrack_helper_find_byname(helpname); | ||
1158 | if (helper == NULL) { | ||
1159 | rcu_read_unlock(); | ||
1160 | #ifdef CONFIG_MODULES | ||
1161 | if (request_module("nfct-helper-%s", helpname) < 0) { | ||
1162 | err = -EOPNOTSUPP; | ||
1163 | goto err; | ||
1164 | } | ||
1165 | |||
1166 | rcu_read_lock(); | ||
1167 | helper = __nf_conntrack_helper_find_byname(helpname); | ||
1168 | if (helper) { | ||
1169 | rcu_read_unlock(); | ||
1170 | err = -EAGAIN; | ||
1171 | goto err; | ||
1172 | } | ||
1173 | rcu_read_unlock(); | ||
1174 | #endif | ||
1175 | err = -EOPNOTSUPP; | ||
1176 | goto err; | ||
1177 | } else { | ||
1178 | struct nf_conn_help *help; | ||
1179 | |||
1180 | help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); | ||
1181 | if (help == NULL) { | ||
1182 | rcu_read_unlock(); | ||
1183 | err = -ENOMEM; | ||
1184 | goto err; | ||
1185 | } | ||
1186 | |||
1187 | /* not in hash table yet so not strictly necessary */ | ||
1188 | rcu_assign_pointer(help->helper, helper); | ||
1189 | } | ||
1190 | } else { | ||
1191 | /* try an implicit helper assignation */ | ||
1192 | err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC); | ||
1193 | if (err < 0) { | ||
1109 | rcu_read_unlock(); | 1194 | rcu_read_unlock(); |
1110 | err = -ENOMEM; | ||
1111 | goto err; | 1195 | goto err; |
1112 | } | 1196 | } |
1113 | /* not in hash table yet so not strictly necessary */ | ||
1114 | rcu_assign_pointer(help->helper, helper); | ||
1115 | } | 1197 | } |
1116 | 1198 | ||
1117 | if (cda[CTA_STATUS]) { | 1199 | if (cda[CTA_STATUS]) { |
@@ -1151,9 +1233,12 @@ ctnetlink_create_conntrack(struct nlattr *cda[], | |||
1151 | ct->master = master_ct; | 1233 | ct->master = master_ct; |
1152 | } | 1234 | } |
1153 | 1235 | ||
1236 | nf_conntrack_get(&ct->ct_general); | ||
1154 | add_timer(&ct->timeout); | 1237 | add_timer(&ct->timeout); |
1155 | nf_conntrack_hash_insert(ct); | 1238 | nf_conntrack_hash_insert(ct); |
1156 | rcu_read_unlock(); | 1239 | rcu_read_unlock(); |
1240 | ctnetlink_event_report(ct, pid, report); | ||
1241 | nf_ct_put(ct); | ||
1157 | 1242 | ||
1158 | return 0; | 1243 | return 0; |
1159 | 1244 | ||
@@ -1209,7 +1294,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1209 | goto out_unlock; | 1294 | goto out_unlock; |
1210 | } | 1295 | } |
1211 | master_ct = nf_ct_tuplehash_to_ctrack(master_h); | 1296 | master_ct = nf_ct_tuplehash_to_ctrack(master_h); |
1212 | atomic_inc(&master_ct->ct_general.use); | 1297 | nf_conntrack_get(&master_ct->ct_general); |
1213 | } | 1298 | } |
1214 | 1299 | ||
1215 | err = -ENOENT; | 1300 | err = -ENOENT; |
@@ -1217,9 +1302,10 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1217 | err = ctnetlink_create_conntrack(cda, | 1302 | err = ctnetlink_create_conntrack(cda, |
1218 | &otuple, | 1303 | &otuple, |
1219 | &rtuple, | 1304 | &rtuple, |
1220 | master_ct); | 1305 | master_ct, |
1306 | NETLINK_CB(skb).pid, | ||
1307 | nlmsg_report(nlh)); | ||
1221 | spin_unlock_bh(&nf_conntrack_lock); | 1308 | spin_unlock_bh(&nf_conntrack_lock); |
1222 | |||
1223 | if (err < 0 && master_ct) | 1309 | if (err < 0 && master_ct) |
1224 | nf_ct_put(master_ct); | 1310 | nf_ct_put(master_ct); |
1225 | 1311 | ||
@@ -1231,6 +1317,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1231 | * so there's no need to increase the refcount */ | 1317 | * so there's no need to increase the refcount */ |
1232 | err = -EEXIST; | 1318 | err = -EEXIST; |
1233 | 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 | |||
1234 | /* we only allow nat config for new conntracks */ | 1322 | /* we only allow nat config for new conntracks */ |
1235 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { | 1323 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { |
1236 | err = -EOPNOTSUPP; | 1324 | err = -EOPNOTSUPP; |
@@ -1241,8 +1329,19 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1241 | err = -EOPNOTSUPP; | 1329 | err = -EOPNOTSUPP; |
1242 | goto out_unlock; | 1330 | goto out_unlock; |
1243 | } | 1331 | } |
1244 | err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), | 1332 | |
1245 | 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; | ||
1246 | } | 1345 | } |
1247 | 1346 | ||
1248 | out_unlock: | 1347 | out_unlock: |
@@ -1293,16 +1392,14 @@ ctnetlink_exp_dump_mask(struct sk_buff *skb, | |||
1293 | if (!nest_parms) | 1392 | if (!nest_parms) |
1294 | goto nla_put_failure; | 1393 | goto nla_put_failure; |
1295 | 1394 | ||
1296 | l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); | 1395 | l3proto = __nf_ct_l3proto_find(tuple->src.l3num); |
1297 | ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto); | 1396 | ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto); |
1298 | nf_ct_l3proto_put(l3proto); | ||
1299 | 1397 | ||
1300 | if (unlikely(ret < 0)) | 1398 | if (unlikely(ret < 0)) |
1301 | goto nla_put_failure; | 1399 | goto nla_put_failure; |
1302 | 1400 | ||
1303 | l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); | 1401 | l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum); |
1304 | ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto); | 1402 | ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto); |
1305 | nf_ct_l4proto_put(l4proto); | ||
1306 | if (unlikely(ret < 0)) | 1403 | if (unlikely(ret < 0)) |
1307 | goto nla_put_failure; | 1404 | goto nla_put_failure; |
1308 | 1405 | ||
@@ -1379,7 +1476,8 @@ static int ctnetlink_expect_event(struct notifier_block *this, | |||
1379 | { | 1476 | { |
1380 | struct nlmsghdr *nlh; | 1477 | struct nlmsghdr *nlh; |
1381 | struct nfgenmsg *nfmsg; | 1478 | struct nfgenmsg *nfmsg; |
1382 | 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; | ||
1383 | struct sk_buff *skb; | 1481 | struct sk_buff *skb; |
1384 | unsigned int type; | 1482 | unsigned int type; |
1385 | sk_buff_data_t b; | 1483 | sk_buff_data_t b; |
@@ -1401,7 +1499,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, | |||
1401 | b = skb->tail; | 1499 | b = skb->tail; |
1402 | 1500 | ||
1403 | type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; | 1501 | type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; |
1404 | nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); | 1502 | nlh = NLMSG_PUT(skb, item->pid, 0, type, sizeof(struct nfgenmsg)); |
1405 | nfmsg = NLMSG_DATA(nlh); | 1503 | nfmsg = NLMSG_DATA(nlh); |
1406 | 1504 | ||
1407 | nlh->nlmsg_flags = flags; | 1505 | nlh->nlmsg_flags = flags; |
@@ -1409,15 +1507,18 @@ static int ctnetlink_expect_event(struct notifier_block *this, | |||
1409 | nfmsg->version = NFNETLINK_V0; | 1507 | nfmsg->version = NFNETLINK_V0; |
1410 | nfmsg->res_id = 0; | 1508 | nfmsg->res_id = 0; |
1411 | 1509 | ||
1510 | rcu_read_lock(); | ||
1412 | if (ctnetlink_exp_dump_expect(skb, exp) < 0) | 1511 | if (ctnetlink_exp_dump_expect(skb, exp) < 0) |
1413 | goto nla_put_failure; | 1512 | goto nla_put_failure; |
1513 | rcu_read_unlock(); | ||
1414 | 1514 | ||
1415 | nlh->nlmsg_len = skb->tail - b; | 1515 | nlh->nlmsg_len = skb->tail - b; |
1416 | nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0); | 1516 | nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, item->report); |
1417 | return NOTIFY_DONE; | 1517 | return NOTIFY_DONE; |
1418 | 1518 | ||
1419 | nlmsg_failure: | ||
1420 | nla_put_failure: | 1519 | nla_put_failure: |
1520 | rcu_read_unlock(); | ||
1521 | nlmsg_failure: | ||
1421 | kfree_skb(skb); | 1522 | kfree_skb(skb); |
1422 | return NOTIFY_DONE; | 1523 | return NOTIFY_DONE; |
1423 | } | 1524 | } |
@@ -1521,9 +1622,11 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1521 | if (!skb2) | 1622 | if (!skb2) |
1522 | goto out; | 1623 | goto out; |
1523 | 1624 | ||
1625 | rcu_read_lock(); | ||
1524 | err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, | 1626 | err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, |
1525 | nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, | 1627 | nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, |
1526 | 1, exp); | 1628 | 1, exp); |
1629 | rcu_read_unlock(); | ||
1527 | if (err <= 0) | 1630 | if (err <= 0) |
1528 | goto free; | 1631 | goto free; |
1529 | 1632 | ||
@@ -1624,7 +1727,7 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nlattr *cda[]) | |||
1624 | } | 1727 | } |
1625 | 1728 | ||
1626 | static int | 1729 | static int |
1627 | ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3) | 1730 | ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3, u32 pid, int report) |
1628 | { | 1731 | { |
1629 | struct nf_conntrack_tuple tuple, mask, master_tuple; | 1732 | struct nf_conntrack_tuple tuple, mask, master_tuple; |
1630 | struct nf_conntrack_tuple_hash *h = NULL; | 1733 | struct nf_conntrack_tuple_hash *h = NULL; |
@@ -1653,7 +1756,7 @@ ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3) | |||
1653 | 1756 | ||
1654 | if (!help || !help->helper) { | 1757 | if (!help || !help->helper) { |
1655 | /* such conntrack hasn't got any helper, abort */ | 1758 | /* such conntrack hasn't got any helper, abort */ |
1656 | err = -EINVAL; | 1759 | err = -EOPNOTSUPP; |
1657 | goto out; | 1760 | goto out; |
1658 | } | 1761 | } |
1659 | 1762 | ||
@@ -1671,7 +1774,7 @@ ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3) | |||
1671 | 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)); |
1672 | exp->mask.src.u.all = mask.src.u.all; | 1775 | exp->mask.src.u.all = mask.src.u.all; |
1673 | 1776 | ||
1674 | err = nf_ct_expect_related(exp); | 1777 | err = nf_ct_expect_related_report(exp, pid, report); |
1675 | nf_ct_expect_put(exp); | 1778 | nf_ct_expect_put(exp); |
1676 | 1779 | ||
1677 | out: | 1780 | out: |
@@ -1704,8 +1807,12 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1704 | if (!exp) { | 1807 | if (!exp) { |
1705 | spin_unlock_bh(&nf_conntrack_lock); | 1808 | spin_unlock_bh(&nf_conntrack_lock); |
1706 | err = -ENOENT; | 1809 | err = -ENOENT; |
1707 | if (nlh->nlmsg_flags & NLM_F_CREATE) | 1810 | if (nlh->nlmsg_flags & NLM_F_CREATE) { |
1708 | err = ctnetlink_create_expect(cda, u3); | 1811 | err = ctnetlink_create_expect(cda, |
1812 | u3, | ||
1813 | NETLINK_CB(skb).pid, | ||
1814 | nlmsg_report(nlh)); | ||
1815 | } | ||
1709 | return err; | 1816 | return err; |
1710 | } | 1817 | } |
1711 | 1818 | ||
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 1bc3001d182..9e169ef2e85 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
@@ -37,6 +37,7 @@ MODULE_LICENSE("GPL"); | |||
37 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | 37 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); |
38 | MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); | 38 | MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); |
39 | MODULE_ALIAS("ip_conntrack_pptp"); | 39 | MODULE_ALIAS("ip_conntrack_pptp"); |
40 | MODULE_ALIAS_NFCT_HELPER("pptp"); | ||
40 | 41 | ||
41 | static DEFINE_SPINLOCK(nf_pptp_lock); | 42 | static DEFINE_SPINLOCK(nf_pptp_lock); |
42 | 43 | ||
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 4ab62ad85dd..1b279f9d6bf 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
@@ -341,7 +341,7 @@ static int __init nf_ct_proto_gre_init(void) | |||
341 | return rv; | 341 | return rv; |
342 | } | 342 | } |
343 | 343 | ||
344 | static void nf_ct_proto_gre_fini(void) | 344 | static void __exit nf_ct_proto_gre_fini(void) |
345 | { | 345 | { |
346 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); | 346 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); |
347 | unregister_pernet_gen_subsys(proto_gre_net_id, &proto_gre_net_ops); | 347 | unregister_pernet_gen_subsys(proto_gre_net_id, &proto_gre_net_ops); |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index c2bd457bc2f..74e03790119 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -317,7 +317,7 @@ static int sctp_packet(struct nf_conn *ct, | |||
317 | goto out; | 317 | goto out; |
318 | } | 318 | } |
319 | 319 | ||
320 | old_state = new_state = SCTP_CONNTRACK_MAX; | 320 | old_state = new_state = SCTP_CONNTRACK_NONE; |
321 | write_lock_bh(&sctp_lock); | 321 | write_lock_bh(&sctp_lock); |
322 | for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { | 322 | for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { |
323 | /* Special cases of Verification tag check (Sec 8.5.1) */ | 323 | /* Special cases of Verification tag check (Sec 8.5.1) */ |
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index a94294b2b23..dcfecbb81c4 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c | |||
@@ -30,6 +30,7 @@ | |||
30 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
31 | MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>"); | 31 | MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>"); |
32 | MODULE_DESCRIPTION("SANE connection tracking helper"); | 32 | MODULE_DESCRIPTION("SANE connection tracking helper"); |
33 | MODULE_ALIAS_NFCT_HELPER("sane"); | ||
33 | 34 | ||
34 | static char *sane_buffer; | 35 | static char *sane_buffer; |
35 | 36 | ||
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 6813f1c8863..4b572163784 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -28,6 +28,7 @@ MODULE_LICENSE("GPL"); | |||
28 | MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); | 28 | MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); |
29 | MODULE_DESCRIPTION("SIP connection tracking helper"); | 29 | MODULE_DESCRIPTION("SIP connection tracking helper"); |
30 | MODULE_ALIAS("ip_conntrack_sip"); | 30 | MODULE_ALIAS("ip_conntrack_sip"); |
31 | MODULE_ALIAS_NFCT_HELPER("sip"); | ||
31 | 32 | ||
32 | #define MAX_PORTS 8 | 33 | #define MAX_PORTS 8 |
33 | static unsigned short ports[MAX_PORTS]; | 34 | static unsigned short ports[MAX_PORTS]; |
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index f57f6e7a71e..46e646b2e9b 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c | |||
@@ -22,6 +22,7 @@ MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>"); | |||
22 | MODULE_DESCRIPTION("TFTP connection tracking helper"); | 22 | MODULE_DESCRIPTION("TFTP connection tracking helper"); |
23 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
24 | MODULE_ALIAS("ip_conntrack_tftp"); | 24 | MODULE_ALIAS("ip_conntrack_tftp"); |
25 | MODULE_ALIAS_NFCT_HELPER("tftp"); | ||
25 | 26 | ||
26 | #define MAX_PORTS 8 | 27 | #define MAX_PORTS 8 |
27 | static unsigned short ports[MAX_PORTS]; | 28 | static unsigned short ports[MAX_PORTS]; |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 41e0105d382..2770b4e57ea 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/random.h> | 30 | #include <linux/random.h> |
31 | #include <net/sock.h> | 31 | #include <net/sock.h> |
32 | #include <net/netfilter/nf_log.h> | 32 | #include <net/netfilter/nf_log.h> |
33 | #include <net/netfilter/nfnetlink_log.h> | ||
33 | 34 | ||
34 | #include <asm/atomic.h> | 35 | #include <asm/atomic.h> |
35 | 36 | ||
@@ -533,7 +534,7 @@ static struct nf_loginfo default_loginfo = { | |||
533 | }; | 534 | }; |
534 | 535 | ||
535 | /* log handler for internal netfilter logging api */ | 536 | /* log handler for internal netfilter logging api */ |
536 | static void | 537 | void |
537 | nfulnl_log_packet(u_int8_t pf, | 538 | nfulnl_log_packet(u_int8_t pf, |
538 | unsigned int hooknum, | 539 | unsigned int hooknum, |
539 | const struct sk_buff *skb, | 540 | const struct sk_buff *skb, |
@@ -648,6 +649,7 @@ alloc_failure: | |||
648 | /* FIXME: statistics */ | 649 | /* FIXME: statistics */ |
649 | goto unlock_and_release; | 650 | goto unlock_and_release; |
650 | } | 651 | } |
652 | EXPORT_SYMBOL_GPL(nfulnl_log_packet); | ||
651 | 653 | ||
652 | static int | 654 | static int |
653 | nfulnl_rcv_nl_event(struct notifier_block *this, | 655 | nfulnl_rcv_nl_event(struct notifier_block *this, |
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c index 50e3a52d3b3..a57c5cf018e 100644 --- a/net/netfilter/xt_NFLOG.c +++ b/net/netfilter/xt_NFLOG.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/netfilter/x_tables.h> | 13 | #include <linux/netfilter/x_tables.h> |
14 | #include <linux/netfilter/xt_NFLOG.h> | 14 | #include <linux/netfilter/xt_NFLOG.h> |
15 | #include <net/netfilter/nf_log.h> | 15 | #include <net/netfilter/nf_log.h> |
16 | #include <net/netfilter/nfnetlink_log.h> | ||
16 | 17 | ||
17 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 18 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
18 | MODULE_DESCRIPTION("Xtables: packet logging to netlink using NFLOG"); | 19 | MODULE_DESCRIPTION("Xtables: packet logging to netlink using NFLOG"); |
@@ -31,8 +32,8 @@ nflog_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
31 | li.u.ulog.group = info->group; | 32 | li.u.ulog.group = info->group; |
32 | li.u.ulog.qthreshold = info->threshold; | 33 | li.u.ulog.qthreshold = info->threshold; |
33 | 34 | ||
34 | nf_log_packet(par->family, par->hooknum, skb, par->in, | 35 | nfulnl_log_packet(par->family, par->hooknum, skb, par->in, |
35 | par->out, &li, "%s", info->prefix); | 36 | par->out, &li, info->prefix); |
36 | return XT_CONTINUE; | 37 | return XT_CONTINUE; |
37 | } | 38 | } |
38 | 39 | ||
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 3c3dd22b1d0..fe80b614a40 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -72,9 +72,6 @@ struct recent_entry { | |||
72 | struct recent_table { | 72 | struct recent_table { |
73 | struct list_head list; | 73 | struct list_head list; |
74 | char name[XT_RECENT_NAME_LEN]; | 74 | char name[XT_RECENT_NAME_LEN]; |
75 | #ifdef CONFIG_PROC_FS | ||
76 | struct proc_dir_entry *proc_old, *proc; | ||
77 | #endif | ||
78 | unsigned int refcnt; | 75 | unsigned int refcnt; |
79 | unsigned int entries; | 76 | unsigned int entries; |
80 | struct list_head lru_list; | 77 | struct list_head lru_list; |
@@ -284,6 +281,9 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) | |||
284 | { | 281 | { |
285 | const struct xt_recent_mtinfo *info = par->matchinfo; | 282 | const struct xt_recent_mtinfo *info = par->matchinfo; |
286 | struct recent_table *t; | 283 | struct recent_table *t; |
284 | #ifdef CONFIG_PROC_FS | ||
285 | struct proc_dir_entry *pde; | ||
286 | #endif | ||
287 | unsigned i; | 287 | unsigned i; |
288 | bool ret = false; | 288 | bool ret = false; |
289 | 289 | ||
@@ -318,25 +318,25 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) | |||
318 | for (i = 0; i < ip_list_hash_size; i++) | 318 | for (i = 0; i < ip_list_hash_size; i++) |
319 | INIT_LIST_HEAD(&t->iphash[i]); | 319 | INIT_LIST_HEAD(&t->iphash[i]); |
320 | #ifdef CONFIG_PROC_FS | 320 | #ifdef CONFIG_PROC_FS |
321 | t->proc = proc_create_data(t->name, ip_list_perms, recent_proc_dir, | 321 | pde = proc_create_data(t->name, ip_list_perms, recent_proc_dir, |
322 | &recent_mt_fops, t); | 322 | &recent_mt_fops, t); |
323 | if (t->proc == NULL) { | 323 | if (pde == NULL) { |
324 | kfree(t); | 324 | kfree(t); |
325 | goto out; | 325 | goto out; |
326 | } | 326 | } |
327 | pde->uid = ip_list_uid; | ||
328 | pde->gid = ip_list_gid; | ||
327 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | 329 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT |
328 | t->proc_old = proc_create_data(t->name, ip_list_perms, proc_old_dir, | 330 | pde = proc_create_data(t->name, ip_list_perms, proc_old_dir, |
329 | &recent_old_fops, t); | 331 | &recent_old_fops, t); |
330 | if (t->proc_old == NULL) { | 332 | if (pde == NULL) { |
331 | remove_proc_entry(t->name, proc_old_dir); | 333 | remove_proc_entry(t->name, proc_old_dir); |
332 | kfree(t); | 334 | kfree(t); |
333 | goto out; | 335 | goto out; |
334 | } | 336 | } |
335 | t->proc_old->uid = ip_list_uid; | 337 | pde->uid = ip_list_uid; |
336 | t->proc_old->gid = ip_list_gid; | 338 | pde->gid = ip_list_gid; |
337 | #endif | 339 | #endif |
338 | t->proc->uid = ip_list_uid; | ||
339 | t->proc->gid = ip_list_gid; | ||
340 | #endif | 340 | #endif |
341 | spin_lock_bh(&recent_lock); | 341 | spin_lock_bh(&recent_lock); |
342 | list_add_tail(&t->list, &tables); | 342 | list_add_tail(&t->list, &tables); |