netfilter: xtables: add struct xt_mtchk_param::net
[safe/jmp/linux-2.6] / net / ipv4 / arp.c
index 46edf1c..c95cd93 100644 (file)
@@ -1,7 +1,5 @@
 /* linux/net/ipv4/arp.c
  *
- * Version:    $Id: arp.c,v 1.99 2001/08/30 22:55:42 davem Exp $
- *
  * Copyright (C) 1994 by Florian  La Roche
  *
  * This module implements the Address Resolution Protocol ARP (RFC 826),
@@ -132,7 +130,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
 static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
 static void parp_redo(struct sk_buff *skb);
 
-static struct neigh_ops arp_generic_ops = {
+static const struct neigh_ops arp_generic_ops = {
        .family =               AF_INET,
        .solicit =              arp_solicit,
        .error_report =         arp_error_report,
@@ -142,7 +140,7 @@ static struct neigh_ops arp_generic_ops = {
        .queue_xmit =           dev_queue_xmit,
 };
 
-static struct neigh_ops arp_hh_ops = {
+static const struct neigh_ops arp_hh_ops = {
        .family =               AF_INET,
        .solicit =              arp_solicit,
        .error_report =         arp_error_report,
@@ -152,7 +150,7 @@ static struct neigh_ops arp_hh_ops = {
        .queue_xmit =           dev_queue_xmit,
 };
 
-static struct neigh_ops arp_direct_ops = {
+static const struct neigh_ops arp_direct_ops = {
        .family =               AF_INET,
        .output =               dev_queue_xmit,
        .connected_output =     dev_queue_xmit,
@@ -160,7 +158,7 @@ static struct neigh_ops arp_direct_ops = {
        .queue_xmit =           dev_queue_xmit,
 };
 
-struct neigh_ops arp_broken_ops = {
+const struct neigh_ops arp_broken_ops = {
        .family =               AF_INET,
        .solicit =              arp_solicit,
        .error_report =         arp_error_report,
@@ -235,8 +233,6 @@ static int arp_constructor(struct neighbour *neigh)
        struct in_device *in_dev;
        struct neigh_parms *parms;
 
-       neigh->type = inet_addr_type(addr);
-
        rcu_read_lock();
        in_dev = __in_dev_get_rcu(dev);
        if (in_dev == NULL) {
@@ -244,6 +240,8 @@ static int arp_constructor(struct neighbour *neigh)
                return -EINVAL;
        }
 
+       neigh->type = inet_addr_type(dev_net(dev), addr);
+
        parms = in_dev->arp_parms;
        __neigh_parms_put(neigh->parms);
        neigh->parms = neigh_parms_clone(parms);
@@ -341,14 +339,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
        switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
        default:
        case 0:         /* By default announce any local IP */
-               if (skb && inet_addr_type(ip_hdr(skb)->saddr) == RTN_LOCAL)
+               if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL)
                        saddr = ip_hdr(skb)->saddr;
                break;
        case 1:         /* Restrict announcements of saddr in same subnet */
                if (!skb)
                        break;
                saddr = ip_hdr(skb)->saddr;
-               if (inet_addr_type(saddr) == RTN_LOCAL) {
+               if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) {
                        /* saddr should be known to target */
                        if (inet_addr_onlink(in_dev, target, saddr))
                                break;
@@ -382,8 +380,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
                read_unlock_bh(&neigh->lock);
 }
 
-static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
-                     __be32 sip, __be32 tip)
+static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
 {
        int scope;
 
@@ -403,7 +400,6 @@ static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
        case 3: /* Do not reply for scope host addresses */
                sip = 0;
                scope = RT_SCOPE_LINK;
-               dev = NULL;
                break;
        case 4: /* Reserved */
        case 5:
@@ -415,7 +411,7 @@ static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
        default:
                return 0;
        }
-       return !inet_confirm_addr(dev, sip, tip, scope);
+       return !inet_confirm_addr(in_dev, sip, tip, scope);
 }
 
 static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
@@ -425,11 +421,12 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
        struct rtable *rt;
        int flag = 0;
        /*unsigned long now; */
+       struct net *net = dev_net(dev);
 
-       if (ip_route_output_key(&rt, &fl) < 0)
+       if (ip_route_output_key(net, &rt, &fl) < 0)
                return 1;
        if (rt->u.dst.dev != dev) {
-               NET_INC_STATS_BH(LINUX_MIB_ARPFILTER);
+               NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER);
                flag = 1;
        }
        ip_rt_put(rt);
@@ -471,15 +468,15 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
        __be32 paddr;
        struct neighbour *n;
 
-       if (!skb->dst) {
+       if (!skb_dst(skb)) {
                printk(KERN_DEBUG "arp_find is called with dst==NULL\n");
                kfree_skb(skb);
                return 1;
        }
 
-       paddr = ((struct rtable*)skb->dst)->rt_gateway;
+       paddr = skb_rtable(skb)->rt_gateway;
 
-       if (arp_set_predefined(inet_addr_type(paddr), haddr, paddr, dev))
+       if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr, paddr, dev))
                return 0;
 
        n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
@@ -509,7 +506,7 @@ int arp_bind_neighbour(struct dst_entry *dst)
        if (dev == NULL)
                return -EINVAL;
        if (n == NULL) {
-               __be32 nexthop = ((struct rtable*)dst)->rt_gateway;
+               __be32 nexthop = ((struct rtable *)dst)->rt_gateway;
                if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
                        nexthop = 0;
                n = __neigh_lookup_errno(
@@ -560,8 +557,9 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt)
  */
 struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
                           struct net_device *dev, __be32 src_ip,
-                          unsigned char *dest_hw, unsigned char *src_hw,
-                          unsigned char *target_hw)
+                          const unsigned char *dest_hw,
+                          const unsigned char *src_hw,
+                          const unsigned char *target_hw)
 {
        struct sk_buff *skb;
        struct arphdr *arp;
@@ -571,14 +569,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
         *      Allocate a buffer
         */
 
-       skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
-                               + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
+       skb = alloc_skb(arp_hdr_len(dev) + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
        if (skb == NULL)
                return NULL;
 
        skb_reserve(skb, LL_RESERVED_SPACE(dev));
        skb_reset_network_header(skb);
-       arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));
+       arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev));
        skb->dev = dev;
        skb->protocol = htons(ETH_P_ARP);
        if (src_hw == NULL)
@@ -643,14 +640,14 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
        arp_ptr=(unsigned char *)(arp+1);
 
        memcpy(arp_ptr, src_hw, dev->addr_len);
-       arp_ptr+=dev->addr_len;
-       memcpy(arp_ptr, &src_ip,4);
-       arp_ptr+=4;
+       arp_ptr += dev->addr_len;
+       memcpy(arp_ptr, &src_ip, 4);
+       arp_ptr += 4;
        if (target_hw != NULL)
                memcpy(arp_ptr, target_hw, dev->addr_len);
        else
                memset(arp_ptr, 0, dev->addr_len);
-       arp_ptr+=dev->addr_len;
+       arp_ptr += dev->addr_len;
        memcpy(arp_ptr, &dest_ip, 4);
 
        return skb;
@@ -666,7 +663,7 @@ out:
 void arp_xmit(struct sk_buff *skb)
 {
        /* Send it off, maybe filter it using firewalling first.  */
-       NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
+       NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
 }
 
 /*
@@ -674,8 +671,8 @@ void arp_xmit(struct sk_buff *skb)
  */
 void arp_send(int type, int ptype, __be32 dest_ip,
              struct net_device *dev, __be32 src_ip,
-             unsigned char *dest_hw, unsigned char *src_hw,
-             unsigned char *target_hw)
+             const unsigned char *dest_hw, const unsigned char *src_hw,
+             const unsigned char *target_hw)
 {
        struct sk_buff *skb;
 
@@ -711,6 +708,7 @@ static int arp_process(struct sk_buff *skb)
        u16 dev_type = dev->type;
        int addr_type;
        struct neighbour *n;
+       struct net *net = dev_net(dev);
 
        /* arp_rcv below verifies the ARP header and verifies the device
         * is ARP'able.
@@ -806,8 +804,8 @@ static int arp_process(struct sk_buff *skb)
        /* Special case: IPv4 duplicate address detection packet (RFC2131) */
        if (sip == 0) {
                if (arp->ar_op == htons(ARPOP_REQUEST) &&
-                   inet_addr_type(tip) == RTN_LOCAL &&
-                   !arp_ignore(in_dev,dev,sip,tip))
+                   inet_addr_type(net, tip) == RTN_LOCAL &&
+                   !arp_ignore(in_dev, sip, tip))
                        arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
                                 dev->dev_addr, sha);
                goto out;
@@ -816,27 +814,27 @@ static int arp_process(struct sk_buff *skb)
        if (arp->ar_op == htons(ARPOP_REQUEST) &&
            ip_route_input(skb, tip, sip, 0, dev) == 0) {
 
-               rt = (struct rtable*)skb->dst;
+               rt = skb_rtable(skb);
                addr_type = rt->rt_type;
 
                if (addr_type == RTN_LOCAL) {
-                       n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
-                       if (n) {
-                               int dont_send = 0;
-
-                               if (!dont_send)
-                                       dont_send |= arp_ignore(in_dev,dev,sip,tip);
-                               if (!dont_send && IN_DEV_ARPFILTER(in_dev))
-                                       dont_send |= arp_filter(sip,tip,dev);
-                               if (!dont_send)
-                                       arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+                       int dont_send = 0;
 
-                               neigh_release(n);
+                       if (!dont_send)
+                               dont_send |= arp_ignore(in_dev,sip,tip);
+                       if (!dont_send && IN_DEV_ARPFILTER(in_dev))
+                               dont_send |= arp_filter(sip,tip,dev);
+                       if (!dont_send) {
+                               n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
+                               if (n) {
+                                       arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+                                       neigh_release(n);
+                               }
                        }
                        goto out;
                } else if (IN_DEV_FORWARD(in_dev)) {
                            if (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&
-                            (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &init_net, &tip, dev, 0))) {
+                            (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
                                n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
                                if (n)
                                        neigh_release(n);
@@ -859,14 +857,14 @@ static int arp_process(struct sk_buff *skb)
 
        n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
 
-       if (IPV4_DEVCONF_ALL(dev->nd_net, ARP_ACCEPT)) {
+       if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) {
                /* Unsolicited ARP is not accepted by default.
                   It is possible, that this option should be enabled for some
                   devices (strip is candidate)
                 */
                if (n == NULL &&
                    arp->ar_op == htons(ARPOP_REPLY) &&
-                   inet_addr_type(sip) == RTN_UNICAST)
+                   inet_addr_type(net, sip) == RTN_UNICAST)
                        n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
        }
 
@@ -894,7 +892,7 @@ static int arp_process(struct sk_buff *skb)
 out:
        if (in_dev)
                in_dev_put(in_dev);
-       kfree_skb(skb);
+       consume_skb(skb);
        return 0;
 }
 
@@ -913,13 +911,8 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
 {
        struct arphdr *arp;
 
-       if (dev->nd_net != &init_net)
-               goto freeskb;
-
        /* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
-       if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
-                                (2 * dev->addr_len) +
-                                (2 * sizeof(u32)))))
+       if (!pskb_may_pull(skb, arp_hdr_len(dev)))
                goto freeskb;
 
        arp = arp_hdr(skb);
@@ -935,7 +928,7 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
 
        memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
 
-       return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
+       return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
 
 freeskb:
        kfree_skb(skb);
@@ -973,13 +966,13 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,
        if (mask && mask != htonl(0xFFFFFFFF))
                return -EINVAL;
        if (!dev && (r->arp_flags & ATF_COM)) {
-               dev = dev_getbyhwaddr(&init_net, r->arp_ha.sa_family,
+               dev = dev_getbyhwaddr(net, r->arp_ha.sa_family,
                                r->arp_ha.sa_data);
                if (!dev)
                        return -ENODEV;
        }
        if (mask) {
-               if (pneigh_lookup(&arp_tbl, &init_net, &ip, dev, 1) == NULL)
+               if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL)
                        return -ENOBUFS;
                return 0;
        }
@@ -1004,7 +997,7 @@ static int arp_req_set(struct net *net, struct arpreq *r,
                struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
                                                         .tos = RTO_ONLINK } } };
                struct rtable * rt;
-               if ((err = ip_route_output_key(&rt, &fl)) != 0)
+               if ((err = ip_route_output_key(net, &rt, &fl)) != 0)
                        return err;
                dev = rt->u.dst.dev;
                ip_rt_put(rt);
@@ -1088,7 +1081,7 @@ static int arp_req_delete_public(struct net *net, struct arpreq *r,
        __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
 
        if (mask == htonl(0xFFFFFFFF))
-               return pneigh_delete(&arp_tbl, &init_net, &ip, dev);
+               return pneigh_delete(&arp_tbl, net, &ip, dev);
 
        if (mask)
                return -EINVAL;
@@ -1111,7 +1104,7 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
                struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
                                                         .tos = RTO_ONLINK } } };
                struct rtable * rt;
-               if ((err = ip_route_output_key(&rt, &fl)) != 0)
+               if ((err = ip_route_output_key(net, &rt, &fl)) != 0)
                        return err;
                dev = rt->u.dst.dev;
                ip_rt_put(rt);
@@ -1166,7 +1159,7 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        rtnl_lock();
        if (r.arp_dev[0]) {
                err = -ENODEV;
-               if ((dev = __dev_get_by_name(&init_net, r.arp_dev)) == NULL)
+               if ((dev = __dev_get_by_name(net, r.arp_dev)) == NULL)
                        goto out;
 
                /* Mmmm... It is wrong... ARPHRD_NETROM==0 */
@@ -1202,13 +1195,10 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
 {
        struct net_device *dev = ptr;
 
-       if (dev->nd_net != &init_net)
-               return NOTIFY_DONE;
-
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&arp_tbl, dev);
-               rt_cache_flush(0);
+               rt_cache_flush(dev_net(dev), 0);
                break;
        default:
                break;
@@ -1235,8 +1225,8 @@ void arp_ifdown(struct net_device *dev)
  *     Called once on startup.
  */
 
-static struct packet_type arp_packet_type = {
-       .type = __constant_htons(ETH_P_ARP),
+static struct packet_type arp_packet_type __read_mostly = {
+       .type = cpu_to_be16(ETH_P_ARP),
        .func = arp_rcv,
 };
 
@@ -1250,7 +1240,7 @@ void __init arp_init(void)
        arp_proc_init();
 #ifdef CONFIG_SYSCTL
        neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
-                             NET_IPV4_NEIGH, "ipv4", NULL, NULL);
+                             NET_IPV4_NEIGH, "ipv4", NULL);
 #endif
        register_netdevice_notifier(&arp_netdev_notifier);
 }
@@ -1297,7 +1287,6 @@ static void arp_format_neigh_entry(struct seq_file *seq,
                                   struct neighbour *n)
 {
        char hbuffer[HBUFFERLEN];
-       const char hexbuf[] = "0123456789ABCDEF";
        int k, j;
        char tbuf[16];
        struct net_device *dev = n->dev;
@@ -1311,15 +1300,17 @@ static void arp_format_neigh_entry(struct seq_file *seq,
        else {
 #endif
        for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) {
-               hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];
-               hbuffer[k++] = hexbuf[n->ha[j] & 15];
+               hbuffer[k++] = hex_asc_hi(n->ha[j]);
+               hbuffer[k++] = hex_asc_lo(n->ha[j]);
                hbuffer[k++] = ':';
        }
-       hbuffer[--k] = 0;
+       if (k != 0)
+               --k;
+       hbuffer[k] = 0;
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
        }
 #endif
-       sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));
+       sprintf(tbuf, "%pI4", n->primary_key);
        seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
                   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
        read_unlock(&n->lock);
@@ -1332,7 +1323,7 @@ static void arp_format_pneigh_entry(struct seq_file *seq,
        int hatype = dev ? dev->type : 0;
        char tbuf[16];
 
-       sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
+       sprintf(tbuf, "%pI4", n->key);
        seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
                   tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",
                   dev ? dev->name : "*");
@@ -1386,13 +1377,29 @@ static const struct file_operations arp_seq_fops = {
        .release        = seq_release_net,
 };
 
-static int __init arp_proc_init(void)
+
+static int __net_init arp_net_init(struct net *net)
 {
-       if (!proc_net_fops_create(&init_net, "arp", S_IRUGO, &arp_seq_fops))
+       if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
                return -ENOMEM;
        return 0;
 }
 
+static void __net_exit arp_net_exit(struct net *net)
+{
+       proc_net_remove(net, "arp");
+}
+
+static struct pernet_operations arp_net_ops = {
+       .init = arp_net_init,
+       .exit = arp_net_exit,
+};
+
+static int __init arp_proc_init(void)
+{
+       return register_pernet_subsys(&arp_net_ops);
+}
+
 #else /* CONFIG_PROC_FS */
 
 static int __init arp_proc_init(void)