diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 38 | ||||
| -rw-r--r-- | net/ipv6/calipso.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ip6_gre.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ping.c | 33 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 8 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 1 | ||||
| -rw-r--r-- | net/ipv6/udplite.c | 1 |
7 files changed, 50 insertions, 37 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ab3e796596b1..f418d2eaeddd 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -1872,7 +1872,6 @@ static int addrconf_dad_end(struct inet6_ifaddr *ifp) | |||
| 1872 | 1872 | ||
| 1873 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1873 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) |
| 1874 | { | 1874 | { |
| 1875 | struct in6_addr addr; | ||
| 1876 | struct inet6_dev *idev = ifp->idev; | 1875 | struct inet6_dev *idev = ifp->idev; |
| 1877 | struct net *net = dev_net(ifp->idev->dev); | 1876 | struct net *net = dev_net(ifp->idev->dev); |
| 1878 | 1877 | ||
| @@ -1934,18 +1933,6 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
| 1934 | in6_ifa_put(ifp2); | 1933 | in6_ifa_put(ifp2); |
| 1935 | lock_errdad: | 1934 | lock_errdad: |
| 1936 | spin_lock_bh(&ifp->lock); | 1935 | spin_lock_bh(&ifp->lock); |
| 1937 | } else if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { | ||
| 1938 | addr.s6_addr32[0] = htonl(0xfe800000); | ||
| 1939 | addr.s6_addr32[1] = 0; | ||
| 1940 | |||
| 1941 | if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) && | ||
| 1942 | ipv6_addr_equal(&ifp->addr, &addr)) { | ||
| 1943 | /* DAD failed for link-local based on MAC address */ | ||
| 1944 | idev->cnf.disable_ipv6 = 1; | ||
| 1945 | |||
| 1946 | pr_info("%s: IPv6 being disabled!\n", | ||
| 1947 | ifp->idev->dev->name); | ||
| 1948 | } | ||
| 1949 | } | 1936 | } |
| 1950 | 1937 | ||
| 1951 | errdad: | 1938 | errdad: |
| @@ -3543,7 +3530,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 3543 | /* combine the user config with event to determine if permanent | 3530 | /* combine the user config with event to determine if permanent |
| 3544 | * addresses are to be removed from address hash table | 3531 | * addresses are to be removed from address hash table |
| 3545 | */ | 3532 | */ |
| 3546 | keep_addr = !(how || _keep_addr <= 0); | 3533 | keep_addr = !(how || _keep_addr <= 0 || idev->cnf.disable_ipv6); |
| 3547 | 3534 | ||
| 3548 | /* Step 2: clear hash table */ | 3535 | /* Step 2: clear hash table */ |
| 3549 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { | 3536 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
| @@ -3599,7 +3586,7 @@ restart: | |||
| 3599 | /* re-combine the user config with event to determine if permanent | 3586 | /* re-combine the user config with event to determine if permanent |
| 3600 | * addresses are to be removed from the interface list | 3587 | * addresses are to be removed from the interface list |
| 3601 | */ | 3588 | */ |
| 3602 | keep_addr = (!how && _keep_addr > 0); | 3589 | keep_addr = (!how && _keep_addr > 0 && !idev->cnf.disable_ipv6); |
| 3603 | 3590 | ||
| 3604 | INIT_LIST_HEAD(&del_list); | 3591 | INIT_LIST_HEAD(&del_list); |
| 3605 | list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) { | 3592 | list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) { |
| @@ -3821,6 +3808,7 @@ static void addrconf_dad_work(struct work_struct *w) | |||
| 3821 | dad_work); | 3808 | dad_work); |
| 3822 | struct inet6_dev *idev = ifp->idev; | 3809 | struct inet6_dev *idev = ifp->idev; |
| 3823 | struct in6_addr mcaddr; | 3810 | struct in6_addr mcaddr; |
| 3811 | bool disable_ipv6 = false; | ||
| 3824 | 3812 | ||
| 3825 | enum { | 3813 | enum { |
| 3826 | DAD_PROCESS, | 3814 | DAD_PROCESS, |
| @@ -3837,6 +3825,24 @@ static void addrconf_dad_work(struct work_struct *w) | |||
| 3837 | } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) { | 3825 | } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) { |
| 3838 | action = DAD_ABORT; | 3826 | action = DAD_ABORT; |
| 3839 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | 3827 | ifp->state = INET6_IFADDR_STATE_POSTDAD; |
| 3828 | |||
| 3829 | if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6 && | ||
| 3830 | !(ifp->flags & IFA_F_STABLE_PRIVACY)) { | ||
| 3831 | struct in6_addr addr; | ||
| 3832 | |||
| 3833 | addr.s6_addr32[0] = htonl(0xfe800000); | ||
| 3834 | addr.s6_addr32[1] = 0; | ||
| 3835 | |||
| 3836 | if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) && | ||
| 3837 | ipv6_addr_equal(&ifp->addr, &addr)) { | ||
| 3838 | /* DAD failed for link-local based on MAC */ | ||
| 3839 | idev->cnf.disable_ipv6 = 1; | ||
| 3840 | |||
| 3841 | pr_info("%s: IPv6 being disabled!\n", | ||
| 3842 | ifp->idev->dev->name); | ||
| 3843 | disable_ipv6 = true; | ||
| 3844 | } | ||
| 3845 | } | ||
| 3840 | } | 3846 | } |
| 3841 | spin_unlock_bh(&ifp->lock); | 3847 | spin_unlock_bh(&ifp->lock); |
| 3842 | 3848 | ||
| @@ -3845,6 +3851,8 @@ static void addrconf_dad_work(struct work_struct *w) | |||
| 3845 | goto out; | 3851 | goto out; |
| 3846 | } else if (action == DAD_ABORT) { | 3852 | } else if (action == DAD_ABORT) { |
| 3847 | addrconf_dad_stop(ifp, 1); | 3853 | addrconf_dad_stop(ifp, 1); |
| 3854 | if (disable_ipv6) | ||
| 3855 | addrconf_ifdown(idev->dev, 0); | ||
| 3848 | goto out; | 3856 | goto out; |
| 3849 | } | 3857 | } |
| 3850 | 3858 | ||
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index c53b92c617c5..37ac9de713c6 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c | |||
| @@ -952,8 +952,10 @@ calipso_opt_insert(struct ipv6_opt_hdr *hop, | |||
| 952 | memcpy(new, hop, start); | 952 | memcpy(new, hop, start); |
| 953 | ret_val = calipso_genopt((unsigned char *)new, start, buf_len, doi_def, | 953 | ret_val = calipso_genopt((unsigned char *)new, start, buf_len, doi_def, |
| 954 | secattr); | 954 | secattr); |
| 955 | if (ret_val < 0) | 955 | if (ret_val < 0) { |
| 956 | kfree(new); | ||
| 956 | return ERR_PTR(ret_val); | 957 | return ERR_PTR(ret_val); |
| 958 | } | ||
| 957 | 959 | ||
| 958 | buf_len = start + ret_val; | 960 | buf_len = start + ret_val; |
| 959 | /* At this point buf_len aligns to 4n, so (buf_len & 4) pads to 8n */ | 961 | /* At this point buf_len aligns to 4n, so (buf_len & 4) pads to 8n */ |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 776d145113e1..704274cbd495 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -519,8 +519,6 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb, | |||
| 519 | gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags, | 519 | gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags, |
| 520 | protocol, tunnel->parms.o_key, htonl(tunnel->o_seqno)); | 520 | protocol, tunnel->parms.o_key, htonl(tunnel->o_seqno)); |
| 521 | 521 | ||
| 522 | skb_set_inner_protocol(skb, protocol); | ||
| 523 | |||
| 524 | return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu, | 522 | return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu, |
| 525 | NEXTHDR_GRE); | 523 | NEXTHDR_GRE); |
| 526 | } | 524 | } |
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index fed40d1ec29b..0900352c924c 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
| @@ -55,7 +55,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
| 55 | struct icmp6hdr user_icmph; | 55 | struct icmp6hdr user_icmph; |
| 56 | int addr_type; | 56 | int addr_type; |
| 57 | struct in6_addr *daddr; | 57 | struct in6_addr *daddr; |
| 58 | int iif = 0; | 58 | int oif = 0; |
| 59 | struct flowi6 fl6; | 59 | struct flowi6 fl6; |
| 60 | int err; | 60 | int err; |
| 61 | struct dst_entry *dst; | 61 | struct dst_entry *dst; |
| @@ -78,25 +78,30 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
| 78 | if (u->sin6_family != AF_INET6) { | 78 | if (u->sin6_family != AF_INET6) { |
| 79 | return -EAFNOSUPPORT; | 79 | return -EAFNOSUPPORT; |
| 80 | } | 80 | } |
| 81 | if (sk->sk_bound_dev_if && | ||
| 82 | sk->sk_bound_dev_if != u->sin6_scope_id) { | ||
| 83 | return -EINVAL; | ||
| 84 | } | ||
| 85 | daddr = &(u->sin6_addr); | 81 | daddr = &(u->sin6_addr); |
| 86 | iif = u->sin6_scope_id; | 82 | if (__ipv6_addr_needs_scope_id(ipv6_addr_type(daddr))) |
| 83 | oif = u->sin6_scope_id; | ||
| 87 | } else { | 84 | } else { |
| 88 | if (sk->sk_state != TCP_ESTABLISHED) | 85 | if (sk->sk_state != TCP_ESTABLISHED) |
| 89 | return -EDESTADDRREQ; | 86 | return -EDESTADDRREQ; |
| 90 | daddr = &sk->sk_v6_daddr; | 87 | daddr = &sk->sk_v6_daddr; |
| 91 | } | 88 | } |
| 92 | 89 | ||
| 93 | if (!iif) | 90 | if (!oif) |
| 94 | iif = sk->sk_bound_dev_if; | 91 | oif = sk->sk_bound_dev_if; |
| 92 | |||
| 93 | if (!oif) | ||
| 94 | oif = np->sticky_pktinfo.ipi6_ifindex; | ||
| 95 | |||
| 96 | if (!oif && ipv6_addr_is_multicast(daddr)) | ||
| 97 | oif = np->mcast_oif; | ||
| 98 | else if (!oif) | ||
| 99 | oif = np->ucast_oif; | ||
| 95 | 100 | ||
| 96 | addr_type = ipv6_addr_type(daddr); | 101 | addr_type = ipv6_addr_type(daddr); |
| 97 | if (__ipv6_addr_needs_scope_id(addr_type) && !iif) | 102 | if ((__ipv6_addr_needs_scope_id(addr_type) && !oif) || |
| 98 | return -EINVAL; | 103 | (addr_type & IPV6_ADDR_MAPPED) || |
| 99 | if (addr_type & IPV6_ADDR_MAPPED) | 104 | (oif && sk->sk_bound_dev_if && oif != sk->sk_bound_dev_if)) |
| 100 | return -EINVAL; | 105 | return -EINVAL; |
| 101 | 106 | ||
| 102 | /* TODO: use ip6_datagram_send_ctl to get options from cmsg */ | 107 | /* TODO: use ip6_datagram_send_ctl to get options from cmsg */ |
| @@ -106,16 +111,12 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
| 106 | fl6.flowi6_proto = IPPROTO_ICMPV6; | 111 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
| 107 | fl6.saddr = np->saddr; | 112 | fl6.saddr = np->saddr; |
| 108 | fl6.daddr = *daddr; | 113 | fl6.daddr = *daddr; |
| 114 | fl6.flowi6_oif = oif; | ||
| 109 | fl6.flowi6_mark = sk->sk_mark; | 115 | fl6.flowi6_mark = sk->sk_mark; |
| 110 | fl6.fl6_icmp_type = user_icmph.icmp6_type; | 116 | fl6.fl6_icmp_type = user_icmph.icmp6_type; |
| 111 | fl6.fl6_icmp_code = user_icmph.icmp6_code; | 117 | fl6.fl6_icmp_code = user_icmph.icmp6_code; |
| 112 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 118 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
| 113 | 119 | ||
| 114 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) | ||
| 115 | fl6.flowi6_oif = np->mcast_oif; | ||
| 116 | else if (!fl6.flowi6_oif) | ||
| 117 | fl6.flowi6_oif = np->ucast_oif; | ||
| 118 | |||
| 119 | ipc6.tclass = np->tclass; | 120 | ipc6.tclass = np->tclass; |
| 120 | fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel); | 121 | fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel); |
| 121 | 122 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 33df8b8575cc..94f4f89d73e7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -944,9 +944,15 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, | |||
| 944 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV | 944 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV |
| 945 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. | 945 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. |
| 946 | */ | 946 | */ |
| 947 | /* RFC 7323 2.3 | ||
| 948 | * The window field (SEG.WND) of every outgoing segment, with the | ||
| 949 | * exception of <SYN> segments, MUST be right-shifted by | ||
| 950 | * Rcv.Wind.Shift bits: | ||
| 951 | */ | ||
| 947 | tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ? | 952 | tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ? |
| 948 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, | 953 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, |
| 949 | tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, | 954 | tcp_rsk(req)->rcv_nxt, |
| 955 | req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, | ||
| 950 | tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if, | 956 | tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if, |
| 951 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), | 957 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), |
| 952 | 0, 0); | 958 | 0, 0); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 81e2f98b958d..19ac3a1c308d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -1460,7 +1460,6 @@ struct proto udpv6_prot = { | |||
| 1460 | .sysctl_wmem = &sysctl_udp_wmem_min, | 1460 | .sysctl_wmem = &sysctl_udp_wmem_min, |
| 1461 | .sysctl_rmem = &sysctl_udp_rmem_min, | 1461 | .sysctl_rmem = &sysctl_udp_rmem_min, |
| 1462 | .obj_size = sizeof(struct udp6_sock), | 1462 | .obj_size = sizeof(struct udp6_sock), |
| 1463 | .slab_flags = SLAB_DESTROY_BY_RCU, | ||
| 1464 | .h.udp_table = &udp_table, | 1463 | .h.udp_table = &udp_table, |
| 1465 | #ifdef CONFIG_COMPAT | 1464 | #ifdef CONFIG_COMPAT |
| 1466 | .compat_setsockopt = compat_udpv6_setsockopt, | 1465 | .compat_setsockopt = compat_udpv6_setsockopt, |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 9cf097e206e9..fd6ef414899b 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
| @@ -50,7 +50,6 @@ struct proto udplitev6_prot = { | |||
| 50 | .unhash = udp_lib_unhash, | 50 | .unhash = udp_lib_unhash, |
| 51 | .get_port = udp_v6_get_port, | 51 | .get_port = udp_v6_get_port, |
| 52 | .obj_size = sizeof(struct udp6_sock), | 52 | .obj_size = sizeof(struct udp6_sock), |
| 53 | .slab_flags = SLAB_DESTROY_BY_RCU, | ||
| 54 | .h.udp_table = &udplite_table, | 53 | .h.udp_table = &udplite_table, |
| 55 | #ifdef CONFIG_COMPAT | 54 | #ifdef CONFIG_COMPAT |
| 56 | .compat_setsockopt = compat_udpv6_setsockopt, | 55 | .compat_setsockopt = compat_udpv6_setsockopt, |
