aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/af_inet6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r--net/ipv6/af_inet6.c70
1 files changed, 34 insertions, 36 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 56b9bf2516f4..3b5669a2582d 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -272,6 +272,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
272 272
273 if (addr_len < SIN6_LEN_RFC2133) 273 if (addr_len < SIN6_LEN_RFC2133)
274 return -EINVAL; 274 return -EINVAL;
275
276 if (addr->sin6_family != AF_INET6)
277 return -EAFNOSUPPORT;
278
275 addr_type = ipv6_addr_type(&addr->sin6_addr); 279 addr_type = ipv6_addr_type(&addr->sin6_addr);
276 if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) 280 if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM)
277 return -EINVAL; 281 return -EINVAL;
@@ -300,7 +304,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
300 goto out; 304 goto out;
301 } 305 }
302 306
303 /* Reproduce AF_INET checks to make the bindings consitant */ 307 /* Reproduce AF_INET checks to make the bindings consistent */
304 v4addr = addr->sin6_addr.s6_addr32[3]; 308 v4addr = addr->sin6_addr.s6_addr32[3];
305 chk_addr_ret = inet_addr_type(net, v4addr); 309 chk_addr_ret = inet_addr_type(net, v4addr);
306 if (!sysctl_ip_nonlocal_bind && 310 if (!sysctl_ip_nonlocal_bind &&
@@ -343,7 +347,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
343 */ 347 */
344 v4addr = LOOPBACK4_IPV6; 348 v4addr = LOOPBACK4_IPV6;
345 if (!(addr_type & IPV6_ADDR_MULTICAST)) { 349 if (!(addr_type & IPV6_ADDR_MULTICAST)) {
346 if (!ipv6_chk_addr(net, &addr->sin6_addr, 350 if (!inet->transparent &&
351 !ipv6_chk_addr(net, &addr->sin6_addr,
347 dev, 0)) { 352 dev, 0)) {
348 err = -EADDRNOTAVAIL; 353 err = -EADDRNOTAVAIL;
349 goto out_unlock; 354 goto out_unlock;
@@ -467,7 +472,7 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
467 if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) 472 if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
468 sin->sin6_scope_id = sk->sk_bound_dev_if; 473 sin->sin6_scope_id = sk->sk_bound_dev_if;
469 *uaddr_len = sizeof(*sin); 474 *uaddr_len = sizeof(*sin);
470 return(0); 475 return 0;
471} 476}
472 477
473EXPORT_SYMBOL(inet6_getname); 478EXPORT_SYMBOL(inet6_getname);
@@ -488,7 +493,7 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
488 case SIOCADDRT: 493 case SIOCADDRT:
489 case SIOCDELRT: 494 case SIOCDELRT:
490 495
491 return(ipv6_route_ioctl(net, cmd, (void __user *)arg)); 496 return ipv6_route_ioctl(net, cmd, (void __user *)arg);
492 497
493 case SIOCSIFADDR: 498 case SIOCSIFADDR:
494 return addrconf_add_ifaddr(net, (void __user *) arg); 499 return addrconf_add_ifaddr(net, (void __user *) arg);
@@ -502,7 +507,7 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
502 return sk->sk_prot->ioctl(sk, cmd, arg); 507 return sk->sk_prot->ioctl(sk, cmd, arg);
503 } 508 }
504 /*NOTREACHED*/ 509 /*NOTREACHED*/
505 return(0); 510 return 0;
506} 511}
507 512
508EXPORT_SYMBOL(inet6_ioctl); 513EXPORT_SYMBOL(inet6_ioctl);
@@ -643,41 +648,34 @@ EXPORT_SYMBOL(inet6_unregister_protosw);
643 648
644int inet6_sk_rebuild_header(struct sock *sk) 649int inet6_sk_rebuild_header(struct sock *sk)
645{ 650{
646 int err;
647 struct dst_entry *dst;
648 struct ipv6_pinfo *np = inet6_sk(sk); 651 struct ipv6_pinfo *np = inet6_sk(sk);
652 struct dst_entry *dst;
649 653
650 dst = __sk_dst_check(sk, np->dst_cookie); 654 dst = __sk_dst_check(sk, np->dst_cookie);
651 655
652 if (dst == NULL) { 656 if (dst == NULL) {
653 struct inet_sock *inet = inet_sk(sk); 657 struct inet_sock *inet = inet_sk(sk);
654 struct in6_addr *final_p, final; 658 struct in6_addr *final_p, final;
655 struct flowi fl; 659 struct flowi6 fl6;
656 660
657 memset(&fl, 0, sizeof(fl)); 661 memset(&fl6, 0, sizeof(fl6));
658 fl.proto = sk->sk_protocol; 662 fl6.flowi6_proto = sk->sk_protocol;
659 ipv6_addr_copy(&fl.fl6_dst, &np->daddr); 663 ipv6_addr_copy(&fl6.daddr, &np->daddr);
660 ipv6_addr_copy(&fl.fl6_src, &np->saddr); 664 ipv6_addr_copy(&fl6.saddr, &np->saddr);
661 fl.fl6_flowlabel = np->flow_label; 665 fl6.flowlabel = np->flow_label;
662 fl.oif = sk->sk_bound_dev_if; 666 fl6.flowi6_oif = sk->sk_bound_dev_if;
663 fl.mark = sk->sk_mark; 667 fl6.flowi6_mark = sk->sk_mark;
664 fl.fl_ip_dport = inet->inet_dport; 668 fl6.fl6_dport = inet->inet_dport;
665 fl.fl_ip_sport = inet->inet_sport; 669 fl6.fl6_sport = inet->inet_sport;
666 security_sk_classify_flow(sk, &fl); 670 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
667 671
668 final_p = fl6_update_dst(&fl, np->opt, &final); 672 final_p = fl6_update_dst(&fl6, np->opt, &final);
669 673
670 err = ip6_dst_lookup(sk, &dst, &fl); 674 dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
671 if (err) { 675 if (IS_ERR(dst)) {
672 sk->sk_route_caps = 0; 676 sk->sk_route_caps = 0;
673 return err; 677 sk->sk_err_soft = -PTR_ERR(dst);
674 } 678 return PTR_ERR(dst);
675 if (final_p)
676 ipv6_addr_copy(&fl.fl6_dst, final_p);
677
678 if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) {
679 sk->sk_err_soft = -err;
680 return err;
681 } 679 }
682 680
683 __ip6_dst_store(sk, dst, NULL, NULL); 681 __ip6_dst_store(sk, dst, NULL, NULL);
@@ -746,7 +744,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
746 744
747static int ipv6_gso_send_check(struct sk_buff *skb) 745static int ipv6_gso_send_check(struct sk_buff *skb)
748{ 746{
749 struct ipv6hdr *ipv6h; 747 const struct ipv6hdr *ipv6h;
750 const struct inet6_protocol *ops; 748 const struct inet6_protocol *ops;
751 int err = -EINVAL; 749 int err = -EINVAL;
752 750
@@ -771,7 +769,7 @@ out:
771 return err; 769 return err;
772} 770}
773 771
774static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) 772static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features)
775{ 773{
776 struct sk_buff *segs = ERR_PTR(-EINVAL); 774 struct sk_buff *segs = ERR_PTR(-EINVAL);
777 struct ipv6hdr *ipv6h; 775 struct ipv6hdr *ipv6h;
@@ -809,7 +807,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
809 } 807 }
810 rcu_read_unlock(); 808 rcu_read_unlock();
811 809
812 if (unlikely(IS_ERR(segs))) 810 if (IS_ERR(segs))
813 goto out; 811 goto out;
814 812
815 for (skb = segs; skb; skb = skb->next) { 813 for (skb = segs; skb; skb = skb->next) {
@@ -1119,7 +1117,7 @@ static int __init inet6_init(void)
1119 /* 1117 /*
1120 * ipngwg API draft makes clear that the correct semantics 1118 * ipngwg API draft makes clear that the correct semantics
1121 * for TCP and UDP is to consider one TCP and UDP instance 1119 * for TCP and UDP is to consider one TCP and UDP instance
1122 * in a host availiable by both INET and INET6 APIs and 1120 * in a host available by both INET and INET6 APIs and
1123 * able to communicate via both network protocols. 1121 * able to communicate via both network protocols.
1124 */ 1122 */
1125 1123