IPv6: data structure changes for new socket options
authorBrian Haley <brian.haley@hp.com>
Fri, 23 Apr 2010 11:26:07 +0000 (11:26 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 24 Apr 2010 06:35:28 +0000 (23:35 -0700)
Add underlying data structure changes and basic setsockopt()
and getsockopt() support for IPV6_RECVPATHMTU, IPV6_PATHMTU,
and IPV6_DONTFRAG.  IPV6_PATHMTU is actually fully functional
at this point.

Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/in6.h
include/linux/ipv6.h
net/ipv6/ipv6_sockglue.c

index 9b90cb296eb1b52008a4cff83b163e0f47accd5e..c4bf46f764bf34bffab67e6de3ec9c8ddee70b0e 100644 (file)
@@ -221,10 +221,10 @@ struct in6_flowlabel_req {
 #define IPV6_RTHDR             57
 #define IPV6_RECVDSTOPTS       58
 #define IPV6_DSTOPTS           59
-#if 0  /* not yet */
 #define IPV6_RECVPATHMTU       60
 #define IPV6_PATHMTU           61
 #define IPV6_DONTFRAG          62
+#if 0  /* not yet */
 #define IPV6_USE_MIN_MTU       63
 #endif
 
index 1bdbebf08d16221d7b341c90e4fd70b3a6665c2d..1976942cf6f9c68c877c6e8b9955aa26bc285712 100644 (file)
@@ -21,6 +21,10 @@ struct in6_pktinfo {
        int             ipi6_ifindex;
 };
 
+struct ip6_mtuinfo {
+       struct sockaddr_in6     ip6m_addr;
+       __u32                   ip6m_mtu;
+};
 
 struct in6_ifreq {
        struct in6_addr ifr6_addr;
@@ -334,22 +338,25 @@ struct ipv6_pinfo {
                                dstopts:1,
                                odstopts:1,
                                 rxflow:1,
-                               rxtclass:1;
+                               rxtclass:1,
+                               rxpmtu:1;
                } bits;
                __u16           all;
        } rxopt;
 
        /* sockopt flags */
-       __u                   recverr:1,
+       __u16                   recverr:1,
                                sndflow:1,
                                pmtudisc:2,
                                ipv6only:1,
-                               srcprefs:3;     /* 001: prefer temporary address
+                               srcprefs:3,     /* 001: prefer temporary address
                                                 * 010: prefer public address
                                                 * 100: prefer care-of address
                                                 */
+                               dontfrag:1;
        __u8                    min_hopcount;
        __u8                    tclass;
+       __u8                    padding;
 
        __u32                   dst_cookie;
 
index 92295ad3487ad441bbf65c1787f4b0fc142eb31f..2bf9eda72788264fa0d047523e0af5ba549b87a2 100644 (file)
@@ -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:
@@ -773,6 +780,9 @@ pref_skip_coa:
                if (val < 0 || val > 255)
                        goto e_inval;
                np->min_hopcount = val;
+               break;
+       case IPV6_DONTFRAG:
+               np->dontfrag = valbool;
                retv = 0;
                break;
        }
@@ -1063,6 +1073,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:
        {
@@ -1128,6 +1170,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                val = np->min_hopcount;
                break;
 
+       case IPV6_DONTFRAG:
+               val = np->dontfrag;
+               break;
+
        default:
                return -ENOPROTOOPT;
        }