vserver 1.9.3
[linux-2.6.git] / net / ipv6 / icmp.c
index 4faafff..26273c8 100644 (file)
@@ -139,10 +139,12 @@ static int is_ineligible(struct sk_buff *skb)
        if (ptr < 0)
                return 0;
        if (nexthdr == IPPROTO_ICMPV6) {
-               u8 type;
-               if (skb_copy_bits(skb, ptr+offsetof(struct icmp6hdr, icmp6_type),
-                                 &type, 1)
-                   || !(type & ICMPV6_INFOMSG_MASK))
+               u8 _type, *tp;
+               tp = skb_header_pointer(skb,
+                       ptr+offsetof(struct icmp6hdr, icmp6_type),
+                       sizeof(_type), &_type);
+               if (tp == NULL ||
+                   !(*tp & ICMPV6_INFOMSG_MASK))
                        return 1;
        }
        return 0;
@@ -200,12 +202,13 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
 
 static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
 {
-       u8 optval;
+       u8 _optval, *op;
 
        offset += skb->nh.raw - skb->data;
-       if (skb_copy_bits(skb, offset, &optval, 1))
+       op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval);
+       if (op == NULL)
                return 1;
-       return (optval&0xC0) == 0x80;
+       return (*op & 0xC0) == 0x80;
 }
 
 int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len)
@@ -369,6 +372,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
        err = ip6_dst_lookup(sk, &dst, &fl);
        if (err)
                goto out;
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+               goto out_dst_release;
 
        if (hlimit < 0) {
                if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -455,6 +460,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        err = ip6_dst_lookup(sk, &dst, &fl);
        if (err)
                goto out;
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+               goto out_dst_release;
 
        if (hlimit < 0) {
                if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -486,6 +493,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 out_put: 
        if (likely(idev != NULL))
                in6_dev_put(idev);
+out_dst_release:
        dst_release(dst);
 out: 
        icmpv6_xmit_unlock();
@@ -530,8 +538,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
        hash = nexthdr & (MAX_INET_PROTOS - 1);
 
        rcu_read_lock();
-       ipprot = inet6_protos[hash];
-       smp_read_barrier_depends();
+       ipprot = rcu_dereference(inet6_protos[hash]);
        if (ipprot && ipprot->err_handler)
                ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
        rcu_read_unlock();