Merge git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.14+advapi-fix/
[pandora-kernel.git] / net / ipv6 / raw.c
index ed3a76b..a66900c 100644 (file)
@@ -174,8 +174,10 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
                        struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
 
                        /* Not releasing hash table! */
-                       if (clone)
+                       if (clone) {
+                               nf_reset(clone);
                                rawv6_rcv(sk, clone);
+                       }
                }
                sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr,
                                     IP6CB(skb)->iif);
@@ -296,13 +298,10 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb,
 static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
 {
        if ((raw6_sk(sk)->checksum || sk->sk_filter) && 
-           skb->ip_summed != CHECKSUM_UNNECESSARY) {
-               if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
-                       /* FIXME: increment a raw6 drops counter here */
-                       kfree_skb(skb);
-                       return 0;
-               }
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
+           skb_checksum_complete(skb)) {
+               /* FIXME: increment a raw6 drops counter here */
+               kfree_skb(skb);
+               return 0;
        }
 
        /* Charge it to the socket. */
@@ -335,32 +334,25 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
        if (!rp->checksum)
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-       if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
-               if (skb->ip_summed == CHECKSUM_HW) {
-                       skb_postpull_rcsum(skb, skb->nh.raw,
-                                          skb->h.raw - skb->nh.raw);
+       if (skb->ip_summed == CHECKSUM_HW) {
+               skb_postpull_rcsum(skb, skb->nh.raw,
+                                  skb->h.raw - skb->nh.raw);
+               if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+                                    &skb->nh.ipv6h->daddr,
+                                    skb->len, inet->num, skb->csum))
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
-                       if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
-                                           &skb->nh.ipv6h->daddr,
-                                           skb->len, inet->num, skb->csum)) {
-                               LIMIT_NETDEBUG(KERN_DEBUG "raw v6 hw csum failure.\n");
-                               skb->ip_summed = CHECKSUM_NONE;
-                       }
-               }
-               if (skb->ip_summed == CHECKSUM_NONE)
-                       skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
-                                                    &skb->nh.ipv6h->daddr,
-                                                    skb->len, inet->num, 0);
        }
+       if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+               skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+                                            &skb->nh.ipv6h->daddr,
+                                            skb->len, inet->num, 0);
 
        if (inet->hdrincl) {
-               if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
-                   (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
+               if (skb_checksum_complete(skb)) {
                        /* FIXME: increment a raw6 drops counter here */
                        kfree_skb(skb);
                        return 0;
                }
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
 
        rawv6_rcv_skb(sk, skb);
@@ -405,7 +397,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
                err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
        } else if (msg->msg_flags&MSG_TRUNC) {
-               if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)))
+               if (__skb_checksum_complete(skb))
                        goto csum_copy_err;
                err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
        } else {
@@ -627,7 +619,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
 
                        if (type && code) {
                                get_user(fl->fl_icmp_type, type);
-                               __get_user(fl->fl_icmp_code, code);
+                               get_user(fl->fl_icmp_code, code);
                                probed = 1;
                        }
                        break;
@@ -655,6 +647,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
        struct flowi fl;
        int addr_len = msg->msg_namelen;
        int hlimit = -1;
+       int tclass = -1;
        u16 proto;
        int err;
 
@@ -740,7 +733,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(struct ipv6_txoptions);
 
-               err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+               err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -757,6 +750,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                opt = np->opt;
        if (flowlabel)
                opt = fl6_merge_options(&opt_space, flowlabel, opt);
+       opt = ipv6_fixup_options(&opt_space, opt);
 
        fl.proto = proto;
        rawv6_probe_proto_opt(&fl, msg);
@@ -782,10 +776,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
        if (final_p)
                ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
-               dst_release(dst);
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
                goto out;
-       }
 
        if (hlimit < 0) {
                if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -798,6 +790,12 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                        hlimit = ipv6_get_hoplimit(dst->dev);
        }
 
+       if (tclass < 0) {
+               tclass = np->cork.tclass;
+               if (tclass < 0)
+                       tclass = 0;
+       }
+
        if (msg->msg_flags&MSG_CONFIRM)
                goto do_confirm;
 
@@ -806,8 +804,9 @@ back_from_confirm:
                err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags);
        } else {
                lock_sock(sk);
-               err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0,
-                                       hlimit, opt, &fl, (struct rt6_info*)dst, msg->msg_flags);
+               err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
+                       len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst,
+                       msg->msg_flags);
 
                if (err)
                        ip6_flush_pending_frames(sk);