aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index fa1ce0ae123e..d09329ca3267 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -50,6 +50,9 @@
50#include <net/udp.h> 50#include <net/udp.h>
51#include <net/inet_common.h> 51#include <net/inet_common.h>
52#include <net/tcp_states.h> 52#include <net/tcp_states.h>
53#ifdef CONFIG_IPV6_MIP6
54#include <net/mip6.h>
55#endif
53 56
54#include <net/rawv6.h> 57#include <net/rawv6.h>
55#include <net/xfrm.h> 58#include <net/xfrm.h>
@@ -169,8 +172,32 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
169 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); 172 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
170 173
171 while (sk) { 174 while (sk) {
175 int filtered;
176
172 delivered = 1; 177 delivered = 1;
173 if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) { 178 switch (nexthdr) {
179 case IPPROTO_ICMPV6:
180 filtered = icmpv6_filter(sk, skb);
181 break;
182#ifdef CONFIG_IPV6_MIP6
183 case IPPROTO_MH:
184 /* XXX: To validate MH only once for each packet,
185 * this is placed here. It should be after checking
186 * xfrm policy, however it doesn't. The checking xfrm
187 * policy is placed in rawv6_rcv() because it is
188 * required for each socket.
189 */
190 filtered = mip6_mh_filter(sk, skb);
191 break;
192#endif
193 default:
194 filtered = 0;
195 break;
196 }
197
198 if (filtered < 0)
199 break;
200 if (filtered == 0) {
174 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 201 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
175 202
176 /* Not releasing hash table! */ 203 /* Not releasing hash table! */
@@ -334,7 +361,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
334 if (!rp->checksum) 361 if (!rp->checksum)
335 skb->ip_summed = CHECKSUM_UNNECESSARY; 362 skb->ip_summed = CHECKSUM_UNNECESSARY;
336 363
337 if (skb->ip_summed == CHECKSUM_HW) { 364 if (skb->ip_summed == CHECKSUM_COMPLETE) {
338 skb_postpull_rcsum(skb, skb->nh.raw, 365 skb_postpull_rcsum(skb, skb->nh.raw,
339 skb->h.raw - skb->nh.raw); 366 skb->h.raw - skb->nh.raw);
340 if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr, 367 if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -411,6 +438,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
411 /* Copy the address. */ 438 /* Copy the address. */
412 if (sin6) { 439 if (sin6) {
413 sin6->sin6_family = AF_INET6; 440 sin6->sin6_family = AF_INET6;
441 sin6->sin6_port = 0;
414 ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); 442 ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
415 sin6->sin6_flowinfo = 0; 443 sin6->sin6_flowinfo = 0;
416 sin6->sin6_scope_id = 0; 444 sin6->sin6_scope_id = 0;
@@ -581,6 +609,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
581 struct iovec *iov; 609 struct iovec *iov;
582 u8 __user *type = NULL; 610 u8 __user *type = NULL;
583 u8 __user *code = NULL; 611 u8 __user *code = NULL;
612#ifdef CONFIG_IPV6_MIP6
613 u8 len = 0;
614#endif
584 int probed = 0; 615 int probed = 0;
585 int i; 616 int i;
586 617
@@ -612,6 +643,20 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
612 probed = 1; 643 probed = 1;
613 } 644 }
614 break; 645 break;
646#ifdef CONFIG_IPV6_MIP6
647 case IPPROTO_MH:
648 if (iov->iov_base && iov->iov_len < 1)
649 break;
650 /* check if type field is readable or not. */
651 if (iov->iov_len > 2 - len) {
652 u8 __user *p = iov->iov_base;
653 get_user(fl->fl_mh_type, &p[2 - len]);
654 probed = 1;
655 } else
656 len += iov->iov_len;
657
658 break;
659#endif
615 default: 660 default:
616 probed = 1; 661 probed = 1;
617 break; 662 break;
@@ -758,6 +803,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
758 803
759 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) 804 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
760 fl.oif = np->mcast_oif; 805 fl.oif = np->mcast_oif;
806 security_sk_classify_flow(sk, &fl);
761 807
762 err = ip6_dst_lookup(sk, &dst, &fl); 808 err = ip6_dst_lookup(sk, &dst, &fl);
763 if (err) 809 if (err)
@@ -780,7 +826,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
780 } 826 }
781 827
782 if (tclass < 0) { 828 if (tclass < 0) {
783 tclass = np->cork.tclass; 829 tclass = np->tclass;
784 if (tclass < 0) 830 if (tclass < 0)
785 tclass = 0; 831 tclass = 0;
786 } 832 }