/*
* IPv6 BSD socket options interface
- * Linux INET6 implementation
+ * Linux INET6 implementation
*
* Authors:
- * Pedro Roque <roque@di.fc.ul.pt>
+ * Pedro Roque <roque@di.fc.ul.pt>
*
* Based on linux/net/ipv4/ip_sockglue.c
*
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sockios.h>
-#include <linux/sched.h>
#include <linux/net.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
}
static struct packet_type ipv6_packet_type = {
- .type = __constant_htons(ETH_P_IPV6),
+ .type = __constant_htons(ETH_P_IPV6),
.func = ipv6_rcv,
.gso_send_check = ipv6_gso_send_check,
.gso_segment = ipv6_gso_segment,
np->rxopt.bits.rxinfo = valbool;
retv = 0;
break;
-
+
case IPV6_2292PKTINFO:
np->rxopt.bits.rxoinfo = valbool;
retv = 0;
np->tclass = val;
retv = 0;
break;
-
+
case IPV6_RECVTCLASS:
np->rxopt.bits.rxtclass = valbool;
retv = 0;
}
/* routing header option needs extra check */
- if (optname == IPV6_RTHDR && opt->srcrt) {
+ if (optname == IPV6_RTHDR && opt && opt->srcrt) {
struct ipv6_rt_hdr *rthdr = opt->srcrt;
switch (rthdr->type) {
case IPV6_SRCRT_TYPE_0:
EXPORT_SYMBOL(compat_ipv6_setsockopt);
#endif
-static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
+static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
char __user *optval, int len)
{
- if (!hdr)
+ struct ipv6_opt_hdr *hdr;
+
+ if (!opt || !opt->hopopt)
return 0;
- len = min_t(int, len, ipv6_optlen(hdr));
+ hdr = opt->hopopt;
+
+ len = min_t(unsigned int, len, ipv6_optlen(hdr));
if (copy_to_user(optval, hdr, ipv6_optlen(hdr)))
return -EFAULT;
return len;
case IPV6_MTU:
{
struct dst_entry *dst;
- val = 0;
+ val = 0;
lock_sock(sk);
dst = sk_dst_get(sk);
if (dst) {
{
lock_sock(sk);
- len = ipv6_getsockopt_sticky(sk, np->opt->hopopt,
+ len = ipv6_getsockopt_sticky(sk, np->opt,
optval, len);
release_sock(sk);
return put_user(len, optlen);
break;
case IPV6_UNICAST_HOPS:
- val = np->hop_limit;
- break;
-
case IPV6_MULTICAST_HOPS:
- val = np->mcast_hops;
+ {
+ struct dst_entry *dst;
+
+ if (optname == IPV6_UNICAST_HOPS)
+ val = np->hop_limit;
+ else
+ val = np->mcast_hops;
+
+ dst = sk_dst_get(sk);
+ if (dst) {
+ if (val < 0)
+ val = dst_metric(dst, RTAX_HOPLIMIT);
+ if (val < 0)
+ val = ipv6_get_hoplimit(dst->dev);
+ dst_release(dst);
+ }
+ if (val < 0)
+ val = ipv6_devconf.hop_limit;
break;
+ }
case IPV6_MULTICAST_LOOP:
val = np->mc_loop;