initramfs: fix initramfs size calculation
[linux-drm-fsl-dcu.git] / net / ipv6 / ipv6_sockglue.c
index 33f60fca7aa775e36082c65171a10e10a4ec49bb..bd43f0152c21d5e7f5dca9b609a735d1a0573bac 100644 (file)
@@ -114,9 +114,9 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
                }
                opt = xchg(&inet6_sk(sk)->opt, opt);
        } else {
-               write_lock(&sk->sk_dst_lock);
+               spin_lock(&sk->sk_dst_lock);
                opt = xchg(&inet6_sk(sk)->opt, opt);
-               write_unlock(&sk->sk_dst_lock);
+               spin_unlock(&sk->sk_dst_lock);
        }
        sk_dst_reset(sk);
 
@@ -337,6 +337,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                retv = 0;
                break;
 
+       case IPV6_RECVPATHMTU:
+               if (optlen < sizeof(int))
+                       goto e_inval;
+               np->rxopt.bits.rxpmtu = valbool;
+               retv = 0;
+               break;
+
        case IPV6_HOPOPTS:
        case IPV6_RTHDRDSTOPTS:
        case IPV6_RTHDR:
@@ -451,7 +458,8 @@ sticky_done:
                msg.msg_controllen = optlen;
                msg.msg_control = (void*)(opt+1);
 
-               retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk);
+               retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk,
+                                        &junk);
                if (retv)
                        goto done;
 update:
@@ -767,6 +775,17 @@ pref_skip_coa:
 
                break;
            }
+       case IPV6_MINHOPCOUNT:
+               if (optlen < sizeof(int))
+                       goto e_inval;
+               if (val < 0 || val > 255)
+                       goto e_inval;
+               np->min_hopcount = val;
+               break;
+       case IPV6_DONTFRAG:
+               np->dontfrag = valbool;
+               retv = 0;
+               break;
        }
 
        release_sock(sk);
@@ -971,14 +990,13 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
        case IPV6_MTU:
        {
                struct dst_entry *dst;
+
                val = 0;
-               lock_sock(sk);
-               dst = sk_dst_get(sk);
-               if (dst) {
+               rcu_read_lock();
+               dst = __sk_dst_get(sk);
+               if (dst)
                        val = dst_mtu(dst);
-                       dst_release(dst);
-               }
-               release_sock(sk);
+               rcu_read_unlock();
                if (!val)
                        return -ENOTCONN;
                break;
@@ -1056,6 +1074,38 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                val = np->rxopt.bits.rxflow;
                break;
 
+       case IPV6_RECVPATHMTU:
+               val = np->rxopt.bits.rxpmtu;
+               break;
+
+       case IPV6_PATHMTU:
+       {
+               struct dst_entry *dst;
+               struct ip6_mtuinfo mtuinfo;
+
+               if (len < sizeof(mtuinfo))
+                       return -EINVAL;
+
+               len = sizeof(mtuinfo);
+               memset(&mtuinfo, 0, sizeof(mtuinfo));
+
+               rcu_read_lock();
+               dst = __sk_dst_get(sk);
+               if (dst)
+                       mtuinfo.ip6m_mtu = dst_mtu(dst);
+               rcu_read_unlock();
+               if (!mtuinfo.ip6m_mtu)
+                       return -ENOTCONN;
+
+               if (put_user(len, optlen))
+                       return -EFAULT;
+               if (copy_to_user(optval, &mtuinfo, len))
+                       return -EFAULT;
+
+               return 0;
+               break;
+       }
+
        case IPV6_UNICAST_HOPS:
        case IPV6_MULTICAST_HOPS:
        {
@@ -1066,12 +1116,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                else
                        val = np->mcast_hops;
 
-               dst = sk_dst_get(sk);
-               if (dst) {
-                       if (val < 0)
+               if (val < 0) {
+                       rcu_read_lock();
+                       dst = __sk_dst_get(sk);
+                       if (dst)
                                val = ip6_dst_hoplimit(dst);
-                       dst_release(dst);
+                       rcu_read_unlock();
                }
+
                if (val < 0)
                        val = sock_net(sk)->ipv6.devconf_all->hop_limit;
                break;
@@ -1115,6 +1167,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                        val |= IPV6_PREFER_SRC_HOME;
                break;
 
+       case IPV6_MINHOPCOUNT:
+               val = np->min_hopcount;
+               break;
+
+       case IPV6_DONTFRAG:
+               val = np->dontfrag;
+               break;
+
        default:
                return -ENOPROTOOPT;
        }