diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/datagram.c | 19 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 23 |
2 files changed, 42 insertions, 0 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index ef371aa01ac5..320bdb877eed 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -577,6 +577,25 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
577 | u8 *ptr = nh + opt->dst1; | 577 | u8 *ptr = nh + opt->dst1; |
578 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); | 578 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); |
579 | } | 579 | } |
580 | if (np->rxopt.bits.rxorigdstaddr) { | ||
581 | struct sockaddr_in6 sin6; | ||
582 | u16 *ports = (u16 *) skb_transport_header(skb); | ||
583 | |||
584 | if (skb_transport_offset(skb) + 4 <= skb->len) { | ||
585 | /* All current transport protocols have the port numbers in the | ||
586 | * first four bytes of the transport header and this function is | ||
587 | * written with this assumption in mind. | ||
588 | */ | ||
589 | |||
590 | sin6.sin6_family = AF_INET6; | ||
591 | ipv6_addr_copy(&sin6.sin6_addr, &ipv6_hdr(skb)->daddr); | ||
592 | sin6.sin6_port = ports[1]; | ||
593 | sin6.sin6_flowinfo = 0; | ||
594 | sin6.sin6_scope_id = 0; | ||
595 | |||
596 | put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6); | ||
597 | } | ||
598 | } | ||
580 | return 0; | 599 | return 0; |
581 | } | 600 | } |
582 | 601 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index a7f66bc8f0b0..0553867a317f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -342,6 +342,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
342 | retv = 0; | 342 | retv = 0; |
343 | break; | 343 | break; |
344 | 344 | ||
345 | case IPV6_TRANSPARENT: | ||
346 | if (optlen < sizeof(int)) | ||
347 | goto e_inval; | ||
348 | /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */ | ||
349 | inet_sk(sk)->transparent = valbool; | ||
350 | retv = 0; | ||
351 | break; | ||
352 | |||
353 | case IPV6_RECVORIGDSTADDR: | ||
354 | if (optlen < sizeof(int)) | ||
355 | goto e_inval; | ||
356 | np->rxopt.bits.rxorigdstaddr = valbool; | ||
357 | retv = 0; | ||
358 | break; | ||
359 | |||
345 | case IPV6_HOPOPTS: | 360 | case IPV6_HOPOPTS: |
346 | case IPV6_RTHDRDSTOPTS: | 361 | case IPV6_RTHDRDSTOPTS: |
347 | case IPV6_RTHDR: | 362 | case IPV6_RTHDR: |
@@ -1104,6 +1119,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1104 | break; | 1119 | break; |
1105 | } | 1120 | } |
1106 | 1121 | ||
1122 | case IPV6_TRANSPARENT: | ||
1123 | val = inet_sk(sk)->transparent; | ||
1124 | break; | ||
1125 | |||
1126 | case IPV6_RECVORIGDSTADDR: | ||
1127 | val = np->rxopt.bits.rxorigdstaddr; | ||
1128 | break; | ||
1129 | |||
1107 | case IPV6_UNICAST_HOPS: | 1130 | case IPV6_UNICAST_HOPS: |
1108 | case IPV6_MULTICAST_HOPS: | 1131 | case IPV6_MULTICAST_HOPS: |
1109 | { | 1132 | { |