diff options
author | David S. Miller <davem@davemloft.net> | 2012-11-16 12:42:43 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-16 12:42:43 -0500 |
commit | 545b29019c8959c805abfe8194d47e989f1a6e5f (patch) | |
tree | 120f88abf0b4b2317072579c667fddfccb930fe5 | |
parent | 130cd273d4a46a3011b1cc739f5d2af78779d666 (diff) | |
parent | d3976a53ce1f4763cb910d047e8763e4c696e5f7 (diff) |
Merge branch 'master' of git://1984.lsi.us.es/nf-next
Conflicts:
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
Minor conflict due to some IS_ENABLED conversions done
in net-next.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/uapi/linux/in6.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/netfilter_ipv6/ip6_tables.h | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_nat.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_nat.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 66 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_nfct.c | 2 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_xmit.c | 8 |
7 files changed, 77 insertions, 11 deletions
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h index 1e3159989958..f79c3721da6e 100644 --- a/include/uapi/linux/in6.h +++ b/include/uapi/linux/in6.h | |||
@@ -240,6 +240,7 @@ struct in6_flowlabel_req { | |||
240 | * | 240 | * |
241 | * IP6T_SO_GET_REVISION_MATCH 68 | 241 | * IP6T_SO_GET_REVISION_MATCH 68 |
242 | * IP6T_SO_GET_REVISION_TARGET 69 | 242 | * IP6T_SO_GET_REVISION_TARGET 69 |
243 | * IP6T_SO_ORIGINAL_DST 80 | ||
243 | */ | 244 | */ |
244 | 245 | ||
245 | /* RFC5014: Source address selection */ | 246 | /* RFC5014: Source address selection */ |
diff --git a/include/uapi/linux/netfilter_ipv6/ip6_tables.h b/include/uapi/linux/netfilter_ipv6/ip6_tables.h index bf1ef65cc582..649c68062dca 100644 --- a/include/uapi/linux/netfilter_ipv6/ip6_tables.h +++ b/include/uapi/linux/netfilter_ipv6/ip6_tables.h | |||
@@ -178,6 +178,9 @@ struct ip6t_error { | |||
178 | #define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 5) | 178 | #define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 5) |
179 | #define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET | 179 | #define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET |
180 | 180 | ||
181 | /* obtain original address if REDIRECT'd connection */ | ||
182 | #define IP6T_SO_ORIGINAL_DST 80 | ||
183 | |||
181 | /* ICMP matching stuff */ | 184 | /* ICMP matching stuff */ |
182 | struct ip6t_icmp { | 185 | struct ip6t_icmp { |
183 | __u8 type; /* type to match */ | 186 | __u8 type; /* type to match */ |
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index a82047282dbb..ac635a7b4416 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c | |||
@@ -276,9 +276,7 @@ static int __net_init iptable_nat_net_init(struct net *net) | |||
276 | return -ENOMEM; | 276 | return -ENOMEM; |
277 | net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl); | 277 | net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl); |
278 | kfree(repl); | 278 | kfree(repl); |
279 | if (IS_ERR(net->ipv4.nat_table)) | 279 | return PTR_RET(net->ipv4.nat_table); |
280 | return PTR_ERR(net->ipv4.nat_table); | ||
281 | return 0; | ||
282 | } | 280 | } |
283 | 281 | ||
284 | static void __net_exit iptable_nat_net_exit(struct net *net) | 282 | static void __net_exit iptable_nat_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index d57dab17a182..fa84cf8ec6bc 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c | |||
@@ -277,9 +277,7 @@ static int __net_init ip6table_nat_net_init(struct net *net) | |||
277 | return -ENOMEM; | 277 | return -ENOMEM; |
278 | net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl); | 278 | net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl); |
279 | kfree(repl); | 279 | kfree(repl); |
280 | if (IS_ERR(net->ipv6.ip6table_nat)) | 280 | return PTR_RET(net->ipv6.ip6table_nat); |
281 | return PTR_ERR(net->ipv6.ip6table_nat); | ||
282 | return 0; | ||
283 | } | 281 | } |
284 | 282 | ||
285 | static void __net_exit ip6table_nat_net_exit(struct net *net) | 283 | static void __net_exit ip6table_nat_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index ccb5cbe93549..00ee17c3e893 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/netfilter_bridge.h> | 22 | #include <linux/netfilter_bridge.h> |
23 | #include <linux/netfilter_ipv6.h> | 23 | #include <linux/netfilter_ipv6.h> |
24 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
24 | #include <net/netfilter/nf_conntrack.h> | 25 | #include <net/netfilter/nf_conntrack.h> |
25 | #include <net/netfilter/nf_conntrack_helper.h> | 26 | #include <net/netfilter/nf_conntrack_helper.h> |
26 | #include <net/netfilter/nf_conntrack_l4proto.h> | 27 | #include <net/netfilter/nf_conntrack_l4proto.h> |
@@ -295,6 +296,55 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { | |||
295 | }, | 296 | }, |
296 | }; | 297 | }; |
297 | 298 | ||
299 | static int | ||
300 | ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len) | ||
301 | { | ||
302 | const struct inet_sock *inet = inet_sk(sk); | ||
303 | const struct ipv6_pinfo *inet6 = inet6_sk(sk); | ||
304 | const struct nf_conntrack_tuple_hash *h; | ||
305 | struct sockaddr_in6 sin6; | ||
306 | struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 }; | ||
307 | struct nf_conn *ct; | ||
308 | |||
309 | tuple.src.u3.in6 = inet6->rcv_saddr; | ||
310 | tuple.src.u.tcp.port = inet->inet_sport; | ||
311 | tuple.dst.u3.in6 = inet6->daddr; | ||
312 | tuple.dst.u.tcp.port = inet->inet_dport; | ||
313 | tuple.dst.protonum = sk->sk_protocol; | ||
314 | |||
315 | if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP) | ||
316 | return -ENOPROTOOPT; | ||
317 | |||
318 | if (*len < 0 || (unsigned int) *len < sizeof(sin6)) | ||
319 | return -EINVAL; | ||
320 | |||
321 | h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple); | ||
322 | if (!h) { | ||
323 | pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n", | ||
324 | &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port), | ||
325 | &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port)); | ||
326 | return -ENOENT; | ||
327 | } | ||
328 | |||
329 | ct = nf_ct_tuplehash_to_ctrack(h); | ||
330 | |||
331 | sin6.sin6_family = AF_INET6; | ||
332 | sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; | ||
333 | sin6.sin6_flowinfo = inet6->flow_label & IPV6_FLOWINFO_MASK; | ||
334 | memcpy(&sin6.sin6_addr, | ||
335 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6, | ||
336 | sizeof(sin6.sin6_addr)); | ||
337 | |||
338 | nf_ct_put(ct); | ||
339 | |||
340 | if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL) | ||
341 | sin6.sin6_scope_id = sk->sk_bound_dev_if; | ||
342 | else | ||
343 | sin6.sin6_scope_id = 0; | ||
344 | |||
345 | return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0; | ||
346 | } | ||
347 | |||
298 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 348 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
299 | 349 | ||
300 | #include <linux/netfilter/nfnetlink.h> | 350 | #include <linux/netfilter/nfnetlink.h> |
@@ -359,6 +409,14 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); | |||
359 | MODULE_LICENSE("GPL"); | 409 | MODULE_LICENSE("GPL"); |
360 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | 410 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); |
361 | 411 | ||
412 | static struct nf_sockopt_ops so_getorigdst6 = { | ||
413 | .pf = NFPROTO_IPV6, | ||
414 | .get_optmin = IP6T_SO_ORIGINAL_DST, | ||
415 | .get_optmax = IP6T_SO_ORIGINAL_DST + 1, | ||
416 | .get = ipv6_getorigdst, | ||
417 | .owner = THIS_MODULE, | ||
418 | }; | ||
419 | |||
362 | static int ipv6_net_init(struct net *net) | 420 | static int ipv6_net_init(struct net *net) |
363 | { | 421 | { |
364 | int ret = 0; | 422 | int ret = 0; |
@@ -425,6 +483,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
425 | need_conntrack(); | 483 | need_conntrack(); |
426 | nf_defrag_ipv6_enable(); | 484 | nf_defrag_ipv6_enable(); |
427 | 485 | ||
486 | ret = nf_register_sockopt(&so_getorigdst6); | ||
487 | if (ret < 0) { | ||
488 | pr_err("Unable to register netfilter socket option\n"); | ||
489 | return ret; | ||
490 | } | ||
491 | |||
428 | ret = register_pernet_subsys(&ipv6_net_ops); | 492 | ret = register_pernet_subsys(&ipv6_net_ops); |
429 | if (ret < 0) | 493 | if (ret < 0) |
430 | goto cleanup_pernet; | 494 | goto cleanup_pernet; |
@@ -440,6 +504,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
440 | cleanup_ipv6: | 504 | cleanup_ipv6: |
441 | unregister_pernet_subsys(&ipv6_net_ops); | 505 | unregister_pernet_subsys(&ipv6_net_ops); |
442 | cleanup_pernet: | 506 | cleanup_pernet: |
507 | nf_unregister_sockopt(&so_getorigdst6); | ||
443 | return ret; | 508 | return ret; |
444 | } | 509 | } |
445 | 510 | ||
@@ -448,6 +513,7 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void) | |||
448 | synchronize_net(); | 513 | synchronize_net(); |
449 | nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); | 514 | nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); |
450 | unregister_pernet_subsys(&ipv6_net_ops); | 515 | unregister_pernet_subsys(&ipv6_net_ops); |
516 | nf_unregister_sockopt(&so_getorigdst6); | ||
451 | } | 517 | } |
452 | 518 | ||
453 | module_init(nf_conntrack_l3proto_ipv6_init); | 519 | module_init(nf_conntrack_l3proto_ipv6_init); |
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c index 022e77e1e766..c8beafd401aa 100644 --- a/net/netfilter/ipvs/ip_vs_nfct.c +++ b/net/netfilter/ipvs/ip_vs_nfct.c | |||
@@ -82,7 +82,7 @@ void | |||
82 | ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin) | 82 | ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin) |
83 | { | 83 | { |
84 | enum ip_conntrack_info ctinfo; | 84 | enum ip_conntrack_info ctinfo; |
85 | struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo); | 85 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
86 | struct nf_conntrack_tuple new_tuple; | 86 | struct nf_conntrack_tuple new_tuple; |
87 | 87 | ||
88 | if (ct == NULL || nf_ct_is_confirmed(ct) || nf_ct_is_untracked(ct) || | 88 | if (ct == NULL || nf_ct_is_confirmed(ct) || nf_ct_is_untracked(ct) || |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 12008b47e5ca..ee6b7a9f1ec2 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -594,7 +594,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
594 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 594 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
595 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { | 595 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { |
596 | enum ip_conntrack_info ctinfo; | 596 | enum ip_conntrack_info ctinfo; |
597 | struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo); | 597 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
598 | 598 | ||
599 | if (ct && !nf_ct_is_untracked(ct)) { | 599 | if (ct && !nf_ct_is_untracked(ct)) { |
600 | IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0, | 600 | IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0, |
@@ -710,7 +710,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
710 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 710 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
711 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { | 711 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { |
712 | enum ip_conntrack_info ctinfo; | 712 | enum ip_conntrack_info ctinfo; |
713 | struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo); | 713 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
714 | 714 | ||
715 | if (ct && !nf_ct_is_untracked(ct)) { | 715 | if (ct && !nf_ct_is_untracked(ct)) { |
716 | IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0, | 716 | IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0, |
@@ -1235,7 +1235,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
1235 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 1235 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
1236 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { | 1236 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { |
1237 | enum ip_conntrack_info ctinfo; | 1237 | enum ip_conntrack_info ctinfo; |
1238 | struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo); | 1238 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
1239 | 1239 | ||
1240 | if (ct && !nf_ct_is_untracked(ct)) { | 1240 | if (ct && !nf_ct_is_untracked(ct)) { |
1241 | IP_VS_DBG(10, "%s(): " | 1241 | IP_VS_DBG(10, "%s(): " |
@@ -1356,7 +1356,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
1356 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 1356 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
1357 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { | 1357 | if (cp->flags & IP_VS_CONN_F_SYNC && local) { |
1358 | enum ip_conntrack_info ctinfo; | 1358 | enum ip_conntrack_info ctinfo; |
1359 | struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo); | 1359 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
1360 | 1360 | ||
1361 | if (ct && !nf_ct_is_untracked(ct)) { | 1361 | if (ct && !nf_ct_is_untracked(ct)) { |
1362 | IP_VS_DBG(10, "%s(): " | 1362 | IP_VS_DBG(10, "%s(): " |