aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ipv6_sockglue.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ipv6_sockglue.c')
-rw-r--r--net/ipv6/ipv6_sockglue.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 2aa294be0c79..eeeaad2e8b5c 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;
@@ -916,8 +938,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
916 } else { 938 } else {
917 if (np->rxopt.bits.rxinfo) { 939 if (np->rxopt.bits.rxinfo) {
918 struct in6_pktinfo src_info; 940 struct in6_pktinfo src_info;
919 src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : sk->sk_bound_dev_if; 941 src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
920 ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); 942 np->sticky_pktinfo.ipi6_ifindex;
943 np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) :
944 ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr));
921 put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); 945 put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info);
922 } 946 }
923 if (np->rxopt.bits.rxhlim) { 947 if (np->rxopt.bits.rxhlim) {
@@ -926,8 +950,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
926 } 950 }
927 if (np->rxopt.bits.rxoinfo) { 951 if (np->rxopt.bits.rxoinfo) {
928 struct in6_pktinfo src_info; 952 struct in6_pktinfo src_info;
929 src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : sk->sk_bound_dev_if; 953 src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
930 ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); 954 np->sticky_pktinfo.ipi6_ifindex;
955 np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) :
956 ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr));
931 put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); 957 put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
932 } 958 }
933 if (np->rxopt.bits.rxohlim) { 959 if (np->rxopt.bits.rxohlim) {