]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/raw.c
[IPV6]: Use macro for rwlock_t initialization.
[linux-2.6-omap-h63xx.git] / net / ipv6 / raw.c
index ed3a76b30fd932db9153b0fd31ea405ff97cc15a..66f1d12ea578319f144044313a6776cefa7090d2 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/icmpv6.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/skbuff.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <asm/bug.h>
@@ -174,8 +175,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 +299,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 +335,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 +398,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 {
@@ -441,25 +434,14 @@ out:
        return err;
 
 csum_copy_err:
-       /* Clear queue. */
-       if (flags&MSG_PEEK) {
-               int clear = 0;
-               spin_lock_bh(&sk->sk_receive_queue.lock);
-               if (skb == skb_peek(&sk->sk_receive_queue)) {
-                       __skb_unlink(skb, &sk->sk_receive_queue);
-                       clear = 1;
-               }
-               spin_unlock_bh(&sk->sk_receive_queue.lock);
-               if (clear)
-                       kfree_skb(skb);
-       }
+       skb_kill_datagram(sk, skb, flags);
 
        /* Error for blocking case is chosen to masquerade
           as some normal condition.
         */
        err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
        /* FIXME: increment a raw6 drops counter here */
-       goto out_free;
+       goto out;
 }
 
 static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
@@ -627,7 +609,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 +637,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 +723,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 +740,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 +766,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 +780,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 +794,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);