aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Haley <brian.haley@hp.com>2010-04-23 07:26:07 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-24 02:35:28 -0400
commit793b14731686595a741d9f47726ad8b9a235385a (patch)
tree915755840b09ed25911bfbc965bc5e186d05383d
parent3a737028630bb3c2b9efc38b9ddef2e09b06b808 (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.h2
-rw-r--r--include/linux/ipv6.h13
-rw-r--r--net/ipv6/ipv6_sockglue.c46
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
24struct ip6_mtuinfo {
25 struct sockaddr_in6 ip6m_addr;
26 __u32 ip6m_mtu;
27};
24 28
25struct in6_ifreq { 29struct 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 }