aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYang Hongyang <yanghy@cn.fujitsu.com>2008-12-16 05:06:23 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-16 05:06:23 -0500
commitb24a2516d10751d7ed5afb58420df25370c9dffb (patch)
treecffcf4fc47c4da696e3426424e6ccac7b789e917
parentbc02ff95fe4ebd3e5ee7455c0aa6f76ebe39ebca (diff)
ipv6: Add IPV6_PKTINFO sticky option support to setsockopt()
There are three reasons for me to add this support: 1.When no interface is specified in an IPV6_PKTINFO ancillary data item, the interface specified in an IPV6_PKTINFO sticky optionis is used. RFC3542: 6.7. Summary of Outgoing Interface Selection This document and [RFC-3493] specify various methods that affect the selection of the packet's outgoing interface. This subsection summarizes the ordering among those in order to ensure deterministic behavior. For a given outgoing packet on a given socket, the outgoing interface is determined in the following order: 1. if an interface is specified in an IPV6_PKTINFO ancillary data item, the interface is used. 2. otherwise, if an interface is specified in an IPV6_PKTINFO sticky option, the interface is used. 2.When no IPV6_PKTINFO ancillary data is received,getsockopt() should return the sticky option value which set with setsockopt(). RFC 3542: Issuing getsockopt() for the above options will return the sticky option value i.e., the value set with setsockopt(). If no sticky option value has been set getsockopt() will return the following values: 3.Make the setsockopt implementation POSIX compliant. Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-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 {
278 struct in6_addr saddr; 278 struct in6_addr saddr;
279 struct in6_addr rcv_saddr; 279 struct in6_addr rcv_saddr;
280 struct in6_addr daddr; 280 struct in6_addr daddr;
281 struct in6_pktinfo sticky_pktinfo;
281 struct in6_addr *daddr_cache; 282 struct in6_addr *daddr_cache;
282#ifdef CONFIG_IPV6_SUBTREES 283#ifdef CONFIG_IPV6_SUBTREES
283 struct in6_addr *saddr_cache; 284 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:
395 break; 395 break;
396 } 396 }
397 397
398 case IPV6_PKTINFO:
399 {
400 struct in6_pktinfo pkt;
401
402 if (optlen == 0)
403 goto e_inval;
404 else if (optlen < sizeof(struct in6_pktinfo) || optval == NULL)
405 goto e_inval;
406
407 if (copy_from_user(&pkt, optval, optlen)) {
408 retv = -EFAULT;
409 break;
410 }
411 if (sk->sk_bound_dev_if && pkt.ipi6_ifindex != sk->sk_bound_dev_if)
412 goto e_inval;
413
414 np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
415 ipv6_addr_copy(&np->sticky_pktinfo.ipi6_addr, &pkt.ipi6_addr);
416 retv = 0;
417 break;
418 }
419
398 case IPV6_2292PKTOPTIONS: 420 case IPV6_2292PKTOPTIONS:
399 { 421 {
400 struct ipv6_txoptions *opt = NULL; 422 struct ipv6_txoptions *opt = NULL;