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.c49
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)