[IPV6] sit: Add missing MODULE_LICENSE
[pandora-kernel.git] / net / ipv6 / raw.c
index fa1ce0a..d09329c 100644 (file)
@@ -50,6 +50,9 @@
 #include <net/udp.h>
 #include <net/inet_common.h>
 #include <net/tcp_states.h>
+#ifdef CONFIG_IPV6_MIP6
+#include <net/mip6.h>
+#endif
 
 #include <net/rawv6.h>
 #include <net/xfrm.h>
@@ -169,8 +172,32 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
        sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
 
        while (sk) {
+               int filtered;
+
                delivered = 1;
-               if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) {
+               switch (nexthdr) {
+               case IPPROTO_ICMPV6:
+                       filtered = icmpv6_filter(sk, skb);
+                       break;
+#ifdef CONFIG_IPV6_MIP6
+               case IPPROTO_MH:
+                       /* XXX: To validate MH only once for each packet,
+                        * this is placed here. It should be after checking
+                        * xfrm policy, however it doesn't. The checking xfrm
+                        * policy is placed in rawv6_rcv() because it is
+                        * required for each socket.
+                        */
+                       filtered = mip6_mh_filter(sk, skb);
+                       break;
+#endif
+               default:
+                       filtered = 0;
+                       break;
+               }
+
+               if (filtered < 0)
+                       break;
+               if (filtered == 0) {
                        struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
 
                        /* Not releasing hash table! */
@@ -334,7 +361,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
        if (!rp->checksum)
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_COMPLETE) {
                skb_postpull_rcsum(skb, skb->nh.raw,
                                   skb->h.raw - skb->nh.raw);
                if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -411,6 +438,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        /* Copy the address. */
        if (sin6) {
                sin6->sin6_family = AF_INET6;
+               sin6->sin6_port = 0;
                ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
                sin6->sin6_flowinfo = 0;
                sin6->sin6_scope_id = 0;
@@ -581,6 +609,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
        struct iovec *iov;
        u8 __user *type = NULL;
        u8 __user *code = NULL;
+#ifdef CONFIG_IPV6_MIP6
+       u8 len = 0;
+#endif
        int probed = 0;
        int i;
 
@@ -612,6 +643,20 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
                                probed = 1;
                        }
                        break;
+#ifdef CONFIG_IPV6_MIP6
+               case IPPROTO_MH:
+                       if (iov->iov_base && iov->iov_len < 1)
+                               break;
+                       /* check if type field is readable or not. */
+                       if (iov->iov_len > 2 - len) {
+                               u8 __user *p = iov->iov_base;
+                               get_user(fl->fl_mh_type, &p[2 - len]);
+                               probed = 1;
+                       } else
+                               len += iov->iov_len;
+
+                       break;
+#endif
                default:
                        probed = 1;
                        break;
@@ -758,6 +803,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 
        if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
                fl.oif = np->mcast_oif;
+       security_sk_classify_flow(sk, &fl);
 
        err = ip6_dst_lookup(sk, &dst, &fl);
        if (err)
@@ -780,7 +826,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
        }
 
        if (tclass < 0) {
-               tclass = np->cork.tclass;
+               tclass = np->tclass;
                if (tclass < 0)
                        tclass = 0;
        }