diff options
author | Brian Haley <brian.haley@hp.com> | 2010-04-23 07:26:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-24 02:35:28 -0400 |
commit | 793b14731686595a741d9f47726ad8b9a235385a (patch) | |
tree | 915755840b09ed25911bfbc965bc5e186d05383d | |
parent | 3a737028630bb3c2b9efc38b9ddef2e09b06b808 (diff) |
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>
-rw-r--r-- | include/linux/in6.h | 2 | ||||
-rw-r--r-- | include/linux/ipv6.h | 13 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 46 |
3 files changed, 57 insertions, 4 deletions
diff --git a/include/linux/in6.h b/include/linux/in6.h index 9b90cb296eb1..c4bf46f764bf 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h | |||
@@ -221,10 +221,10 @@ struct in6_flowlabel_req { | |||
221 | #define IPV6_RTHDR 57 | 221 | #define IPV6_RTHDR 57 |
222 | #define IPV6_RECVDSTOPTS 58 | 222 | #define IPV6_RECVDSTOPTS 58 |
223 | #define IPV6_DSTOPTS 59 | 223 | #define IPV6_DSTOPTS 59 |
224 | #if 0 /* not yet */ | ||
225 | #define IPV6_RECVPATHMTU 60 | 224 | #define IPV6_RECVPATHMTU 60 |
226 | #define IPV6_PATHMTU 61 | 225 | #define IPV6_PATHMTU 61 |
227 | #define IPV6_DONTFRAG 62 | 226 | #define IPV6_DONTFRAG 62 |
227 | #if 0 /* not yet */ | ||
228 | #define IPV6_USE_MIN_MTU 63 | 228 | #define IPV6_USE_MIN_MTU 63 |
229 | #endif | 229 | #endif |
230 | 230 | ||
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 1bdbebf08d16..1976942cf6f9 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h | |||
@@ -21,6 +21,10 @@ struct in6_pktinfo { | |||
21 | int ipi6_ifindex; | 21 | int ipi6_ifindex; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | struct ip6_mtuinfo { | ||
25 | struct sockaddr_in6 ip6m_addr; | ||
26 | __u32 ip6m_mtu; | ||
27 | }; | ||
24 | 28 | ||
25 | struct in6_ifreq { | 29 | struct in6_ifreq { |
26 | struct in6_addr ifr6_addr; | 30 | struct in6_addr ifr6_addr; |
@@ -334,22 +338,25 @@ struct ipv6_pinfo { | |||
334 | dstopts:1, | 338 | dstopts:1, |
335 | odstopts:1, | 339 | odstopts:1, |
336 | rxflow:1, | 340 | rxflow:1, |
337 | rxtclass:1; | 341 | rxtclass:1, |
342 | rxpmtu:1; | ||
338 | } bits; | 343 | } bits; |
339 | __u16 all; | 344 | __u16 all; |
340 | } rxopt; | 345 | } rxopt; |
341 | 346 | ||
342 | /* sockopt flags */ | 347 | /* sockopt flags */ |
343 | __u8 recverr:1, | 348 | __u16 recverr:1, |
344 | sndflow:1, | 349 | sndflow:1, |
345 | pmtudisc:2, | 350 | pmtudisc:2, |
346 | ipv6only:1, | 351 | ipv6only:1, |
347 | srcprefs:3; /* 001: prefer temporary address | 352 | srcprefs:3, /* 001: prefer temporary address |
348 | * 010: prefer public address | 353 | * 010: prefer public address |
349 | * 100: prefer care-of address | 354 | * 100: prefer care-of address |
350 | */ | 355 | */ |
356 | dontfrag:1; | ||
351 | __u8 min_hopcount; | 357 | __u8 min_hopcount; |
352 | __u8 tclass; | 358 | __u8 tclass; |
359 | __u8 padding; | ||
353 | 360 | ||
354 | __u32 dst_cookie; | 361 | __u32 dst_cookie; |
355 | 362 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 92295ad3487a..2bf9eda72788 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -337,6 +337,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
337 | retv = 0; | 337 | retv = 0; |
338 | break; | 338 | break; |
339 | 339 | ||
340 | case IPV6_RECVPATHMTU: | ||
341 | if (optlen < sizeof(int)) | ||
342 | goto e_inval; | ||
343 | np->rxopt.bits.rxpmtu = valbool; | ||
344 | retv = 0; | ||
345 | break; | ||
346 | |||
340 | case IPV6_HOPOPTS: | 347 | case IPV6_HOPOPTS: |
341 | case IPV6_RTHDRDSTOPTS: | 348 | case IPV6_RTHDRDSTOPTS: |
342 | case IPV6_RTHDR: | 349 | case IPV6_RTHDR: |
@@ -773,6 +780,9 @@ pref_skip_coa: | |||
773 | if (val < 0 || val > 255) | 780 | if (val < 0 || val > 255) |
774 | goto e_inval; | 781 | goto e_inval; |
775 | np->min_hopcount = val; | 782 | np->min_hopcount = val; |
783 | break; | ||
784 | case IPV6_DONTFRAG: | ||
785 | np->dontfrag = valbool; | ||
776 | retv = 0; | 786 | retv = 0; |
777 | break; | 787 | break; |
778 | } | 788 | } |
@@ -1063,6 +1073,38 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1063 | val = np->rxopt.bits.rxflow; | 1073 | val = np->rxopt.bits.rxflow; |
1064 | break; | 1074 | break; |
1065 | 1075 | ||
1076 | case IPV6_RECVPATHMTU: | ||
1077 | val = np->rxopt.bits.rxpmtu; | ||
1078 | break; | ||
1079 | |||
1080 | case IPV6_PATHMTU: | ||
1081 | { | ||
1082 | struct dst_entry *dst; | ||
1083 | struct ip6_mtuinfo mtuinfo; | ||
1084 | |||
1085 | if (len < sizeof(mtuinfo)) | ||
1086 | return -EINVAL; | ||
1087 | |||
1088 | len = sizeof(mtuinfo); | ||
1089 | memset(&mtuinfo, 0, sizeof(mtuinfo)); | ||
1090 | |||
1091 | rcu_read_lock(); | ||
1092 | dst = __sk_dst_get(sk); | ||
1093 | if (dst) | ||
1094 | mtuinfo.ip6m_mtu = dst_mtu(dst); | ||
1095 | rcu_read_unlock(); | ||
1096 | if (!mtuinfo.ip6m_mtu) | ||
1097 | return -ENOTCONN; | ||
1098 | |||
1099 | if (put_user(len, optlen)) | ||
1100 | return -EFAULT; | ||
1101 | if (copy_to_user(optval, &mtuinfo, len)) | ||
1102 | return -EFAULT; | ||
1103 | |||
1104 | return 0; | ||
1105 | break; | ||
1106 | } | ||
1107 | |||
1066 | case IPV6_UNICAST_HOPS: | 1108 | case IPV6_UNICAST_HOPS: |
1067 | case IPV6_MULTICAST_HOPS: | 1109 | case IPV6_MULTICAST_HOPS: |
1068 | { | 1110 | { |
@@ -1128,6 +1170,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1128 | val = np->min_hopcount; | 1170 | val = np->min_hopcount; |
1129 | break; | 1171 | break; |
1130 | 1172 | ||
1173 | case IPV6_DONTFRAG: | ||
1174 | val = np->dontfrag; | ||
1175 | break; | ||
1176 | |||
1131 | default: | 1177 | default: |
1132 | return -ENOPROTOOPT; | 1178 | return -ENOPROTOOPT; |
1133 | } | 1179 | } |