diff options
Diffstat (limited to 'net/ipv6/ipv6_sockglue.c')
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 34 |
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) { |