-/* linux/net/inet/arp.c
+/* linux/net/ipv4/arp.c
*
* Version: $Id: arp.c,v 1.99 2001/08/30 22:55:42 davem Exp $
*
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/mm.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/fddidevice.h>
.gc_thresh3 = 1024,
};
-int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir)
+int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
{
switch (dev->type) {
case ARPHRD_ETHER:
static int arp_constructor(struct neighbour *neigh)
{
- u32 addr = *(u32*)neigh->primary_key;
+ __be32 addr = *(__be32*)neigh->primary_key;
struct net_device *dev = neigh->dev;
struct in_device *in_dev;
struct neigh_parms *parms;
neigh->type = inet_addr_type(addr);
rcu_read_lock();
- in_dev = rcu_dereference(__in_dev_get(dev));
+ in_dev = __in_dev_get_rcu(dev);
if (in_dev == NULL) {
rcu_read_unlock();
return -EINVAL;
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
{
- u32 saddr = 0;
+ __be32 saddr = 0;
u8 *dst_ha = NULL;
struct net_device *dev = neigh->dev;
- u32 target = *(u32*)neigh->primary_key;
+ __be32 target = *(__be32*)neigh->primary_key;
int probes = atomic_read(&neigh->probes);
struct in_device *in_dev = in_dev_get(dev);
}
static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
- u32 sip, u32 tip)
+ __be32 sip, __be32 tip)
{
int scope;
return !inet_confirm_addr(dev, sip, tip, scope);
}
-static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
+static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
{
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip,
.saddr = tip } } };
* 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 net_device * dev)
+static int arp_set_predefined(int addr_hint, unsigned char * haddr, __be32 paddr, struct net_device * dev)
{
switch (addr_hint) {
case RTN_LOCAL:
int arp_find(unsigned char *haddr, struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- u32 paddr;
+ __be32 paddr;
struct neighbour *n;
if (!skb->dst) {
if (dev == NULL)
return -EINVAL;
if (n == NULL) {
- u32 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(
* Create an arp packet. If (dest_hw == NULL), we create a broadcast
* message.
*/
-struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
- struct net_device *dev, u32 src_ip,
+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)
{
/*
* Create and send an arp packet.
*/
-void arp_send(int type, int ptype, u32 dest_ip,
- struct net_device *dev, u32 src_ip,
+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)
{
arp_xmit(skb);
}
-static void parp_redo(struct sk_buff *skb)
-{
- nf_reset(skb);
- arp_rcv(skb, skb->dev, NULL);
-}
-
/*
* Process an arp request.
*/
unsigned char *arp_ptr;
struct rtable *rt;
unsigned char *sha, *tha;
- u32 sip, tip;
+ __be32 sip, tip;
u16 dev_type = dev->type;
int addr_type;
struct neighbour *n;
if (n)
neigh_release(n);
- if (skb->stamp.tv_sec == LOCALLY_ENQUEUED ||
+ if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
skb->pkt_type == PACKET_HOST ||
in_dev->arp_parms->proxy_delay == 0) {
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
-#ifdef CONFIG_IP_ACCEPT_UNSOLICITED_ARP
- /* 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)
- n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
-#endif
+ if (ipv4_devconf.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)
+ n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
+ }
if (n) {
int state = NUD_REACHABLE;
return 0;
}
+static void parp_redo(struct sk_buff *skb)
+{
+ arp_process(skb);
+}
+
/*
* Receive an arp request from the device layer.
*/
-int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct arphdr *arp;
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
goto out_of_mem;
+ memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
+
return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
freeskb:
static int arp_req_set(struct arpreq *r, struct net_device * dev)
{
- u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+ __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
struct neighbour *neigh;
int err;
if (r->arp_flags&ATF_PUBL) {
- u32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
- if (mask && mask != 0xFFFFFFFF)
+ __be32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
+ if (mask && mask != htonl(0xFFFFFFFF))
return -EINVAL;
if (!dev && (r->arp_flags & ATF_COM)) {
dev = dev_getbyhwaddr(r->arp_ha.sa_family, r->arp_ha.sa_data);
ipv4_devconf.proxy_arp = 1;
return 0;
}
- if (__in_dev_get(dev)) {
- __in_dev_get(dev)->cnf.proxy_arp = 1;
+ if (__in_dev_get_rtnl(dev)) {
+ __in_dev_get_rtnl(dev)->cnf.proxy_arp = 1;
return 0;
}
return -ENXIO;
static int arp_req_get(struct arpreq *r, struct net_device *dev)
{
- u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+ __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
struct neighbour *neigh;
int err = -ENXIO;
static 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;
+ __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
struct neighbour *neigh;
if (r->arp_flags & ATF_PUBL) {
- u32 mask =
+ __be32 mask =
((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
- if (mask == 0xFFFFFFFF)
+ if (mask == htonl(0xFFFFFFFF))
return pneigh_delete(&arp_tbl, &ip, dev);
if (mask == 0) {
if (dev == NULL) {
ipv4_devconf.proxy_arp = 0;
return 0;
}
- if (__in_dev_get(dev)) {
- __in_dev_get(dev)->cnf.proxy_arp = 0;
+ if (__in_dev_get_rtnl(dev)) {
+ __in_dev_get_rtnl(dev)->cnf.proxy_arp = 0;
return 0;
}
return -ENXIO;
arp_proc_init();
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
- NET_IPV4_NEIGH, "ipv4", NULL);
+ NET_IPV4_NEIGH, "ipv4", NULL, NULL);
#endif
register_netdevice_notifier(&arp_netdev_notifier);
}
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct neigh_seq_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
- memset(s, 0, sizeof(*s));
rc = seq_open(file, &arp_seq_ops);
if (rc)
goto out_kfree;
EXPORT_SYMBOL(arp_broken_ops);
EXPORT_SYMBOL(arp_find);
-EXPORT_SYMBOL(arp_rcv);
EXPORT_SYMBOL(arp_create);
EXPORT_SYMBOL(arp_xmit);
EXPORT_SYMBOL(arp_send);