diff options
40 files changed, 514 insertions, 221 deletions
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index d45e29cd1cfb..e40ddb94b1af 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h | |||
@@ -300,7 +300,8 @@ struct ebt_table | |||
300 | 300 | ||
301 | #define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_replace)-1)) & \ | 301 | #define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_replace)-1)) & \ |
302 | ~(__alignof__(struct ebt_replace)-1)) | 302 | ~(__alignof__(struct ebt_replace)-1)) |
303 | extern int ebt_register_table(struct ebt_table *table); | 303 | extern struct ebt_table *ebt_register_table(struct net *net, |
304 | struct ebt_table *table); | ||
304 | extern void ebt_unregister_table(struct ebt_table *table); | 305 | extern void ebt_unregister_table(struct ebt_table *table); |
305 | extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb, | 306 | extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb, |
306 | const struct net_device *in, const struct net_device *out, | 307 | const struct net_device *in, const struct net_device *out, |
diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h index b9478a255301..1037fb2cd206 100644 --- a/include/linux/netfilter_ipv4/ipt_policy.h +++ b/include/linux/netfilter_ipv4/ipt_policy.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _IPT_POLICY_H | 1 | #ifndef _IPT_POLICY_H |
2 | #define _IPT_POLICY_H | 2 | #define _IPT_POLICY_H |
3 | 3 | ||
4 | #include <linux/netfilter/xt_policy.h> | ||
5 | |||
4 | #define IPT_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM | 6 | #define IPT_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM |
5 | 7 | ||
6 | /* ipt_policy_flags */ | 8 | /* ipt_policy_flags */ |
diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h index 6bab3163d2fb..b1c449d7ec89 100644 --- a/include/linux/netfilter_ipv6/ip6t_policy.h +++ b/include/linux/netfilter_ipv6/ip6t_policy.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _IP6T_POLICY_H | 1 | #ifndef _IP6T_POLICY_H |
2 | #define _IP6T_POLICY_H | 2 | #define _IP6T_POLICY_H |
3 | 3 | ||
4 | #include <linux/netfilter/xt_policy.h> | ||
5 | |||
4 | #define IP6T_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM | 6 | #define IP6T_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM |
5 | 7 | ||
6 | /* ip6t_policy_flags */ | 8 | /* ip6t_policy_flags */ |
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index b76a8685b5b5..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 | ||
200 | extern void nf_conntrack_hash_insert(struct nf_conn *ct); | 200 | extern void nf_conntrack_hash_insert(struct nf_conn *ct); |
201 | 201 | ||
202 | extern void nf_conntrack_flush(struct net *net); | 202 | extern void nf_conntrack_flush(struct net *net, u32 pid, int report); |
203 | 203 | ||
204 | extern bool nf_ct_get_tuplepr(const struct sk_buff *skb, | 204 | extern 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, |
@@ -298,5 +298,8 @@ do { \ | |||
298 | local_bh_enable(); \ | 298 | local_bh_enable(); \ |
299 | } while (0) | 299 | } while (0) |
300 | 300 | ||
301 | #define MODULE_ALIAS_NFCT_HELPER(helper) \ | ||
302 | MODULE_ALIAS("nfct-helper-" helper) | ||
303 | |||
301 | #endif /* __KERNEL__ */ | 304 | #endif /* __KERNEL__ */ |
302 | #endif /* _NF_CONNTRACK_H */ | 305 | #endif /* _NF_CONNTRACK_H */ |
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 */ | ||
21 | struct nf_ct_event { | ||
22 | struct nf_conn *ct; | ||
23 | u32 pid; | ||
24 | int report; | ||
25 | }; | ||
26 | |||
20 | extern struct atomic_notifier_head nf_conntrack_chain; | 27 | extern struct atomic_notifier_head nf_conntrack_chain; |
21 | extern int nf_conntrack_register_notifier(struct notifier_block *nb); | 28 | extern int nf_conntrack_register_notifier(struct notifier_block *nb); |
22 | extern int nf_conntrack_unregister_notifier(struct notifier_block *nb); | 29 | extern 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 | ||
42 | static inline void nf_conntrack_event(enum ip_conntrack_events event, | 49 | static inline void |
43 | struct nf_conn *ct) | 50 | nf_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 | ||
64 | static inline void | ||
65 | nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) | ||
66 | { | ||
67 | nf_conntrack_event_report(event, ct, 0, 0); | ||
68 | } | ||
69 | |||
70 | struct nf_exp_event { | ||
71 | struct nf_conntrack_expect *exp; | ||
72 | u32 pid; | ||
73 | int report; | ||
74 | }; | ||
75 | |||
49 | extern struct atomic_notifier_head nf_ct_expect_chain; | 76 | extern struct atomic_notifier_head nf_ct_expect_chain; |
50 | extern int nf_ct_expect_register_notifier(struct notifier_block *nb); | 77 | extern int nf_ct_expect_register_notifier(struct notifier_block *nb); |
51 | extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb); | 78 | extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb); |
52 | 79 | ||
53 | static inline void | 80 | static inline void |
81 | nf_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 | |||
94 | static inline void | ||
54 | nf_ct_expect_event(enum ip_conntrack_expect_events event, | 95 | nf_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 | ||
60 | extern int nf_conntrack_ecache_init(struct net *net); | 101 | extern 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) {} |
67 | static inline void nf_conntrack_event(enum ip_conntrack_events event, | 108 | static inline void nf_conntrack_event(enum ip_conntrack_events event, |
68 | struct nf_conn *ct) {} | 109 | struct nf_conn *ct) {} |
110 | static inline void nf_conntrack_event_report(enum ip_conntrack_events event, | ||
111 | struct nf_conn *ct, | ||
112 | u32 pid, | ||
113 | int report) {} | ||
69 | static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} | 114 | static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} |
70 | static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, | 115 | static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, |
71 | struct nf_conntrack_expect *exp) {} | 116 | struct nf_conntrack_expect *exp) {} |
117 | static 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) {} | ||
72 | static inline void nf_ct_event_cache_flush(struct net *net) {} | 121 | static inline void nf_ct_event_cache_flush(struct net *net) {} |
73 | 122 | ||
74 | static inline int nf_conntrack_ecache_init(struct net *net) | 123 | static 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 *); |
101 | void nf_ct_expect_put(struct nf_conntrack_expect *exp); | 101 | void nf_ct_expect_put(struct nf_conntrack_expect *exp); |
102 | int nf_ct_expect_related(struct nf_conntrack_expect *expect); | 102 | int nf_ct_expect_related(struct nf_conntrack_expect *expect); |
103 | int 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/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index f8060ab5a083..66d65a7caa39 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h | |||
@@ -39,9 +39,6 @@ struct nf_conntrack_helper | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | extern struct nf_conntrack_helper * | 41 | extern struct nf_conntrack_helper * |
42 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple); | ||
43 | |||
44 | extern struct nf_conntrack_helper * | ||
45 | __nf_conntrack_helper_find_byname(const char *name); | 42 | __nf_conntrack_helper_find_byname(const char *name); |
46 | 43 | ||
47 | extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); | 44 | extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); |
@@ -49,6 +46,8 @@ extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); | |||
49 | 46 | ||
50 | extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); | 47 | extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); |
51 | 48 | ||
49 | extern int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags); | ||
50 | |||
52 | static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) | 51 | static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) |
53 | { | 52 | { |
54 | return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); | 53 | return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); |
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 7f2f43c77284..debdaf75cecf 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h | |||
@@ -129,7 +129,7 @@ extern const struct nla_policy nf_ct_port_nla_policy[]; | |||
129 | && net_ratelimit()) | 129 | && net_ratelimit()) |
130 | #endif | 130 | #endif |
131 | #else | 131 | #else |
132 | #define LOG_INVALID(net, proto) 0 | 132 | static inline int LOG_INVALID(struct net *net, int proto) { return 0; } |
133 | #endif /* CONFIG_SYSCTL */ | 133 | #endif /* CONFIG_SYSCTL */ |
134 | 134 | ||
135 | #endif /*_NF_CONNTRACK_PROTOCOL_H*/ | 135 | #endif /*_NF_CONNTRACK_PROTOCOL_H*/ |
diff --git a/include/net/netfilter/nfnetlink_log.h b/include/net/netfilter/nfnetlink_log.h new file mode 100644 index 000000000000..b0569ff0775e --- /dev/null +++ b/include/net/netfilter/nfnetlink_log.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _KER_NFNETLINK_LOG_H | ||
2 | #define _KER_NFNETLINK_LOG_H | ||
3 | |||
4 | void | ||
5 | nfulnl_log_packet(u_int8_t pf, | ||
6 | unsigned int hooknum, | ||
7 | const struct sk_buff *skb, | ||
8 | const struct net_device *in, | ||
9 | const struct net_device *out, | ||
10 | const struct nf_loginfo *li_user, | ||
11 | const char *prefix); | ||
12 | |||
13 | #endif /* _KER_NFNETLINK_LOG_H */ | ||
14 | |||
diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h index b8093971ccb4..9554a644a8f8 100644 --- a/include/net/netns/x_tables.h +++ b/include/net/netns/x_tables.h | |||
@@ -4,7 +4,12 @@ | |||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <linux/netfilter.h> | 5 | #include <linux/netfilter.h> |
6 | 6 | ||
7 | struct ebt_table; | ||
8 | |||
7 | struct netns_xt { | 9 | struct netns_xt { |
8 | struct list_head tables[NFPROTO_NUMPROTO]; | 10 | struct list_head tables[NFPROTO_NUMPROTO]; |
11 | struct ebt_table *broute_table; | ||
12 | struct ebt_table *frame_filter; | ||
13 | struct ebt_table *frame_nat; | ||
9 | }; | 14 | }; |
10 | #endif | 15 | #endif |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 274194b78247..a65e43a17fbb 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -369,7 +369,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
369 | if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev)) | 369 | if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev)) |
370 | goto free_skb; | 370 | goto free_skb; |
371 | 371 | ||
372 | if (!ip_route_output_key(&init_net, &rt, &fl)) { | 372 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { |
373 | /* - Bridged-and-DNAT'ed traffic doesn't | 373 | /* - Bridged-and-DNAT'ed traffic doesn't |
374 | * require ip_forwarding. */ | 374 | * require ip_forwarding. */ |
375 | if (((struct dst_entry *)rt)->dev == dev) { | 375 | if (((struct dst_entry *)rt)->dev == dev) { |
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index 246626bb0c87..8604dfc1fc3b 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c | |||
@@ -56,29 +56,47 @@ static int ebt_broute(struct sk_buff *skb) | |||
56 | int ret; | 56 | int ret; |
57 | 57 | ||
58 | ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, | 58 | ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, |
59 | &broute_table); | 59 | dev_net(skb->dev)->xt.broute_table); |
60 | if (ret == NF_DROP) | 60 | if (ret == NF_DROP) |
61 | return 1; /* route it */ | 61 | return 1; /* route it */ |
62 | return 0; /* bridge it */ | 62 | return 0; /* bridge it */ |
63 | } | 63 | } |
64 | 64 | ||
65 | static int __net_init broute_net_init(struct net *net) | ||
66 | { | ||
67 | net->xt.broute_table = ebt_register_table(net, &broute_table); | ||
68 | if (IS_ERR(net->xt.broute_table)) | ||
69 | return PTR_ERR(net->xt.broute_table); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static void __net_exit broute_net_exit(struct net *net) | ||
74 | { | ||
75 | ebt_unregister_table(net->xt.broute_table); | ||
76 | } | ||
77 | |||
78 | static struct pernet_operations broute_net_ops = { | ||
79 | .init = broute_net_init, | ||
80 | .exit = broute_net_exit, | ||
81 | }; | ||
82 | |||
65 | static int __init ebtable_broute_init(void) | 83 | static int __init ebtable_broute_init(void) |
66 | { | 84 | { |
67 | int ret; | 85 | int ret; |
68 | 86 | ||
69 | ret = ebt_register_table(&broute_table); | 87 | ret = register_pernet_subsys(&broute_net_ops); |
70 | if (ret < 0) | 88 | if (ret < 0) |
71 | return ret; | 89 | return ret; |
72 | /* see br_input.c */ | 90 | /* see br_input.c */ |
73 | rcu_assign_pointer(br_should_route_hook, ebt_broute); | 91 | rcu_assign_pointer(br_should_route_hook, ebt_broute); |
74 | return ret; | 92 | return 0; |
75 | } | 93 | } |
76 | 94 | ||
77 | static void __exit ebtable_broute_fini(void) | 95 | static void __exit ebtable_broute_fini(void) |
78 | { | 96 | { |
79 | rcu_assign_pointer(br_should_route_hook, NULL); | 97 | rcu_assign_pointer(br_should_route_hook, NULL); |
80 | synchronize_net(); | 98 | synchronize_net(); |
81 | ebt_unregister_table(&broute_table); | 99 | unregister_pernet_subsys(&broute_net_ops); |
82 | } | 100 | } |
83 | 101 | ||
84 | module_init(ebtable_broute_init); | 102 | module_init(ebtable_broute_init); |
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 1a58af51a2e2..2b2e8040a9c6 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
@@ -61,29 +61,36 @@ static struct ebt_table frame_filter = | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | static unsigned int | 63 | static unsigned int |
64 | ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, | 64 | ebt_in_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, |
65 | const struct net_device *out, int (*okfn)(struct sk_buff *)) | 65 | const struct net_device *out, int (*okfn)(struct sk_buff *)) |
66 | { | 66 | { |
67 | return ebt_do_table(hook, skb, in, out, &frame_filter); | 67 | return ebt_do_table(hook, skb, in, out, dev_net(in)->xt.frame_filter); |
68 | } | ||
69 | |||
70 | static unsigned int | ||
71 | ebt_out_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, | ||
72 | const struct net_device *out, int (*okfn)(struct sk_buff *)) | ||
73 | { | ||
74 | return ebt_do_table(hook, skb, in, out, dev_net(out)->xt.frame_filter); | ||
68 | } | 75 | } |
69 | 76 | ||
70 | static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { | 77 | static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { |
71 | { | 78 | { |
72 | .hook = ebt_hook, | 79 | .hook = ebt_in_hook, |
73 | .owner = THIS_MODULE, | 80 | .owner = THIS_MODULE, |
74 | .pf = PF_BRIDGE, | 81 | .pf = PF_BRIDGE, |
75 | .hooknum = NF_BR_LOCAL_IN, | 82 | .hooknum = NF_BR_LOCAL_IN, |
76 | .priority = NF_BR_PRI_FILTER_BRIDGED, | 83 | .priority = NF_BR_PRI_FILTER_BRIDGED, |
77 | }, | 84 | }, |
78 | { | 85 | { |
79 | .hook = ebt_hook, | 86 | .hook = ebt_in_hook, |
80 | .owner = THIS_MODULE, | 87 | .owner = THIS_MODULE, |
81 | .pf = PF_BRIDGE, | 88 | .pf = PF_BRIDGE, |
82 | .hooknum = NF_BR_FORWARD, | 89 | .hooknum = NF_BR_FORWARD, |
83 | .priority = NF_BR_PRI_FILTER_BRIDGED, | 90 | .priority = NF_BR_PRI_FILTER_BRIDGED, |
84 | }, | 91 | }, |
85 | { | 92 | { |
86 | .hook = ebt_hook, | 93 | .hook = ebt_out_hook, |
87 | .owner = THIS_MODULE, | 94 | .owner = THIS_MODULE, |
88 | .pf = PF_BRIDGE, | 95 | .pf = PF_BRIDGE, |
89 | .hooknum = NF_BR_LOCAL_OUT, | 96 | .hooknum = NF_BR_LOCAL_OUT, |
@@ -91,23 +98,41 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { | |||
91 | }, | 98 | }, |
92 | }; | 99 | }; |
93 | 100 | ||
101 | static int __net_init frame_filter_net_init(struct net *net) | ||
102 | { | ||
103 | net->xt.frame_filter = ebt_register_table(net, &frame_filter); | ||
104 | if (IS_ERR(net->xt.frame_filter)) | ||
105 | return PTR_ERR(net->xt.frame_filter); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void __net_exit frame_filter_net_exit(struct net *net) | ||
110 | { | ||
111 | ebt_unregister_table(net->xt.frame_filter); | ||
112 | } | ||
113 | |||
114 | static struct pernet_operations frame_filter_net_ops = { | ||
115 | .init = frame_filter_net_init, | ||
116 | .exit = frame_filter_net_exit, | ||
117 | }; | ||
118 | |||
94 | static int __init ebtable_filter_init(void) | 119 | static int __init ebtable_filter_init(void) |
95 | { | 120 | { |
96 | int ret; | 121 | int ret; |
97 | 122 | ||
98 | ret = ebt_register_table(&frame_filter); | 123 | ret = register_pernet_subsys(&frame_filter_net_ops); |
99 | if (ret < 0) | 124 | if (ret < 0) |
100 | return ret; | 125 | return ret; |
101 | ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); | 126 | ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); |
102 | if (ret < 0) | 127 | if (ret < 0) |
103 | ebt_unregister_table(&frame_filter); | 128 | unregister_pernet_subsys(&frame_filter_net_ops); |
104 | return ret; | 129 | return ret; |
105 | } | 130 | } |
106 | 131 | ||
107 | static void __exit ebtable_filter_fini(void) | 132 | static void __exit ebtable_filter_fini(void) |
108 | { | 133 | { |
109 | nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); | 134 | nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); |
110 | ebt_unregister_table(&frame_filter); | 135 | unregister_pernet_subsys(&frame_filter_net_ops); |
111 | } | 136 | } |
112 | 137 | ||
113 | module_init(ebtable_filter_init); | 138 | module_init(ebtable_filter_init); |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index f60c1e78e575..3fe1ae87e35f 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
@@ -61,36 +61,36 @@ static struct ebt_table frame_nat = | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | static unsigned int | 63 | static unsigned int |
64 | ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in | 64 | ebt_nat_in(unsigned int hook, struct sk_buff *skb, const struct net_device *in |
65 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) | 65 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) |
66 | { | 66 | { |
67 | return ebt_do_table(hook, skb, in, out, &frame_nat); | 67 | return ebt_do_table(hook, skb, in, out, dev_net(in)->xt.frame_nat); |
68 | } | 68 | } |
69 | 69 | ||
70 | static unsigned int | 70 | static unsigned int |
71 | ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in | 71 | ebt_nat_out(unsigned int hook, struct sk_buff *skb, const struct net_device *in |
72 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) | 72 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) |
73 | { | 73 | { |
74 | return ebt_do_table(hook, skb, in, out, &frame_nat); | 74 | return ebt_do_table(hook, skb, in, out, dev_net(out)->xt.frame_nat); |
75 | } | 75 | } |
76 | 76 | ||
77 | static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { | 77 | static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { |
78 | { | 78 | { |
79 | .hook = ebt_nat_dst, | 79 | .hook = ebt_nat_out, |
80 | .owner = THIS_MODULE, | 80 | .owner = THIS_MODULE, |
81 | .pf = PF_BRIDGE, | 81 | .pf = PF_BRIDGE, |
82 | .hooknum = NF_BR_LOCAL_OUT, | 82 | .hooknum = NF_BR_LOCAL_OUT, |
83 | .priority = NF_BR_PRI_NAT_DST_OTHER, | 83 | .priority = NF_BR_PRI_NAT_DST_OTHER, |
84 | }, | 84 | }, |
85 | { | 85 | { |
86 | .hook = ebt_nat_src, | 86 | .hook = ebt_nat_out, |
87 | .owner = THIS_MODULE, | 87 | .owner = THIS_MODULE, |
88 | .pf = PF_BRIDGE, | 88 | .pf = PF_BRIDGE, |
89 | .hooknum = NF_BR_POST_ROUTING, | 89 | .hooknum = NF_BR_POST_ROUTING, |
90 | .priority = NF_BR_PRI_NAT_SRC, | 90 | .priority = NF_BR_PRI_NAT_SRC, |
91 | }, | 91 | }, |
92 | { | 92 | { |
93 | .hook = ebt_nat_dst, | 93 | .hook = ebt_nat_in, |
94 | .owner = THIS_MODULE, | 94 | .owner = THIS_MODULE, |
95 | .pf = PF_BRIDGE, | 95 | .pf = PF_BRIDGE, |
96 | .hooknum = NF_BR_PRE_ROUTING, | 96 | .hooknum = NF_BR_PRE_ROUTING, |
@@ -98,23 +98,41 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { | |||
98 | }, | 98 | }, |
99 | }; | 99 | }; |
100 | 100 | ||
101 | static int __net_init frame_nat_net_init(struct net *net) | ||
102 | { | ||
103 | net->xt.frame_nat = ebt_register_table(net, &frame_nat); | ||
104 | if (IS_ERR(net->xt.frame_nat)) | ||
105 | return PTR_ERR(net->xt.frame_nat); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void __net_exit frame_nat_net_exit(struct net *net) | ||
110 | { | ||
111 | ebt_unregister_table(net->xt.frame_nat); | ||
112 | } | ||
113 | |||
114 | static struct pernet_operations frame_nat_net_ops = { | ||
115 | .init = frame_nat_net_init, | ||
116 | .exit = frame_nat_net_exit, | ||
117 | }; | ||
118 | |||
101 | static int __init ebtable_nat_init(void) | 119 | static int __init ebtable_nat_init(void) |
102 | { | 120 | { |
103 | int ret; | 121 | int ret; |
104 | 122 | ||
105 | ret = ebt_register_table(&frame_nat); | 123 | ret = register_pernet_subsys(&frame_nat_net_ops); |
106 | if (ret < 0) | 124 | if (ret < 0) |
107 | return ret; | 125 | return ret; |
108 | ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); | 126 | ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); |
109 | if (ret < 0) | 127 | if (ret < 0) |
110 | ebt_unregister_table(&frame_nat); | 128 | unregister_pernet_subsys(&frame_nat_net_ops); |
111 | return ret; | 129 | return ret; |
112 | } | 130 | } |
113 | 131 | ||
114 | static void __exit ebtable_nat_fini(void) | 132 | static void __exit ebtable_nat_fini(void) |
115 | { | 133 | { |
116 | nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); | 134 | nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); |
117 | ebt_unregister_table(&frame_nat); | 135 | unregister_pernet_subsys(&frame_nat_net_ops); |
118 | } | 136 | } |
119 | 137 | ||
120 | module_init(ebtable_nat_init); | 138 | module_init(ebtable_nat_init); |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 0fa208e86405..fa108c46e851 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -55,7 +55,6 @@ | |||
55 | 55 | ||
56 | 56 | ||
57 | static DEFINE_MUTEX(ebt_mutex); | 57 | static DEFINE_MUTEX(ebt_mutex); |
58 | static LIST_HEAD(ebt_tables); | ||
59 | 58 | ||
60 | static struct xt_target ebt_standard_target = { | 59 | static struct xt_target ebt_standard_target = { |
61 | .name = "standard", | 60 | .name = "standard", |
@@ -315,9 +314,11 @@ find_inlist_lock(struct list_head *head, const char *name, const char *prefix, | |||
315 | } | 314 | } |
316 | 315 | ||
317 | static inline struct ebt_table * | 316 | static inline struct ebt_table * |
318 | find_table_lock(const char *name, int *error, struct mutex *mutex) | 317 | find_table_lock(struct net *net, const char *name, int *error, |
318 | struct mutex *mutex) | ||
319 | { | 319 | { |
320 | return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex); | 320 | return find_inlist_lock(&net->xt.tables[NFPROTO_BRIDGE], name, |
321 | "ebtable_", error, mutex); | ||
321 | } | 322 | } |
322 | 323 | ||
323 | static inline int | 324 | static inline int |
@@ -944,7 +945,7 @@ static void get_counters(struct ebt_counter *oldcounters, | |||
944 | } | 945 | } |
945 | 946 | ||
946 | /* replace the table */ | 947 | /* replace the table */ |
947 | static int do_replace(void __user *user, unsigned int len) | 948 | static int do_replace(struct net *net, void __user *user, unsigned int len) |
948 | { | 949 | { |
949 | int ret, i, countersize; | 950 | int ret, i, countersize; |
950 | struct ebt_table_info *newinfo; | 951 | struct ebt_table_info *newinfo; |
@@ -1016,7 +1017,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1016 | if (ret != 0) | 1017 | if (ret != 0) |
1017 | goto free_counterstmp; | 1018 | goto free_counterstmp; |
1018 | 1019 | ||
1019 | t = find_table_lock(tmp.name, &ret, &ebt_mutex); | 1020 | t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); |
1020 | if (!t) { | 1021 | if (!t) { |
1021 | ret = -ENOENT; | 1022 | ret = -ENOENT; |
1022 | goto free_iterate; | 1023 | goto free_iterate; |
@@ -1097,7 +1098,7 @@ free_newinfo: | |||
1097 | return ret; | 1098 | return ret; |
1098 | } | 1099 | } |
1099 | 1100 | ||
1100 | int ebt_register_table(struct ebt_table *table) | 1101 | struct ebt_table *ebt_register_table(struct net *net, struct ebt_table *table) |
1101 | { | 1102 | { |
1102 | struct ebt_table_info *newinfo; | 1103 | struct ebt_table_info *newinfo; |
1103 | struct ebt_table *t; | 1104 | struct ebt_table *t; |
@@ -1109,14 +1110,21 @@ int ebt_register_table(struct ebt_table *table) | |||
1109 | repl->entries_size == 0 || | 1110 | repl->entries_size == 0 || |
1110 | repl->counters || table->private) { | 1111 | repl->counters || table->private) { |
1111 | BUGPRINT("Bad table data for ebt_register_table!!!\n"); | 1112 | BUGPRINT("Bad table data for ebt_register_table!!!\n"); |
1112 | return -EINVAL; | 1113 | return ERR_PTR(-EINVAL); |
1114 | } | ||
1115 | |||
1116 | /* Don't add one table to multiple lists. */ | ||
1117 | table = kmemdup(table, sizeof(struct ebt_table), GFP_KERNEL); | ||
1118 | if (!table) { | ||
1119 | ret = -ENOMEM; | ||
1120 | goto out; | ||
1113 | } | 1121 | } |
1114 | 1122 | ||
1115 | countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids; | 1123 | countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids; |
1116 | newinfo = vmalloc(sizeof(*newinfo) + countersize); | 1124 | newinfo = vmalloc(sizeof(*newinfo) + countersize); |
1117 | ret = -ENOMEM; | 1125 | ret = -ENOMEM; |
1118 | if (!newinfo) | 1126 | if (!newinfo) |
1119 | return -ENOMEM; | 1127 | goto free_table; |
1120 | 1128 | ||
1121 | p = vmalloc(repl->entries_size); | 1129 | p = vmalloc(repl->entries_size); |
1122 | if (!p) | 1130 | if (!p) |
@@ -1148,7 +1156,7 @@ int ebt_register_table(struct ebt_table *table) | |||
1148 | 1156 | ||
1149 | if (table->check && table->check(newinfo, table->valid_hooks)) { | 1157 | if (table->check && table->check(newinfo, table->valid_hooks)) { |
1150 | BUGPRINT("The table doesn't like its own initial data, lol\n"); | 1158 | BUGPRINT("The table doesn't like its own initial data, lol\n"); |
1151 | return -EINVAL; | 1159 | return ERR_PTR(-EINVAL); |
1152 | } | 1160 | } |
1153 | 1161 | ||
1154 | table->private = newinfo; | 1162 | table->private = newinfo; |
@@ -1157,7 +1165,7 @@ int ebt_register_table(struct ebt_table *table) | |||
1157 | if (ret != 0) | 1165 | if (ret != 0) |
1158 | goto free_chainstack; | 1166 | goto free_chainstack; |
1159 | 1167 | ||
1160 | list_for_each_entry(t, &ebt_tables, list) { | 1168 | list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { |
1161 | if (strcmp(t->name, table->name) == 0) { | 1169 | if (strcmp(t->name, table->name) == 0) { |
1162 | ret = -EEXIST; | 1170 | ret = -EEXIST; |
1163 | BUGPRINT("Table name already exists\n"); | 1171 | BUGPRINT("Table name already exists\n"); |
@@ -1170,9 +1178,9 @@ int ebt_register_table(struct ebt_table *table) | |||
1170 | ret = -ENOENT; | 1178 | ret = -ENOENT; |
1171 | goto free_unlock; | 1179 | goto free_unlock; |
1172 | } | 1180 | } |
1173 | list_add(&table->list, &ebt_tables); | 1181 | list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]); |
1174 | mutex_unlock(&ebt_mutex); | 1182 | mutex_unlock(&ebt_mutex); |
1175 | return 0; | 1183 | return table; |
1176 | free_unlock: | 1184 | free_unlock: |
1177 | mutex_unlock(&ebt_mutex); | 1185 | mutex_unlock(&ebt_mutex); |
1178 | free_chainstack: | 1186 | free_chainstack: |
@@ -1184,7 +1192,10 @@ free_chainstack: | |||
1184 | vfree(newinfo->entries); | 1192 | vfree(newinfo->entries); |
1185 | free_newinfo: | 1193 | free_newinfo: |
1186 | vfree(newinfo); | 1194 | vfree(newinfo); |
1187 | return ret; | 1195 | free_table: |
1196 | kfree(table); | ||
1197 | out: | ||
1198 | return ERR_PTR(ret); | ||
1188 | } | 1199 | } |
1189 | 1200 | ||
1190 | void ebt_unregister_table(struct ebt_table *table) | 1201 | void ebt_unregister_table(struct ebt_table *table) |
@@ -1198,6 +1209,10 @@ void ebt_unregister_table(struct ebt_table *table) | |||
1198 | mutex_lock(&ebt_mutex); | 1209 | mutex_lock(&ebt_mutex); |
1199 | list_del(&table->list); | 1210 | list_del(&table->list); |
1200 | mutex_unlock(&ebt_mutex); | 1211 | mutex_unlock(&ebt_mutex); |
1212 | EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size, | ||
1213 | ebt_cleanup_entry, NULL); | ||
1214 | if (table->private->nentries) | ||
1215 | module_put(table->me); | ||
1201 | vfree(table->private->entries); | 1216 | vfree(table->private->entries); |
1202 | if (table->private->chainstack) { | 1217 | if (table->private->chainstack) { |
1203 | for_each_possible_cpu(i) | 1218 | for_each_possible_cpu(i) |
@@ -1205,10 +1220,11 @@ void ebt_unregister_table(struct ebt_table *table) | |||
1205 | vfree(table->private->chainstack); | 1220 | vfree(table->private->chainstack); |
1206 | } | 1221 | } |
1207 | vfree(table->private); | 1222 | vfree(table->private); |
1223 | kfree(table); | ||
1208 | } | 1224 | } |
1209 | 1225 | ||
1210 | /* userspace just supplied us with counters */ | 1226 | /* userspace just supplied us with counters */ |
1211 | static int update_counters(void __user *user, unsigned int len) | 1227 | static int update_counters(struct net *net, void __user *user, unsigned int len) |
1212 | { | 1228 | { |
1213 | int i, ret; | 1229 | int i, ret; |
1214 | struct ebt_counter *tmp; | 1230 | struct ebt_counter *tmp; |
@@ -1228,7 +1244,7 @@ static int update_counters(void __user *user, unsigned int len) | |||
1228 | return -ENOMEM; | 1244 | return -ENOMEM; |
1229 | } | 1245 | } |
1230 | 1246 | ||
1231 | t = find_table_lock(hlp.name, &ret, &ebt_mutex); | 1247 | t = find_table_lock(net, hlp.name, &ret, &ebt_mutex); |
1232 | if (!t) | 1248 | if (!t) |
1233 | goto free_tmp; | 1249 | goto free_tmp; |
1234 | 1250 | ||
@@ -1386,10 +1402,10 @@ static int do_ebt_set_ctl(struct sock *sk, | |||
1386 | 1402 | ||
1387 | switch(cmd) { | 1403 | switch(cmd) { |
1388 | case EBT_SO_SET_ENTRIES: | 1404 | case EBT_SO_SET_ENTRIES: |
1389 | ret = do_replace(user, len); | 1405 | ret = do_replace(sock_net(sk), user, len); |
1390 | break; | 1406 | break; |
1391 | case EBT_SO_SET_COUNTERS: | 1407 | case EBT_SO_SET_COUNTERS: |
1392 | ret = update_counters(user, len); | 1408 | ret = update_counters(sock_net(sk), user, len); |
1393 | break; | 1409 | break; |
1394 | default: | 1410 | default: |
1395 | ret = -EINVAL; | 1411 | ret = -EINVAL; |
@@ -1406,7 +1422,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1406 | if (copy_from_user(&tmp, user, sizeof(tmp))) | 1422 | if (copy_from_user(&tmp, user, sizeof(tmp))) |
1407 | return -EFAULT; | 1423 | return -EFAULT; |
1408 | 1424 | ||
1409 | t = find_table_lock(tmp.name, &ret, &ebt_mutex); | 1425 | t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex); |
1410 | if (!t) | 1426 | if (!t) |
1411 | return ret; | 1427 | return ret; |
1412 | 1428 | ||
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index c99eecf89da5..fdf6811c31a2 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -125,6 +125,7 @@ struct ip_rt_info { | |||
125 | __be32 daddr; | 125 | __be32 daddr; |
126 | __be32 saddr; | 126 | __be32 saddr; |
127 | u_int8_t tos; | 127 | u_int8_t tos; |
128 | u_int32_t mark; | ||
128 | }; | 129 | }; |
129 | 130 | ||
130 | static void nf_ip_saveroute(const struct sk_buff *skb, | 131 | static void nf_ip_saveroute(const struct sk_buff *skb, |
@@ -138,6 +139,7 @@ static void nf_ip_saveroute(const struct sk_buff *skb, | |||
138 | rt_info->tos = iph->tos; | 139 | rt_info->tos = iph->tos; |
139 | rt_info->daddr = iph->daddr; | 140 | rt_info->daddr = iph->daddr; |
140 | rt_info->saddr = iph->saddr; | 141 | rt_info->saddr = iph->saddr; |
142 | rt_info->mark = skb->mark; | ||
141 | } | 143 | } |
142 | } | 144 | } |
143 | 145 | ||
@@ -150,6 +152,7 @@ static int nf_ip_reroute(struct sk_buff *skb, | |||
150 | const struct iphdr *iph = ip_hdr(skb); | 152 | const struct iphdr *iph = ip_hdr(skb); |
151 | 153 | ||
152 | if (!(iph->tos == rt_info->tos | 154 | if (!(iph->tos == rt_info->tos |
155 | && skb->mark == rt_info->mark | ||
153 | && iph->daddr == rt_info->daddr | 156 | && iph->daddr == rt_info->daddr |
154 | && iph->saddr == rt_info->saddr)) | 157 | && iph->saddr == rt_info->saddr)) |
155 | return ip_route_me_harder(skb, RTN_UNSPEC); | 158 | return ip_route_me_harder(skb, RTN_UNSPEC); |
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index bee3d117661a..e091187e864f 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
@@ -75,16 +75,6 @@ static unsigned int arpt_out_hook(unsigned int hook, | |||
75 | dev_net(out)->ipv4.arptable_filter); | 75 | dev_net(out)->ipv4.arptable_filter); |
76 | } | 76 | } |
77 | 77 | ||
78 | static unsigned int arpt_forward_hook(unsigned int hook, | ||
79 | struct sk_buff *skb, | ||
80 | const struct net_device *in, | ||
81 | const struct net_device *out, | ||
82 | int (*okfn)(struct sk_buff *)) | ||
83 | { | ||
84 | return arpt_do_table(skb, hook, in, out, | ||
85 | dev_net(in)->ipv4.arptable_filter); | ||
86 | } | ||
87 | |||
88 | static struct nf_hook_ops arpt_ops[] __read_mostly = { | 78 | static struct nf_hook_ops arpt_ops[] __read_mostly = { |
89 | { | 79 | { |
90 | .hook = arpt_in_hook, | 80 | .hook = arpt_in_hook, |
@@ -101,7 +91,7 @@ static struct nf_hook_ops arpt_ops[] __read_mostly = { | |||
101 | .priority = NF_IP_PRI_FILTER, | 91 | .priority = NF_IP_PRI_FILTER, |
102 | }, | 92 | }, |
103 | { | 93 | { |
104 | .hook = arpt_forward_hook, | 94 | .hook = arpt_in_hook, |
105 | .owner = THIS_MODULE, | 95 | .owner = THIS_MODULE, |
106 | .pf = NFPROTO_ARP, | 96 | .pf = NFPROTO_ARP, |
107 | .hooknum = NF_ARP_FORWARD, | 97 | .hooknum = NF_ARP_FORWARD, |
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index 88762f02779d..3b216be3bc9f 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c | |||
@@ -23,24 +23,25 @@ MODULE_LICENSE("GPL"); | |||
23 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 23 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
24 | MODULE_DESCRIPTION("Xtables: address type match for IPv4"); | 24 | MODULE_DESCRIPTION("Xtables: address type match for IPv4"); |
25 | 25 | ||
26 | static inline bool match_type(const struct net_device *dev, __be32 addr, | 26 | static inline bool match_type(struct net *net, const struct net_device *dev, |
27 | u_int16_t mask) | 27 | __be32 addr, u_int16_t mask) |
28 | { | 28 | { |
29 | return !!(mask & (1 << inet_dev_addr_type(&init_net, dev, addr))); | 29 | return !!(mask & (1 << inet_dev_addr_type(net, dev, addr))); |
30 | } | 30 | } |
31 | 31 | ||
32 | static bool | 32 | static bool |
33 | addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) | 33 | addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) |
34 | { | 34 | { |
35 | struct net *net = dev_net(par->in ? par->in : par->out); | ||
35 | const struct ipt_addrtype_info *info = par->matchinfo; | 36 | const struct ipt_addrtype_info *info = par->matchinfo; |
36 | const struct iphdr *iph = ip_hdr(skb); | 37 | const struct iphdr *iph = ip_hdr(skb); |
37 | bool ret = true; | 38 | bool ret = true; |
38 | 39 | ||
39 | if (info->source) | 40 | if (info->source) |
40 | ret &= match_type(NULL, iph->saddr, info->source) ^ | 41 | ret &= match_type(net, NULL, iph->saddr, info->source) ^ |
41 | info->invert_source; | 42 | info->invert_source; |
42 | if (info->dest) | 43 | if (info->dest) |
43 | ret &= match_type(NULL, iph->daddr, info->dest) ^ | 44 | ret &= match_type(net, NULL, iph->daddr, info->dest) ^ |
44 | info->invert_dest; | 45 | info->invert_dest; |
45 | 46 | ||
46 | return ret; | 47 | return ret; |
@@ -49,6 +50,7 @@ addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) | |||
49 | static bool | 50 | static bool |
50 | addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | 51 | addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) |
51 | { | 52 | { |
53 | struct net *net = dev_net(par->in ? par->in : par->out); | ||
52 | const struct ipt_addrtype_info_v1 *info = par->matchinfo; | 54 | const struct ipt_addrtype_info_v1 *info = par->matchinfo; |
53 | const struct iphdr *iph = ip_hdr(skb); | 55 | const struct iphdr *iph = ip_hdr(skb); |
54 | const struct net_device *dev = NULL; | 56 | const struct net_device *dev = NULL; |
@@ -60,10 +62,10 @@ addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | |||
60 | dev = par->out; | 62 | dev = par->out; |
61 | 63 | ||
62 | if (info->source) | 64 | if (info->source) |
63 | ret &= match_type(dev, iph->saddr, info->source) ^ | 65 | ret &= match_type(net, dev, iph->saddr, info->source) ^ |
64 | (info->flags & IPT_ADDRTYPE_INVERT_SOURCE); | 66 | (info->flags & IPT_ADDRTYPE_INVERT_SOURCE); |
65 | if (ret && info->dest) | 67 | if (ret && info->dest) |
66 | ret &= match_type(dev, iph->daddr, info->dest) ^ | 68 | ret &= match_type(net, dev, iph->daddr, info->dest) ^ |
67 | !!(info->flags & IPT_ADDRTYPE_INVERT_DEST); | 69 | !!(info->flags & IPT_ADDRTYPE_INVERT_DEST); |
68 | return ret; | 70 | return ret; |
69 | } | 71 | } |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index a4f1c3479e23..cf95469ab9f1 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
@@ -86,24 +86,6 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_target_param *par) | |||
86 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); | 86 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); |
87 | } | 87 | } |
88 | 88 | ||
89 | /* Before 2.6.11 we did implicit source NAT if required. Warn about change. */ | ||
90 | static void warn_if_extra_mangle(struct net *net, __be32 dstip, __be32 srcip) | ||
91 | { | ||
92 | static int warned = 0; | ||
93 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } }; | ||
94 | struct rtable *rt; | ||
95 | |||
96 | if (ip_route_output_key(net, &rt, &fl) != 0) | ||
97 | return; | ||
98 | |||
99 | if (rt->rt_src != srcip && !warned) { | ||
100 | printk("NAT: no longer support implicit source local NAT\n"); | ||
101 | printk("NAT: packet src %pI4 -> dst %pI4\n", &srcip, &dstip); | ||
102 | warned = 1; | ||
103 | } | ||
104 | ip_rt_put(rt); | ||
105 | } | ||
106 | |||
107 | static unsigned int | 89 | static unsigned int |
108 | ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par) | 90 | ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par) |
109 | { | 91 | { |
@@ -119,11 +101,6 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par) | |||
119 | /* Connection must be valid and new. */ | 101 | /* Connection must be valid and new. */ |
120 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | 102 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); |
121 | 103 | ||
122 | if (par->hooknum == NF_INET_LOCAL_OUT && | ||
123 | mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) | ||
124 | warn_if_extra_mangle(dev_net(par->out), ip_hdr(skb)->daddr, | ||
125 | mr->range[0].min_ip); | ||
126 | |||
127 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); | 104 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); |
128 | } | 105 | } |
129 | 106 | ||
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 627e21db65df..834cea69fb53 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -56,6 +56,7 @@ EXPORT_SYMBOL(ip6_route_me_harder); | |||
56 | struct ip6_rt_info { | 56 | struct ip6_rt_info { |
57 | struct in6_addr daddr; | 57 | struct in6_addr daddr; |
58 | struct in6_addr saddr; | 58 | struct in6_addr saddr; |
59 | u_int32_t mark; | ||
59 | }; | 60 | }; |
60 | 61 | ||
61 | static void nf_ip6_saveroute(const struct sk_buff *skb, | 62 | static void nf_ip6_saveroute(const struct sk_buff *skb, |
@@ -68,6 +69,7 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, | |||
68 | 69 | ||
69 | rt_info->daddr = iph->daddr; | 70 | rt_info->daddr = iph->daddr; |
70 | rt_info->saddr = iph->saddr; | 71 | rt_info->saddr = iph->saddr; |
72 | rt_info->mark = skb->mark; | ||
71 | } | 73 | } |
72 | } | 74 | } |
73 | 75 | ||
@@ -79,7 +81,8 @@ static int nf_ip6_reroute(struct sk_buff *skb, | |||
79 | if (entry->hook == NF_INET_LOCAL_OUT) { | 81 | if (entry->hook == NF_INET_LOCAL_OUT) { |
80 | struct ipv6hdr *iph = ipv6_hdr(skb); | 82 | struct ipv6hdr *iph = ipv6_hdr(skb); |
81 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || | 83 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || |
82 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) | 84 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) || |
85 | skb->mark != rt_info->mark) | ||
83 | return ip6_route_me_harder(skb); | 86 | return ip6_route_me_harder(skb); |
84 | } | 87 | } |
85 | return 0; | 88 | return 0; |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index b110a8a85a14..40d2e36d8fac 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -61,7 +61,7 @@ static struct xt_table packet_filter = { | |||
61 | 61 | ||
62 | /* The work comes in here from netfilter.c. */ | 62 | /* The work comes in here from netfilter.c. */ |
63 | static unsigned int | 63 | static unsigned int |
64 | ip6t_local_in_hook(unsigned int hook, | 64 | ip6t_in_hook(unsigned int hook, |
65 | struct sk_buff *skb, | 65 | struct sk_buff *skb, |
66 | const struct net_device *in, | 66 | const struct net_device *in, |
67 | const struct net_device *out, | 67 | const struct net_device *out, |
@@ -72,17 +72,6 @@ ip6t_local_in_hook(unsigned int hook, | |||
72 | } | 72 | } |
73 | 73 | ||
74 | static unsigned int | 74 | static unsigned int |
75 | ip6t_forward_hook(unsigned int hook, | ||
76 | struct sk_buff *skb, | ||
77 | const struct net_device *in, | ||
78 | const struct net_device *out, | ||
79 | int (*okfn)(struct sk_buff *)) | ||
80 | { | ||
81 | return ip6t_do_table(skb, hook, in, out, | ||
82 | dev_net(in)->ipv6.ip6table_filter); | ||
83 | } | ||
84 | |||
85 | static unsigned int | ||
86 | ip6t_local_out_hook(unsigned int hook, | 75 | ip6t_local_out_hook(unsigned int hook, |
87 | struct sk_buff *skb, | 76 | struct sk_buff *skb, |
88 | const struct net_device *in, | 77 | const struct net_device *in, |
@@ -105,14 +94,14 @@ ip6t_local_out_hook(unsigned int hook, | |||
105 | 94 | ||
106 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 95 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { |
107 | { | 96 | { |
108 | .hook = ip6t_local_in_hook, | 97 | .hook = ip6t_in_hook, |
109 | .owner = THIS_MODULE, | 98 | .owner = THIS_MODULE, |
110 | .pf = PF_INET6, | 99 | .pf = PF_INET6, |
111 | .hooknum = NF_INET_LOCAL_IN, | 100 | .hooknum = NF_INET_LOCAL_IN, |
112 | .priority = NF_IP6_PRI_FILTER, | 101 | .priority = NF_IP6_PRI_FILTER, |
113 | }, | 102 | }, |
114 | { | 103 | { |
115 | .hook = ip6t_forward_hook, | 104 | .hook = ip6t_in_hook, |
116 | .owner = THIS_MODULE, | 105 | .owner = THIS_MODULE, |
117 | .pf = PF_INET6, | 106 | .pf = PF_INET6, |
118 | .hooknum = NF_INET_FORWARD, | 107 | .hooknum = NF_INET_FORWARD, |
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 38aedeeaf4e1..4f8fcf498545 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 233fdd2d7d21..7e83f74cd5de 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 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 | ||
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 629500901bd4..00fecc385f9b 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 99bc803d1dd1..687bd633c3d7 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 c39b6a994133..a51bdac9f3a0 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 4d681a04447e..409c8be58e7c 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 08404e6755fb..5af4273b4668 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 5f4a6516b3b6..00e8c27130ff 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 1bc3001d1827..9e169ef2e854 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 4ab62ad85dd4..1b279f9d6bf3 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 c2bd457bc2f2..74e037901199 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 a94294b2b23c..dcfecbb81c46 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 6813f1c8863f..4b572163784b 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 f57f6e7a71ee..46e646b2e9b9 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 41e0105d3828..2770b4e57ea0 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 50e3a52d3b31..a57c5cf018ec 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 3c3dd22b1d06..fe80b614a400 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); |