]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/ipv6_sockglue.c
ipv6: remove ipv6_statistics
[net-next-2.6.git] / net / ipv6 / ipv6_sockglue.c
index 33f60fca7aa775e36082c65171a10e10a4ec49bb..a7f66bc8f0b0ef2a8b0eee454c1e103344eda417 100644 (file)
@@ -55,8 +55,6 @@
 
 #include <asm/uaccess.h>
 
-DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly;
-
 struct ip6_ra_chain *ip6_ra_chain;
 DEFINE_RWLOCK(ip6_ra_lock);
 
@@ -114,9 +112,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 +335,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 +456,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 +773,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 +988,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 +1072,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 +1114,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 +1165,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;
        }