]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.14+advapi-fix/
authorDavid S. Miller <davem@sunset.davemloft.net>
Mon, 21 Nov 2005 04:52:16 +0000 (20:52 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 21 Nov 2005 04:52:16 +0000 (20:52 -0800)
1  2 
include/net/ipv6.h
net/ipv6/raw.c
net/ipv6/udp.c

diff --combined include/net/ipv6.h
index 6addb4d464d6c87b0b7d9ae2884c46e57c2e8737,53c76c8a69007ba0b6f9c80f852efc8994b061a3..0a2ad51cff8223dd1936e958a498d6dbd8644b2d
@@@ -237,6 -237,8 +237,8 @@@ extern struct ipv6_txoptions *     ipv6_ren
                                                   int newtype,
                                                   struct ipv6_opt_hdr __user *newopt,
                                                   int newoptlen);
+ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
+                                         struct ipv6_txoptions *opt);
  
  extern int ip6_frag_nqueues;
  extern atomic_t ip6_frag_mem;
@@@ -252,25 -254,12 +254,25 @@@ typedef int             (*inet_getfrag_t) (const v
                                           char *,
                                           unsigned int, unsigned int);
  
 -
 -extern int            ipv6_addr_type(const struct in6_addr *addr);
 +extern int __ipv6_addr_type(const struct in6_addr *addr);
 +static inline int ipv6_addr_type(const struct in6_addr *addr)
 +{
 +      return __ipv6_addr_type(addr) & 0xffff;
 +}
  
  static inline int ipv6_addr_scope(const struct in6_addr *addr)
  {
 -      return ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK;
 +      return __ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK;
 +}
 +
 +static inline int __ipv6_addr_src_scope(int type)
 +{
 +      return (type == IPV6_ADDR_ANY ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16));
 +}
 +
 +static inline int ipv6_addr_src_scope(const struct in6_addr *addr)
 +{
 +      return __ipv6_addr_src_scope(__ipv6_addr_type(addr));
  }
  
  static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2)
@@@ -353,54 -342,6 +355,54 @@@ static inline int ipv6_addr_any(const s
                 a->s6_addr32[2] | a->s6_addr32[3] ) == 0); 
  }
  
 +/*
 + * find the first different bit between two addresses
 + * length of address must be a multiple of 32bits
 + */
 +static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen)
 +{
 +      const __u32 *a1 = token1, *a2 = token2;
 +      int i;
 +
 +      addrlen >>= 2;
 +
 +      for (i = 0; i < addrlen; i++) {
 +              __u32 xb = a1[i] ^ a2[i];
 +              if (xb) {
 +                      int j = 31;
 +
 +                      xb = ntohl(xb);
 +                      while ((xb & (1 << j)) == 0)
 +                              j--;
 +
 +                      return (i * 32 + 31 - j);
 +              }
 +      }
 +
 +      /*
 +       *      we should *never* get to this point since that 
 +       *      would mean the addrs are equal
 +       *
 +       *      However, we do get to it 8) And exacly, when
 +       *      addresses are equal 8)
 +       *
 +       *      ip route add 1111::/128 via ...
 +       *      ip route add 1111::/64 via ...
 +       *      and we are here.
 +       *
 +       *      Ideally, this function should stop comparison
 +       *      at prefix length. It does not, but it is still OK,
 +       *      if returned value is greater than prefix length.
 +       *                                      --ANK (980803)
 +       */
 +      return (addrlen << 5);
 +}
 +
 +static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2)
 +{
 +      return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
 +}
 +
  /*
   *    Prototypes exported by ipv6
   */
diff --combined net/ipv6/raw.c
index 8e9628f1c4c5b4bc4f1b858c339950072ad50c7c,d77d3352c96754c5b06e00f5d168762fd2dd1ddd..a66900cda2afc79273b2722c9e6d755a9b8725f9
@@@ -174,10 -174,8 +174,10 @@@ int ipv6_raw_deliver(struct sk_buff *sk
                        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);
@@@ -298,10 -296,13 +298,10 @@@ void rawv6_err(struct sock *sk, struct 
  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. */
@@@ -334,25 -335,32 +334,25 @@@ int rawv6_rcv(struct sock *sk, struct s
        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);
@@@ -397,7 -405,7 +397,7 @@@ static int rawv6_recvmsg(struct kiocb *
        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 {
@@@ -748,7 -756,9 +748,9 @@@ static int rawv6_sendmsg(struct kiocb *
        }
        if (opt == NULL)
                opt = np->opt;
-       opt = fl6_merge_options(&opt_space, flowlabel, 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);
diff --combined net/ipv6/udp.c
index e671153b47b250b9a7d10b2500dc15101c010fc7,e2b87cc68b7b61ac6c9814867257bbdb9bfbee4f..5cc8731eb55b8585a75dfc97ea2226b565e75956
@@@ -248,7 -248,7 +248,7 @@@ try_again
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), 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, sizeof(struct udphdr), msg->msg_iov,
                                              copied);
@@@ -363,10 -363,13 +363,10 @@@ static inline int udpv6_queue_rcv_skb(s
                return -1;
        }
  
 -      if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
 -              if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
 -                      UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
 -                      kfree_skb(skb);
 -                      return 0;
 -              }
 -              skb->ip_summed = CHECKSUM_UNNECESSARY;
 +      if (skb_checksum_complete(skb)) {
 +              UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
 +              kfree_skb(skb);
 +              return 0;
        }
  
        if (sock_queue_rcv_skb(sk,skb)<0) {
@@@ -488,10 -491,13 +488,10 @@@ static int udpv6_rcv(struct sk_buff **p
                uh = skb->h.uh;
        }
  
 -      if (skb->ip_summed==CHECKSUM_HW) {
 +      if (skb->ip_summed == CHECKSUM_HW &&
 +          !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum))
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 -              if (csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) {
 -                      LIMIT_NETDEBUG(KERN_DEBUG "udp v6 hw csum failure.\n");
 -                      skb->ip_summed = CHECKSUM_NONE;
 -              }
 -      }
 +
        if (skb->ip_summed != CHECKSUM_UNNECESSARY)
                skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0);
  
                if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
                        goto discard;
  
 -              if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
 -                  (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)))
 +              if (skb_checksum_complete(skb))
                        goto discard;
                UDP6_INC_STATS_BH(UDP_MIB_NOPORTS);
  
@@@ -771,7 -778,9 +771,9 @@@ do_udp_sendmsg
        }
        if (opt == NULL)
                opt = np->opt;
-       opt = fl6_merge_options(&opt_space, flowlabel, opt);
+       if (flowlabel)
+               opt = fl6_merge_options(&opt_space, flowlabel, opt);
+       opt = ipv6_fixup_options(&opt_space, opt);
  
        fl->proto = IPPROTO_UDP;
        ipv6_addr_copy(&fl->fl6_dst, daddr);