diff options
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r-- | net/ipv6/raw.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 15b862d8acab..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, |
@@ -582,6 +609,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
582 | struct iovec *iov; | 609 | struct iovec *iov; |
583 | u8 __user *type = NULL; | 610 | u8 __user *type = NULL; |
584 | u8 __user *code = NULL; | 611 | u8 __user *code = NULL; |
612 | #ifdef CONFIG_IPV6_MIP6 | ||
613 | u8 len = 0; | ||
614 | #endif | ||
585 | int probed = 0; | 615 | int probed = 0; |
586 | int i; | 616 | int i; |
587 | 617 | ||
@@ -613,6 +643,20 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
613 | probed = 1; | 643 | probed = 1; |
614 | } | 644 | } |
615 | 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 | ||
616 | default: | 660 | default: |
617 | probed = 1; | 661 | probed = 1; |
618 | break; | 662 | break; |
@@ -759,6 +803,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
759 | 803 | ||
760 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 804 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
761 | fl.oif = np->mcast_oif; | 805 | fl.oif = np->mcast_oif; |
806 | security_sk_classify_flow(sk, &fl); | ||
762 | 807 | ||
763 | err = ip6_dst_lookup(sk, &dst, &fl); | 808 | err = ip6_dst_lookup(sk, &dst, &fl); |
764 | if (err) | 809 | if (err) |