X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Ficmp.c;h=26273c82f9fc3c348cb10e8b6b1f7fc97a9a2b6e;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=24e3def47237022b3fec75a03f19e2bc81e0c65a;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 24e3def47..26273c82f 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -55,7 +55,7 @@ #include #include -#include +#include #include #include #include @@ -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; @@ -174,7 +176,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, */ dst = ip6_route_output(sk, fl); if (dst->error) { - IP6_INC_STATS(Ip6OutNoRoutes); + IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { res = 1; } else { @@ -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)) @@ -404,8 +409,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr)); if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) - ICMP6_INC_STATS_OFFSET_BH(idev, Icmp6OutDestUnreachs, type - ICMPV6_DEST_UNREACH); - ICMP6_INC_STATS_BH(idev, Icmp6OutMsgs); + ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_OUTDESTUNREACHS, type - ICMPV6_DEST_UNREACH); + ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); out_put: if (likely(idev != NULL)) @@ -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)) @@ -480,12 +487,13 @@ static void icmpv6_echo_reply(struct sk_buff *skb) } err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); - ICMP6_INC_STATS_BH(idev, Icmp6OutEchoReplies); - ICMP6_INC_STATS_BH(idev, Icmp6OutMsgs); + ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTECHOREPLIES); + ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); 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(); @@ -560,7 +567,7 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) struct icmp6hdr *hdr; int type; - ICMP6_INC_STATS_BH(idev, Icmp6InMsgs); + ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS); saddr = &skb->nh.ipv6h->saddr; daddr = &skb->nh.ipv6h->daddr; @@ -593,9 +600,9 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) type = hdr->icmp6_type; if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) - ICMP6_INC_STATS_OFFSET_BH(idev, Icmp6InDestUnreachs, type - ICMPV6_DEST_UNREACH); + ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INDESTUNREACHS, type - ICMPV6_DEST_UNREACH); else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT) - ICMP6_INC_STATS_OFFSET_BH(idev, Icmp6InEchos, type - ICMPV6_ECHO_REQUEST); + ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INECHOS, type - ICMPV6_ECHO_REQUEST); switch (type) { case ICMPV6_ECHO_REQUEST: @@ -646,7 +653,13 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) break; case ICMPV6_MGM_REDUCTION: + case ICMPV6_NI_QUERY: + case ICMPV6_NI_REPLY: case ICMPV6_MLD2_REPORT: + case ICMPV6_DHAAD_REQUEST: + case ICMPV6_DHAAD_REPLY: + case ICMPV6_MOBILE_PREFIX_SOL: + case ICMPV6_MOBILE_PREFIX_ADV: break; default: @@ -668,7 +681,7 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) return 0; discard_it: - ICMP6_INC_STATS_BH(idev, Icmp6InErrors); + ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS); kfree_skb(skb); return 0; }