summaryrefslogtreecommitdiffstats
path: root/net/ipv4/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r--net/ipv4/arp.c86
1 files changed, 58 insertions, 28 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index a3ca88701..0b1ee6387 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1,6 +1,6 @@
/* linux/net/inet/arp.c
*
- * Version: $Id: arp.c,v 1.78 1999/06/09 10:10:36 davem Exp $
+ * Version: $Id: arp.c,v 1.81 1999/08/30 10:17:05 davem Exp $
*
* Copyright (C) 1994 by Florian La Roche
*
@@ -115,6 +115,9 @@
#include <net/netrom.h>
#endif
#endif
+#ifdef CONFIG_ATM_CLIP
+#include <net/atmclip.h>
+#endif
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -127,6 +130,7 @@ static char *ax2asc2(ax25_address *a, char *buf);
/*
* Interface to generic neighbour cache.
*/
+static u32 arp_hash(const void *pkey, const struct net_device *dev);
static int arp_constructor(struct neighbour *neigh);
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
@@ -186,16 +190,18 @@ struct neigh_table arp_tbl =
AF_INET,
sizeof(struct neighbour) + 4,
4,
+ arp_hash,
arp_constructor,
NULL,
NULL,
parp_redo,
+ "arp_cache",
{ NULL, NULL, &arp_tbl, 0, NULL, NULL,
30*HZ, 1*HZ, 60*HZ, 30*HZ, 5*HZ, 3, 3, 0, 3, 1*HZ, (8*HZ)/10, 64, 1*HZ },
30*HZ, 128, 512, 1024,
};
-int arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir)
+int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir)
{
switch (dev->type) {
case ARPHRD_ETHER:
@@ -213,12 +219,24 @@ int arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir)
}
+static u32 arp_hash(const void *pkey, const struct net_device *dev)
+{
+ u32 hash_val;
+
+ hash_val = *(u32*)pkey;
+ hash_val ^= (hash_val>>16);
+ hash_val ^= hash_val>>8;
+ hash_val ^= hash_val>>3;
+ hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
+
+ return hash_val;
+}
static int arp_constructor(struct neighbour *neigh)
{
u32 addr = *(u32*)neigh->primary_key;
- struct device *dev = neigh->dev;
- struct in_device *in_dev = dev->ip_ptr;
+ struct net_device *dev = neigh->dev;
+ struct in_device *in_dev = in_dev_get(dev);
if (in_dev == NULL)
return -EINVAL;
@@ -227,6 +245,8 @@ static int arp_constructor(struct neighbour *neigh)
if (in_dev->arp_parms)
neigh->parms = in_dev->arp_parms;
+ in_dev_put(in_dev);
+
if (dev->hard_header == NULL) {
neigh->nud_state = NUD_NOARP;
neigh->ops = &arp_direct_ops;
@@ -293,7 +313,6 @@ static int arp_constructor(struct neighbour *neigh)
else
neigh->output = neigh->ops->output;
}
-
return 0;
}
@@ -307,7 +326,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
{
u32 saddr;
u8 *dst_ha = NULL;
- struct device *dev = neigh->dev;
+ struct net_device *dev = neigh->dev;
u32 target = *(u32*)neigh->primary_key;
int probes = atomic_read(&neigh->probes);
@@ -345,7 +364,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
* is allowed to use this function, it is scheduled to be removed. --ANK
*/
-static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct device * dev)
+static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct net_device * dev)
{
switch (addr_hint) {
case RTN_LOCAL:
@@ -365,7 +384,7 @@ static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, s
int arp_find(unsigned char *haddr, struct sk_buff *skb)
{
- struct device *dev = skb->dev;
+ struct net_device *dev = skb->dev;
u32 paddr;
struct neighbour *n;
@@ -401,7 +420,7 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
int arp_bind_neighbour(struct dst_entry *dst)
{
- struct device *dev = dst->dev;
+ struct net_device *dev = dst->dev;
if (dev == NULL)
return 0;
@@ -409,7 +428,11 @@ int arp_bind_neighbour(struct dst_entry *dst)
u32 nexthop = ((struct rtable*)dst)->rt_gateway;
if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
nexthop = 0;
- dst->neighbour = __neigh_lookup(&arp_tbl, &nexthop, dev, 1);
+ dst->neighbour = __neigh_lookup(
+#ifdef CONFIG_ATM_CLIP
+ dev->type == ARPHRD_ATM ? &clip_tbl :
+#endif
+ &arp_tbl, &nexthop, dev, 1);
}
return (dst->neighbour != NULL);
}
@@ -424,7 +447,7 @@ int arp_bind_neighbour(struct dst_entry *dst)
*/
void arp_send(int type, int ptype, u32 dest_ip,
- struct device *dev, u32 src_ip,
+ struct net_device *dev, u32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw,
unsigned char *target_hw)
{
@@ -531,7 +554,7 @@ static void parp_redo(struct sk_buff *skb)
* Receive an arp request by the device layer.
*/
-int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
struct arphdr *arp = skb->nh.arph;
unsigned char *arp_ptr= (unsigned char *)(arp+1);
@@ -540,7 +563,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
u32 sip, tip;
u16 dev_type = dev->type;
int addr_type;
- struct in_device *in_dev = dev->ip_ptr;
+ struct in_device *in_dev = in_dev_get(dev);
struct neighbour *n;
/*
@@ -558,6 +581,9 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
arp->ar_pln != 4)
goto out;
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+ goto out_of_mem;
+
switch (dev_type) {
default:
if (arp->ar_pro != __constant_htons(ETH_P_IP))
@@ -610,7 +636,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
#endif
}
- /* Undertsand only these message types */
+ /* Understand only these message types */
if (arp->ar_op != __constant_htons(ARPOP_REPLY) &&
arp->ar_op != __constant_htons(ARPOP_REQUEST))
@@ -685,6 +711,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
} else {
pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb);
+ in_dev_put(in_dev);
return 0;
}
goto out;
@@ -731,6 +758,9 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
out:
kfree_skb(skb);
+ if (in_dev)
+ in_dev_put(in_dev);
+out_of_mem:
return 0;
}
@@ -744,7 +774,7 @@ out:
* Set (create) an ARP cache entry.
*/
-int arp_req_set(struct arpreq *r, struct device * dev)
+int arp_req_set(struct arpreq *r, struct net_device * dev)
{
u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
struct neighbour *neigh;
@@ -768,8 +798,8 @@ int arp_req_set(struct arpreq *r, struct device * dev)
ipv4_devconf.proxy_arp = 1;
return 0;
}
- if (dev->ip_ptr) {
- ((struct in_device*)dev->ip_ptr)->cnf.proxy_arp = 1;
+ if (__in_dev_get(dev)) {
+ __in_dev_get(dev)->cnf.proxy_arp = 1;
return 0;
}
return -ENXIO;
@@ -816,7 +846,7 @@ static unsigned arp_state_to_flags(struct neighbour *neigh)
* Get an ARP cache entry.
*/
-static int arp_req_get(struct arpreq *r, struct device *dev)
+static int arp_req_get(struct arpreq *r, struct net_device *dev)
{
u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
struct neighbour *neigh;
@@ -836,7 +866,7 @@ static int arp_req_get(struct arpreq *r, struct device *dev)
return err;
}
-int arp_req_delete(struct arpreq *r, struct device * dev)
+int arp_req_delete(struct arpreq *r, struct net_device * dev)
{
int err;
u32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
@@ -851,8 +881,8 @@ int arp_req_delete(struct arpreq *r, struct device * dev)
ipv4_devconf.proxy_arp = 0;
return 0;
}
- if (dev->ip_ptr) {
- ((struct in_device*)dev->ip_ptr)->cnf.proxy_arp = 0;
+ if (__in_dev_get(dev)) {
+ __in_dev_get(dev)->cnf.proxy_arp = 0;
return 0;
}
return -ENXIO;
@@ -887,7 +917,7 @@ int arp_ioctl(unsigned int cmd, void *arg)
{
int err;
struct arpreq r;
- struct device * dev = NULL;
+ struct net_device * dev = NULL;
switch(cmd) {
case SIOCDARP:
@@ -915,7 +945,7 @@ int arp_ioctl(unsigned int cmd, void *arg)
rtnl_lock();
if (r.arp_dev[0]) {
err = -ENODEV;
- if ((dev = dev_get(r.arp_dev)) == NULL)
+ if ((dev = __dev_get_by_name(r.arp_dev)) == NULL)
goto out;
/* Mmmm... It is wrong... ARPHRD_NETROM==0 */
@@ -973,7 +1003,7 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy
struct neighbour *n;
read_lock_bh(&arp_tbl.lock);
for (n=arp_tbl.hash_buckets[i]; n; n=n->next) {
- struct device *dev = n->dev;
+ struct net_device *dev = n->dev;
int hatype = dev->type;
/* Do not confuse users "arp -a" with magic entries */
@@ -1028,7 +1058,7 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy
for (i=0; i<=PNEIGH_HASHMASK; i++) {
struct pneigh_entry *n;
for (n=arp_tbl.phash_buckets[i]; n; n=n->next) {
- struct device *dev = n->dev;
+ struct net_device *dev = n->dev;
int hatype = dev ? dev->type : 0;
size = sprintf(buffer+len,
@@ -1067,7 +1097,7 @@ done:
It is necessary, that this routine was called after route cache will be
flushed.
*/
-void arp_ifdown(struct device *dev)
+void arp_ifdown(struct net_device *dev)
{
neigh_ifdown(&arp_tbl, dev);
}
@@ -1082,7 +1112,7 @@ static struct packet_type arp_packet_type =
__constant_htons(ETH_P_ARP),
NULL, /* All devices */
arp_rcv,
- NULL,
+ (void*)1,
NULL
};
@@ -1095,7 +1125,7 @@ static struct proc_dir_entry proc_net_arp = {
};
#endif
-__initfunc(void arp_init (void))
+void __init arp_init (void)
{
neigh_table_init(&arp_tbl);