ide: make ide_hwif_t.ide_dma_host_on void (v2)
[powerpc.git] / net / ipv6 / exthdrs.c
index 88c96b1..28e0c65 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 /* Changes:
- *     yoshfuji                : ensure not to overrun while parsing 
+ *     yoshfuji                : ensure not to overrun while parsing
  *                               tlv options.
  *     Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
  *     YOSHIFUJI Hideaki @USAGI  Register inbound extension header
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/in6.h>
@@ -167,8 +166,8 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
                                goto bad;
                        for (curr=procs; curr->type >= 0; curr++) {
                                if (curr->type == skb->nh.raw[off]) {
-                                       /* type specific length/alignment 
-                                          checks will be performed in the 
+                                       /* type specific length/alignment
+                                          checks will be performed in the
                                           func(). */
                                        if (curr->func(skbp, off) == 0)
                                                return 0;
@@ -284,10 +283,12 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
 #ifdef CONFIG_IPV6_MIP6
        __u16 dstbuf;
 #endif
+       struct dst_entry *dst;
 
        if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
            !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                IPSTATS_MIB_INHDRERRORS);
                kfree_skb(skb);
                return -1;
        }
@@ -298,7 +299,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
        dstbuf = opt->dst1;
 #endif
 
+       dst = dst_clone(skb->dst);
        if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
+               dst_release(dst);
                skb = *skbp;
                skb->h.raw += ((skb->h.raw[1]+1)<<3);
                opt = IP6CB(skb);
@@ -310,7 +313,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
                return 1;
        }
 
-       IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+       IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
+       dst_release(dst);
        return -1;
 }
 
@@ -365,7 +369,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
 
        if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
            !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                IPSTATS_MIB_INHDRERRORS);
                kfree_skb(skb);
                return -1;
        }
@@ -374,7 +379,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
 
        if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
            skb->pkt_type != PACKET_HOST) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                IPSTATS_MIB_INADDRERRORS);
                kfree_skb(skb);
                return -1;
        }
@@ -388,7 +394,8 @@ looped_back:
                         * processed by own
                         */
                        if (!addr) {
-                               IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+                               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                                IPSTATS_MIB_INADDRERRORS);
                                kfree_skb(skb);
                                return -1;
                        }
@@ -410,7 +417,8 @@ looped_back:
        switch (hdr->type) {
        case IPV6_SRCRT_TYPE_0:
                if (hdr->hdrlen & 0x01) {
-                       IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+                       IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                        IPSTATS_MIB_INHDRERRORS);
                        icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
                        return -1;
                }
@@ -419,14 +427,16 @@ looped_back:
        case IPV6_SRCRT_TYPE_2:
                /* Silently discard invalid RTH type 2 */
                if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
-                       IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+                       IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                        IPSTATS_MIB_INHDRERRORS);
                        kfree_skb(skb);
                        return -1;
                }
                break;
 #endif
        default:
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
                return -1;
        }
@@ -439,7 +449,8 @@ looped_back:
        n = hdr->hdrlen >> 1;
 
        if (hdr->segments_left > n) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
                return -1;
        }
@@ -449,12 +460,14 @@ looped_back:
         */
        if (skb_cloned(skb)) {
                struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
-               kfree_skb(skb);
                /* the copy is a forwarded packet */
                if (skb2 == NULL) {
-                       IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS);      
+                       IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                        IPSTATS_MIB_OUTDISCARDS);
+                       kfree_skb(skb);
                        return -1;
                }
+               kfree_skb(skb);
                *skbp = skb = skb2;
                opt = IP6CB(skb2);
                hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
@@ -475,12 +488,14 @@ looped_back:
                if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
                                     (xfrm_address_t *)&skb->nh.ipv6h->saddr,
                                     IPPROTO_ROUTING) < 0) {
-                       IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+                       IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                        IPSTATS_MIB_INADDRERRORS);
                        kfree_skb(skb);
                        return -1;
                }
                if (!ipv6_chk_home_addr(addr)) {
-                       IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+                       IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                        IPSTATS_MIB_INADDRERRORS);
                        kfree_skb(skb);
                        return -1;
                }
@@ -491,7 +506,8 @@ looped_back:
        }
 
        if (ipv6_addr_is_multicast(addr)) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                IPSTATS_MIB_INADDRERRORS);
                kfree_skb(skb);
                return -1;
        }
@@ -510,7 +526,8 @@ looped_back:
 
        if (skb->dst->dev->flags&IFF_LOOPBACK) {
                if (skb->nh.ipv6h->hop_limit <= 1) {
-                       IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+                       IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                        IPSTATS_MIB_INHDRERRORS);
                        icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
                                    0, skb->dev);
                        kfree_skb(skb);
@@ -554,7 +571,7 @@ void __init ipv6_rthdr_init(void)
    For now we need to test the engine, so that I created
    temporary (or permanent) backdoor.
    If listening socket set IPV6_RTHDR to 2, then we invert header.
-                                                   --ANK (980729)
+                                                  --ANK (980729)
  */
 
 struct ipv6_txoptions *
@@ -617,7 +634,7 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
                return 1;
        }
        LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
-                      skb->nh.raw[optoff+1]);
+                      skb->nh.raw[optoff+1]);
        kfree_skb(skb);
        return 0;
 }
@@ -631,25 +648,26 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
 
        if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
                LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
-                              skb->nh.raw[optoff+1]);
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+                              skb->nh.raw[optoff+1]);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+                                IPSTATS_MIB_INHDRERRORS);
                goto drop;
        }
 
-       pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
+       pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2));
        if (pkt_len <= IPV6_MAXPLEN) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
                return 0;
        }
        if (skb->nh.ipv6h->payload_len) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
                return 0;
        }
 
        if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
-               IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
+               IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
                goto drop;
        }
 
@@ -721,7 +739,7 @@ static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
        int hops;
 
        ihdr = (struct rt0_hdr *) opt;
-       
+
        phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
        memcpy(phdr, ihdr, sizeof(struct rt0_hdr));