patch-2.1.89 linux/net/ipv4/arp.c
Next file: linux/net/ipv4/devinet.c
Previous file: linux/net/ipv4/af_inet.c
Back to the patch index
Back to the overall index
- Lines: 211
- Date:
Sun Mar 1 14:43:44 1998
- Orig file:
v2.1.88/linux/net/ipv4/arp.c
- Orig date:
Mon Feb 23 18:12:12 1998
diff -u --recursive --new-file v2.1.88/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
@@ -53,6 +53,7 @@
* Jonathan Layes : Added arpd support through kerneld
* message queue (960314)
* Mike Shaver : /proc/sys/net/ipv4/arp_* support
+ * Mike McLagan : Routing by source
* Stuart Cheshire : Metricom and grat arp fixes
* *** FOR 2.1 clean this up ***
* Lawrence V. Stefani: (08/12/96) Added FDDI support.
@@ -162,17 +163,18 @@
ip_acct_output
};
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25)
-static struct neigh_ops arp_broken_ops =
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25) || \
+ defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
+struct neigh_ops arp_broken_ops =
{
AF_INET,
NULL,
- NULL,
- NULL,
- neigh_compat_output,
- neigh_compat_output,
+ arp_solicit,
+ arp_error_report,
neigh_compat_output,
neigh_compat_output,
+ ip_acct_output,
+ ip_acct_output,
};
#endif
@@ -186,7 +188,8 @@
NULL,
NULL,
parp_redo,
- { NULL, NULL, 30*HZ, 1*HZ, 60*HZ, 30*HZ, 5*HZ, 3, 3, 0, 3, 1*HZ, (8*HZ)/10, 1*HZ, 64 },
+ { 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, 1*HZ, 64 },
30*HZ, 128, 512, 1024,
};
@@ -542,7 +545,8 @@
* is not from an IP number. We can't currently handle this, so toss
* it.
*/
- if (arp->ar_hln != dev->addr_len ||
+ if (in_dev == NULL ||
+ arp->ar_hln != dev->addr_len ||
dev->flags & IFF_NOARP ||
skb->pkt_type == PACKET_OTHERHOST ||
skb->pkt_type == PACKET_LOOPBACK ||
@@ -588,6 +592,12 @@
#endif
}
+ /* Undertsand only these message types */
+
+ if (arp->ar_op != __constant_htons(ARPOP_REPLY) &&
+ arp->ar_op != __constant_htons(ARPOP_REQUEST))
+ goto out;
+
/*
* Extract fields
*/
@@ -621,21 +631,29 @@
* and in the case of requests for us we add the requester to the arp
* cache.
*/
- switch (arp->ar_op) {
- case __constant_htons(ARPOP_REQUEST):
- if (ip_route_input(skb, tip, sip, 0, dev))
- goto out;
+
+ /* Special case: IPv4 duplicate address detection packet (RFC2131) */
+ if (sip == 0) {
+ if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
+ inet_addr_type(tip) == RTN_LOCAL)
+ arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
+ goto out;
+ }
+
+ if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
+ ip_route_input(skb, tip, sip, 0, dev) == 0) {
+
rt = (struct rtable*)skb->dst;
addr_type = rt->rt_type;
if (addr_type == RTN_LOCAL) {
- struct neighbour *n;
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);
}
- } else if (in_dev && IN_DEV_FORWARD(in_dev)) {
+ goto out;
+ } else if (IN_DEV_FORWARD(in_dev)) {
if ((rt->rt_flags&RTCF_DNAT) ||
(addr_type == RTN_UNICAST && rt->u.dst.dev != dev &&
(IN_DEV_PROXY_ARP(in_dev) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {
@@ -650,26 +668,46 @@
pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb);
return 0;
}
+ goto out;
}
}
- break;
+ }
- case __constant_htons(ARPOP_REPLY):
- if (inet_addr_type(sip) != RTN_UNICAST)
- goto out;
+ /* Update our ARP tables */
+
+ 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 == __constant_htons(ARPOP_REPLY) &&
+ inet_addr_type(sip) == RTN_UNICAST)
n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
- if (n) {
- int state = NUD_REACHABLE;
- int override = 1;
- if (jiffies - n->updated < n->parms->locktime &&
- jiffies - n->updated >= 0)
- override = 0;
- if (skb->pkt_type != PACKET_HOST)
- state = NUD_STALE;
- neigh_update(n, sha, state, override, 1);
- neigh_release(n);
- }
- break;
+#endif
+
+ if (n) {
+ int state = NUD_REACHABLE;
+ int override = 0;
+
+ /* If several different ARP replies follows back-to-back,
+ use the FIRST one. It is possible, if several proxy
+ agents are active. Taking the first reply prevents
+ arp trashing and chooses the fastest router.
+ */
+ if (jiffies - n->updated >= n->parms->locktime)
+ override = 1;
+
+ /* Broadcast replies and request packets
+ do not assert neighbour reachability.
+ */
+ if (arp->ar_op != __constant_htons(ARPOP_REPLY) ||
+ skb->pkt_type != PACKET_HOST)
+ state = NUD_STALE;
+ neigh_update(n, sha, state, override, 1);
+ neigh_release(n);
}
out:
@@ -708,11 +746,11 @@
return 0;
}
if (dev == NULL) {
- ipv4_config.proxy_arp = 1;
+ ipv4_devconf.proxy_arp = 1;
return 0;
}
if (dev->ip_ptr) {
- ((struct in_device*)dev->ip_ptr)->flags |= IFF_IP_PROXYARP;
+ ((struct in_device*)dev->ip_ptr)->cnf.proxy_arp = 1;
return 0;
}
return -ENXIO;
@@ -751,7 +789,7 @@
{
unsigned flags = 0;
if (neigh->nud_state&NUD_PERMANENT)
- flags = ATF_PERM;
+ flags = ATF_PERM|ATF_COM;
else if (neigh->nud_state&NUD_VALID)
flags = ATF_COM;
return flags;
@@ -793,11 +831,11 @@
return pneigh_delete(&arp_tbl, &ip, dev);
if (mask == 0) {
if (dev == NULL) {
- ipv4_config.proxy_arp = 0;
+ ipv4_devconf.proxy_arp = 0;
return 0;
}
if (dev->ip_ptr) {
- ((struct in_device*)dev->ip_ptr)->flags &= ~IFF_IP_PROXYARP;
+ ((struct in_device*)dev->ip_ptr)->cnf.proxy_arp = 0;
return 0;
}
return -ENXIO;
@@ -1049,7 +1087,7 @@
proc_net_register(&proc_net_arp);
#endif
#ifdef CONFIG_SYSCTL
- arp_tbl.parms.sysctl_table = neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
+ neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
#endif
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov