IPv6: data structure changes for new socket options
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>
This commit is contained in:
parent
3a73702863
commit
793b147316
3 changed files with 57 additions and 4 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
__u8 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;
|
||||
|
||||
|
|
|
@ -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 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue