These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / ipv6 / af_inet6.c
index eef63b3..9f5137c 100644 (file)
@@ -109,6 +109,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
        int try_loading_module = 0;
        int err;
 
+       if (protocol < 0 || protocol >= IPPROTO_MAX)
+               return -EINVAL;
+
        /* Look for the requested type/protocol pair. */
 lookup_protocol:
        err = -ESOCKTNOSUPPORT;
@@ -167,7 +170,7 @@ lookup_protocol:
        WARN_ON(!answer_prot->slab);
 
        err = -ENOBUFS;
-       sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot);
+       sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot, kern);
        if (!sk)
                goto out;
 
@@ -197,6 +200,7 @@ lookup_protocol:
        np->mcast_hops  = IPV6_DEFAULT_MCASTHOPS;
        np->mc_loop     = 1;
        np->pmtudisc    = IPV6_PMTUDISC_WANT;
+       np->autoflowlabel = ip6_default_np_autolabel(sock_net(sk));
        sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
 
        /* Init the ipv4 part of the socket since we can have sockets
@@ -342,7 +346,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                         */
                        v4addr = LOOPBACK4_IPV6;
                        if (!(addr_type & IPV6_ADDR_MULTICAST)) {
-                               if (!(inet->freebind || inet->transparent) &&
+                               if (!net->ipv6.sysctl.ip_nonlocal_bind &&
+                                   !(inet->freebind || inet->transparent) &&
                                    !ipv6_chk_addr(net, &addr->sin6_addr,
                                                   dev, 0)) {
                                        err = -EADDRNOTAVAIL;
@@ -362,7 +367,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                np->saddr = addr->sin6_addr;
 
        /* Make sure we are allowed to bind here. */
-       if (sk->sk_prot->get_port(sk, snum)) {
+       if ((snum || !inet->bind_address_no_port) &&
+           sk->sk_prot->get_port(sk, snum)) {
                inet_reset_saddr(sk);
                err = -EADDRINUSE;
                goto out;
@@ -425,9 +431,11 @@ void inet6_destroy_sock(struct sock *sk)
 
        /* Free tx options */
 
-       opt = xchg(&np->opt, NULL);
-       if (opt)
-               sock_kfree_s(sk, opt, opt->tot_len);
+       opt = xchg((__force struct ipv6_txoptions **)&np->opt, NULL);
+       if (opt) {
+               atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
+               txopt_put(opt);
+       }
 }
 EXPORT_SYMBOL_GPL(inet6_destroy_sock);
 
@@ -656,7 +664,10 @@ int inet6_sk_rebuild_header(struct sock *sk)
                fl6.fl6_sport = inet->inet_sport;
                security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-               final_p = fl6_update_dst(&fl6, np->opt, &final);
+               rcu_read_lock();
+               final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt),
+                                        &final);
+               rcu_read_unlock();
 
                dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
                if (IS_ERR(dst)) {
@@ -665,7 +676,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
                        return PTR_ERR(dst);
                }
 
-               __ip6_dst_store(sk, dst, NULL, NULL);
+               ip6_dst_store(sk, dst, NULL, NULL);
        }
 
        return 0;
@@ -678,8 +689,8 @@ bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb,
        const struct ipv6_pinfo *np = inet6_sk(sk);
 
        if (np->rxopt.all) {
-               if ((opt->hop && (np->rxopt.bits.hopopts ||
-                                 np->rxopt.bits.ohopopts)) ||
+               if (((opt->flags & IP6SKB_HOPBYHOP) &&
+                    (np->rxopt.bits.hopopts || np->rxopt.bits.ohopopts)) ||
                    (ip6_flowinfo((struct ipv6hdr *) skb_network_header(skb)) &&
                     np->rxopt.bits.rxflow) ||
                    (opt->srcrt && (np->rxopt.bits.srcrt ||
@@ -765,9 +776,10 @@ static int __net_init inet6_net_init(struct net *net)
        net->ipv6.sysctl.bindv6only = 0;
        net->ipv6.sysctl.icmpv6_time = 1*HZ;
        net->ipv6.sysctl.flowlabel_consistency = 1;
-       net->ipv6.sysctl.auto_flowlabels = 0;
+       net->ipv6.sysctl.auto_flowlabels = IP6_DEFAULT_AUTO_FLOW_LABELS;
        net->ipv6.sysctl.idgen_retries = 3;
        net->ipv6.sysctl.idgen_delay = 1 * HZ;
+       net->ipv6.sysctl.flowlabel_state_ranges = 0;
        atomic_set(&net->ipv6.fib6_sernum, 1);
 
        err = ipv6_init_mibs(net);