summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/ipv6.h1
-rw-r--r--net/ipv6/ipv6_sockglue.c22
2 files changed, 23 insertions, 0 deletions
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 641e026eee8f..0b816cae533e 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -278,6 +278,7 @@ struct ipv6_pinfo {
struct in6_addr saddr;
struct in6_addr rcv_saddr;
struct in6_addr daddr;
+ struct in6_pktinfo sticky_pktinfo;
struct in6_addr *daddr_cache;
#ifdef CONFIG_IPV6_SUBTREES
struct in6_addr *saddr_cache;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 2aa294be0c79..0feaee38bc37 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -395,6 +395,28 @@ sticky_done:
break;
}
+ case IPV6_PKTINFO:
+ {
+ struct in6_pktinfo pkt;
+
+ if (optlen == 0)
+ goto e_inval;
+ else if (optlen < sizeof(struct in6_pktinfo) || optval == NULL)
+ goto e_inval;
+
+ if (copy_from_user(&pkt, optval, optlen)) {
+ retv = -EFAULT;
+ break;
+ }
+ if (sk->sk_bound_dev_if && pkt.ipi6_ifindex != sk->sk_bound_dev_if)
+ goto e_inval;
+
+ np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
+ ipv6_addr_copy(&np->sticky_pktinfo.ipi6_addr, &pkt.ipi6_addr);
+ retv = 0;
+ break;
+ }
+
case IPV6_2292PKTOPTIONS:
{
struct ipv6_txoptions *opt = NULL;