Commit 545b29019c8959c805abfe8194d47e989f1a6e5f

Authored by David S. Miller

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>

Showing 7 changed files Side-by-side Diff

include/uapi/linux/in6.h
... ... @@ -240,6 +240,7 @@
240 240 *
241 241 * IP6T_SO_GET_REVISION_MATCH 68
242 242 * IP6T_SO_GET_REVISION_TARGET 69
  243 + * IP6T_SO_ORIGINAL_DST 80
243 244 */
244 245  
245 246 /* RFC5014: Source address selection */
include/uapi/linux/netfilter_ipv6/ip6_tables.h
... ... @@ -178,6 +178,9 @@
178 178 #define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 5)
179 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 184 /* ICMP matching stuff */
182 185 struct ip6t_icmp {
183 186 __u8 type; /* type to match */
net/ipv4/netfilter/iptable_nat.c
... ... @@ -276,9 +276,7 @@
276 276 return -ENOMEM;
277 277 net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
278 278 kfree(repl);
279   - if (IS_ERR(net->ipv4.nat_table))
280   - return PTR_ERR(net->ipv4.nat_table);
281   - return 0;
  279 + return PTR_RET(net->ipv4.nat_table);
282 280 }
283 281  
284 282 static void __net_exit iptable_nat_net_exit(struct net *net)
net/ipv6/netfilter/ip6table_nat.c
... ... @@ -277,9 +277,7 @@
277 277 return -ENOMEM;
278 278 net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
279 279 kfree(repl);
280   - if (IS_ERR(net->ipv6.ip6table_nat))
281   - return PTR_ERR(net->ipv6.ip6table_nat);
282   - return 0;
  280 + return PTR_RET(net->ipv6.ip6table_nat);
283 281 }
284 282  
285 283 static void __net_exit ip6table_nat_net_exit(struct net *net)
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
... ... @@ -21,6 +21,7 @@
21 21  
22 22 #include <linux/netfilter_bridge.h>
23 23 #include <linux/netfilter_ipv6.h>
  24 +#include <linux/netfilter_ipv6/ip6_tables.h>
24 25 #include <net/netfilter/nf_conntrack.h>
25 26 #include <net/netfilter/nf_conntrack_helper.h>
26 27 #include <net/netfilter/nf_conntrack_l4proto.h>
... ... @@ -295,6 +296,55 @@
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 348 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
299 349  
300 350 #include <linux/netfilter/nfnetlink.h>
... ... @@ -359,6 +409,14 @@
359 409 MODULE_LICENSE("GPL");
360 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 420 static int ipv6_net_init(struct net *net)
363 421 {
364 422 int ret = 0;
... ... @@ -425,6 +483,12 @@
425 483 need_conntrack();
426 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 492 ret = register_pernet_subsys(&ipv6_net_ops);
429 493 if (ret < 0)
430 494 goto cleanup_pernet;
... ... @@ -440,6 +504,7 @@
440 504 cleanup_ipv6:
441 505 unregister_pernet_subsys(&ipv6_net_ops);
442 506 cleanup_pernet:
  507 + nf_unregister_sockopt(&so_getorigdst6);
443 508 return ret;
444 509 }
445 510  
... ... @@ -448,6 +513,7 @@
448 513 synchronize_net();
449 514 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
450 515 unregister_pernet_subsys(&ipv6_net_ops);
  516 + nf_unregister_sockopt(&so_getorigdst6);
451 517 }
452 518  
453 519 module_init(nf_conntrack_l3proto_ipv6_init);
net/netfilter/ipvs/ip_vs_nfct.c
... ... @@ -82,7 +82,7 @@
82 82 ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
83 83 {
84 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 86 struct nf_conntrack_tuple new_tuple;
87 87  
88 88 if (ct == NULL || nf_ct_is_confirmed(ct) || nf_ct_is_untracked(ct) ||
net/netfilter/ipvs/ip_vs_xmit.c
... ... @@ -594,7 +594,7 @@
594 594 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
595 595 if (cp->flags & IP_VS_CONN_F_SYNC && local) {
596 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 599 if (ct && !nf_ct_is_untracked(ct)) {
600 600 IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0,
... ... @@ -710,7 +710,7 @@
710 710 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
711 711 if (cp->flags & IP_VS_CONN_F_SYNC && local) {
712 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 715 if (ct && !nf_ct_is_untracked(ct)) {
716 716 IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0,
... ... @@ -1235,7 +1235,7 @@
1235 1235 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
1236 1236 if (cp->flags & IP_VS_CONN_F_SYNC && local) {
1237 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 1240 if (ct && !nf_ct_is_untracked(ct)) {
1241 1241 IP_VS_DBG(10, "%s(): "
... ... @@ -1356,7 +1356,7 @@
1356 1356 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
1357 1357 if (cp->flags & IP_VS_CONN_F_SYNC && local) {
1358 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 1361 if (ct && !nf_ct_is_untracked(ct)) {
1362 1362 IP_VS_DBG(10, "%s(): "