vserver 1.9.5.x5
[linux-2.6.git] / net / ipv4 / icmp.c
index 4a1a8e2..dc2e14f 100644 (file)
@@ -213,8 +213,8 @@ int sysctl_icmp_ratemask = 0x1818;
  */
 
 struct icmp_control {
-       int output_off;         /* Field offset for increment on output */
-       int input_off;          /* Field offset for increment on input */
+       int output_entry;       /* Field for increment on output */
+       int input_entry;        /* Field for increment on input */
        void (*handler)(struct sk_buff *skb);
        short   error;          /* This ICMP is classed as an error message */
 };
@@ -318,8 +318,8 @@ out:
 static void icmp_out_count(int type)
 {
        if (type <= NR_ICMP_TYPES) {
-               ICMP_INC_STATS_FIELD(icmp_pointers[type].output_off);
-               ICMP_INC_STATS(IcmpOutMsgs);
+               ICMP_INC_STATS(icmp_pointers[type].output_entry);
+               ICMP_INC_STATS(ICMP_MIB_OUTMSGS);
        }
 }
 
@@ -327,8 +327,8 @@ static void icmp_out_count(int type)
  *     Checksum each fragment, and on the first include the headers and final
  *     checksum.
  */
-int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
-                  struct sk_buff *skb)
+static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
+                         struct sk_buff *skb)
 {
        struct icmp_bxm *icmp_param = (struct icmp_bxm *)from;
        unsigned int csum;
@@ -338,6 +338,8 @@ int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
                                      to, len, 0);
 
        skb->csum = csum_block_add(skb->csum, csum, odd);
+       if (icmp_pointers[icmp_param->data.icmph.type].error)
+               nf_ct_attach(skb, icmp_param->skb);
        return 0;
 }
 
@@ -375,7 +377,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
 static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 {
        struct sock *sk = icmp_socket->sk;
-       struct inet_opt *inet = inet_sk(sk);
+       struct inet_sock *inet = inet_sk(sk);
        struct ipcm_cookie ipc;
        struct rtable *rt = (struct rtable *)skb->dst;
        u32 daddr;
@@ -478,20 +480,25 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
                 *      ICMP error
                 */
                if (iph->protocol == IPPROTO_ICMP) {
-                       u8 inner_type;
-
-                       if (skb_copy_bits(skb_in,
-                                         skb_in->nh.raw + (iph->ihl << 2) +
-                                         offsetof(struct icmphdr, type) -
-                                         skb_in->data, &inner_type, 1))
+                       u8 _inner_type, *itp;
+
+                       itp = skb_header_pointer(skb_in,
+                                                skb_in->nh.raw +
+                                                (iph->ihl << 2) +
+                                                offsetof(struct icmphdr,
+                                                         type) -
+                                                skb_in->data,
+                                                sizeof(_inner_type),
+                                                &_inner_type);
+                       if (itp == NULL)
                                goto out;
 
                        /*
                         *      Assume any unknown ICMP type is an error. This
                         *      isn't specified by the RFC, but think about it..
                         */
-                       if (inner_type > NR_ICMP_TYPES ||
-                           icmp_pointers[inner_type].error)
+                       if (*itp > NR_ICMP_TYPES ||
+                           icmp_pointers[*itp].error)
                                goto out;
                }
        }
@@ -503,16 +510,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
         *      Construct source address and options.
         */
 
-#ifdef CONFIG_IP_ROUTE_NAT
-       /*
-        *      Restore original addresses if packet has been translated.
-        */
-       if (rt->rt_flags & RTCF_NAT && IPCB(skb_in)->flags & IPSKB_TRANSLATED) {
-               iph->daddr = rt->fl.fl4_dst;
-               iph->saddr = rt->fl.fl4_src;
-       }
-#endif
-
        saddr = iph->daddr;
        if (!(rt->rt_flags & RTCF_LOCAL))
                saddr = 0;
@@ -526,7 +523,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
                                                         .saddr = saddr,
                                                         .tos = RT_TOS(tos) } },
                                    .proto = IPPROTO_ICMP };
-
                if (ip_route_output_key(&rt, &fl))
                    goto out_unlock;
        }
@@ -593,7 +589,7 @@ static void icmp_unreach(struct sk_buff *skb)
        struct iphdr *iph;
        struct icmphdr *icmph;
        int hash, protocol;
-       struct inet_protocol *ipprot;
+       struct net_protocol *ipprot;
        struct sock *raw_sk;
        u32 info = 0;
 
@@ -706,8 +702,7 @@ static void icmp_unreach(struct sk_buff *skb)
        read_unlock(&raw_v4_lock);
 
        rcu_read_lock();
-       ipprot = inet_protos[hash];
-       smp_read_barrier_depends();
+       ipprot = rcu_dereference(inet_protos[hash]);
        if (ipprot && ipprot->err_handler)
                ipprot->err_handler(skb, info);
        rcu_read_unlock();
@@ -715,7 +710,7 @@ static void icmp_unreach(struct sk_buff *skb)
 out:
        return;
 out_err:
-       ICMP_INC_STATS_BH(IcmpInErrors);
+       ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
        goto out;
 }
 
@@ -756,7 +751,7 @@ static void icmp_redirect(struct sk_buff *skb)
 out:
        return;
 out_err:
-       ICMP_INC_STATS_BH(IcmpInErrors);
+       ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
        goto out;
 }
 
@@ -824,7 +819,7 @@ static void icmp_timestamp(struct sk_buff *skb)
 out:
        return;
 out_err:
-       ICMP_INC_STATS_BH(IcmpInErrors);
+       ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
        goto out;
 }
 
@@ -881,7 +876,6 @@ static void icmp_address_reply(struct sk_buff *skb)
        struct net_device *dev = skb->dev;
        struct in_device *in_dev;
        struct in_ifaddr *ifa;
-       u32 mask;
 
        if (skb->len < 4 || !(rt->rt_flags&RTCF_DIRECTSRC))
                goto out;
@@ -889,24 +883,27 @@ static void icmp_address_reply(struct sk_buff *skb)
        in_dev = in_dev_get(dev);
        if (!in_dev)
                goto out;
-       read_lock(&in_dev->lock);
+       rcu_read_lock();
        if (in_dev->ifa_list &&
            IN_DEV_LOG_MARTIANS(in_dev) &&
            IN_DEV_FORWARD(in_dev)) {
-               if (skb_copy_bits(skb, 0, &mask, 4))
+               u32 _mask, *mp;
+
+               mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask);
+               if (mp == NULL)
                        BUG();
                for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
-                       if (mask == ifa->ifa_mask &&
+                       if (*mp == ifa->ifa_mask &&
                            inet_ifa_match(rt->rt_src, ifa))
                                break;
                }
                if (!ifa && net_ratelimit()) {
                        printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from "
                                         "%s/%u.%u.%u.%u\n",
-                              NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src));
+                              NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
                }
        }
-       read_unlock(&in_dev->lock);
+       rcu_read_unlock();
        in_dev_put(in_dev);
 out:;
 }
@@ -923,7 +920,7 @@ int icmp_rcv(struct sk_buff *skb)
        struct icmphdr *icmph;
        struct rtable *rt = (struct rtable *)skb->dst;
 
-       ICMP_INC_STATS_BH(IcmpInMsgs);
+       ICMP_INC_STATS_BH(ICMP_MIB_INMSGS);
 
        switch (skb->ip_summed) {
        case CHECKSUM_HW:
@@ -975,14 +972,14 @@ int icmp_rcv(struct sk_buff *skb)
                }
        }
 
-       ICMP_INC_STATS_BH_FIELD(icmp_pointers[icmph->type].input_off);
+       ICMP_INC_STATS_BH(icmp_pointers[icmph->type].input_entry);
        icmp_pointers[icmph->type].handler(skb);
 
 drop:
        kfree_skb(skb);
        return 0;
 error:
-       ICMP_INC_STATS_BH(IcmpInErrors);
+       ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
        goto drop;
 }
 
@@ -991,116 +988,116 @@ error:
  */
 static struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
        [ICMP_ECHOREPLY] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutEchoReps),
-               .input_off = offsetof(struct icmp_mib, IcmpInEchoReps),
+               .output_entry = ICMP_MIB_OUTECHOREPS,
+               .input_entry = ICMP_MIB_INECHOREPS,
                .handler = icmp_discard,
        },
        [1] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib,IcmpInErrors),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_INERRORS,
                .handler = icmp_discard,
                .error = 1,
        },
        [2] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib,IcmpInErrors),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_INERRORS,
                .handler = icmp_discard,
                .error = 1,
        },
        [ICMP_DEST_UNREACH] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutDestUnreachs),
-               .input_off = offsetof(struct icmp_mib, IcmpInDestUnreachs),
+               .output_entry = ICMP_MIB_OUTDESTUNREACHS,
+               .input_entry = ICMP_MIB_INDESTUNREACHS,
                .handler = icmp_unreach,
                .error = 1,
        },
        [ICMP_SOURCE_QUENCH] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutSrcQuenchs),
-               .input_off = offsetof(struct icmp_mib, IcmpInSrcQuenchs),
+               .output_entry = ICMP_MIB_OUTSRCQUENCHS,
+               .input_entry = ICMP_MIB_INSRCQUENCHS,
                .handler = icmp_unreach,
                .error = 1,
        },
        [ICMP_REDIRECT] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutRedirects),
-               .input_off = offsetof(struct icmp_mib, IcmpInRedirects),
+               .output_entry = ICMP_MIB_OUTREDIRECTS,
+               .input_entry = ICMP_MIB_INREDIRECTS,
                .handler = icmp_redirect,
                .error = 1,
        },
        [6] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib, IcmpInErrors),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_INERRORS,
                .handler = icmp_discard,
                .error = 1,
        },
        [7] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib, IcmpInErrors),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_INERRORS,
                .handler = icmp_discard,
                .error = 1,
        },
        [ICMP_ECHO] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutEchos),
-               .input_off = offsetof(struct icmp_mib, IcmpInEchos),
+               .output_entry = ICMP_MIB_OUTECHOS,
+               .input_entry = ICMP_MIB_INECHOS,
                .handler = icmp_echo,
        },
        [9] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib, IcmpInErrors),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_INERRORS,
                .handler = icmp_discard,
                .error = 1,
        },
        [10] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib, IcmpInErrors),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_INERRORS,
                .handler = icmp_discard,
                .error = 1,
        },
        [ICMP_TIME_EXCEEDED] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutTimeExcds),
-               .input_off = offsetof(struct icmp_mib,IcmpInTimeExcds),
+               .output_entry = ICMP_MIB_OUTTIMEEXCDS,
+               .input_entry = ICMP_MIB_INTIMEEXCDS,
                .handler = icmp_unreach,
                .error = 1,
        },
        [ICMP_PARAMETERPROB] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutParmProbs),
-               .input_off = offsetof(struct icmp_mib, IcmpInParmProbs),
+               .output_entry = ICMP_MIB_OUTPARMPROBS,
+               .input_entry = ICMP_MIB_INPARMPROBS,
                .handler = icmp_unreach,
                .error = 1,
        },
        [ICMP_TIMESTAMP] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutTimestamps),
-               .input_off = offsetof(struct icmp_mib, IcmpInTimestamps),
+               .output_entry = ICMP_MIB_OUTTIMESTAMPS,
+               .input_entry = ICMP_MIB_INTIMESTAMPS,
                .handler = icmp_timestamp,
        },
        [ICMP_TIMESTAMPREPLY] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutTimestampReps),
-               .input_off = offsetof(struct icmp_mib, IcmpInTimestampReps),
+               .output_entry = ICMP_MIB_OUTTIMESTAMPREPS,
+               .input_entry = ICMP_MIB_INTIMESTAMPREPS,
                .handler = icmp_discard,
        },
        [ICMP_INFO_REQUEST] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib, dummy),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_DUMMY,
                .handler = icmp_discard,
        },
        [ICMP_INFO_REPLY] = {
-               .output_off = offsetof(struct icmp_mib, dummy),
-               .input_off = offsetof(struct icmp_mib, dummy),
+               .output_entry = ICMP_MIB_DUMMY,
+               .input_entry = ICMP_MIB_DUMMY,
                .handler = icmp_discard,
        },
        [ICMP_ADDRESS] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutAddrMasks),
-               .input_off = offsetof(struct icmp_mib, IcmpInAddrMasks),
+               .output_entry = ICMP_MIB_OUTADDRMASKS,
+               .input_entry = ICMP_MIB_INADDRMASKS,
                .handler = icmp_address,
        },
        [ICMP_ADDRESSREPLY] = {
-               .output_off = offsetof(struct icmp_mib, IcmpOutAddrMaskReps),
-               .input_off = offsetof(struct icmp_mib, IcmpInAddrMaskReps),
+               .output_entry = ICMP_MIB_OUTADDRMASKREPS,
+               .input_entry = ICMP_MIB_INADDRMASKREPS,
                .handler = icmp_address_reply,
        },
 };
 
 void __init icmp_init(struct net_proto_family *ops)
 {
-       struct inet_opt *inet;
+       struct inet_sock *inet;
        int i;
 
        for (i = 0; i < NR_CPUS; i++) {