// SPDX-License-Identifier: GPL-2.0-or-later /* linux/net/ipv4/arp.c * * Copyright (C) 1994 by Florian La Roche * * This module implements the Address Resolution Protocol ARP (RFC 826), * which is used to convert IP addresses (or in the future maybe other * high-level addresses) into a low-level hardware address (like an Ethernet * address). * * Fixes: * Alan Cox : Removed the Ethernet assumptions in * Florian's code * Alan Cox : Fixed some small errors in the ARP * logic * Alan Cox : Allow >4K in /proc * Alan Cox : Make ARP add its own protocol entry * Ross Martin : Rewrote arp_rcv() and arp_get_info() * Stephen Henson : Add AX25 support to arp_get_info() * Alan Cox : Drop data when a device is downed. * Alan Cox : Use init_timer(). * Alan Cox : Double lock fixes. * Martin Seine : Move the arphdr structure * to if_arp.h for compatibility. * with BSD based programs. * Andrew Tridgell : Added ARP netmask code and * re-arranged proxy handling. * Alan Cox : Changed to use notifiers. * Niibe Yutaka : Reply for this device or proxies only. * Alan Cox : Don't proxy across hardware types! * Jonathan Naylor : Added support for NET/ROM. * Mike Shaver : RFC1122 checks. * Jonathan Naylor : Only lookup the hardware address for * the correct hardware type. * Germano Caronni : Assorted subtle races. * Craig Schlenter : Don't modify permanent entry * during arp_rcv. * Russ Nelson : Tidied up a few bits. * Alexey Kuznetsov: Major changes to caching and behaviour, * eg intelligent arp probing and * generation * of host down events. * Alan Cox : Missing unlock in device events. * Eckes : ARP ioctl control errors. * Alexey Kuznetsov: Arp free fix. * Manuel Rodriguez: Gratuitous ARP. * 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. * Alan Cox : Took the AP1000 nasty FDDI hack and * folded into the mainstream FDDI code. * Ack spit, Linus how did you allow that * one in... * Jes Sorensen : Make FDDI work again in 2.1.x and * clean up the APFDDI & gen. FDDI bits. * Alexey Kuznetsov: new arp state machine; * now it is in net/core/neighbour.c. * Krzysztof Halasa: Added Frame Relay ARP support. * Arnaldo C. Melo : convert /proc/net/arp to seq_file * Shmulik Hen: Split arp_send to arp_create and * arp_xmit so intermediate drivers like * bonding can change the skb before * sending (e.g. insert 8021q tag). * Harald Welte : convert to make use of jenkins hash * Jesper D. Brouer: Proxy ARP PVLAN RFC 3069 support.
*/
if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP;
neigh->ops = &arp_direct_ops;
neigh->output = neigh_direct_output;
} else { /* Good devices (checked by reading texts, but only Ethernet is tested)
ARPHRD_ETHER: (ethernet, apfddi) ARPHRD_FDDI: (fddi) ARPHRD_IEEE802: (tr) ARPHRD_METRICOM: (strip) ARPHRD_ARCNET: etc. etc. etc.
ARPHRD_IPDDP will also work, if author repairs it. I did not it, because this driver does not work even in old paradigm.
*/
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev); if (!in_dev) {
rcu_read_unlock(); return;
} switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: /* By default announce any local IP */ if (skb && inet_addr_type_dev_table(dev_net(dev), 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_dev_table(dev_net(dev), dev,
saddr) == RTN_LOCAL) { /* saddr should be known to target */ if (inet_addr_onlink(in_dev, target, saddr)) break;
}
saddr = 0; break; case 2: /* Avoid secondary IPs, get a primary/preferred one */ break;
}
rcu_read_unlock();
if (!saddr)
saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES); if (probes < 0) { if (!(READ_ONCE(neigh->nud_state) & NUD_VALID))
pr_debug("trying to ucast probe in NUD_INVALID\n");
neigh_ha_snapshot(dst_ha, neigh, dev);
dst_hw = dst_ha;
} else {
probes -= NEIGH_VAR(neigh->parms, APP_PROBES); if (probes < 0) {
neigh_app_ns(neigh); return;
}
}
staticint arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
{ struct net *net = dev_net(in_dev->dev); int scope;
switch (IN_DEV_ARP_IGNORE(in_dev)) { case 0: /* Reply, the tip is already validated */ return 0; case 1: /* Reply only if tip is configured on the incoming interface */
sip = 0;
scope = RT_SCOPE_HOST; break; case 2: /* * Reply only if tip is configured on the incoming interface * and is in same subnet as sip
*/
scope = RT_SCOPE_HOST; break; case 3: /* Do not reply for scope host addresses */
sip = 0;
scope = RT_SCOPE_LINK;
in_dev = NULL; break; case 4: /* Reserved */ case 5: case 6: case 7: return 0; case 8: /* Do not reply */ return 1; default: return 0;
} return !inet_confirm_addr(net, in_dev, sip, tip, scope);
}
staticint arp_accept(struct in_device *in_dev, __be32 sip)
{ struct net *net = dev_net(in_dev->dev); int scope = RT_SCOPE_LINK;
switch (IN_DEV_ARP_ACCEPT(in_dev)) { case 0: /* Don't create new entries from garp */ return 0; case 1: /* Create new entries from garp */ return 1; case 2: /* Create a neighbor in the arp table only if sip * is in the same subnet as an address configured * on the interface that received the garp message
*/ return !!inet_confirm_addr(net, in_dev, sip, 0, scope); default: return 0;
}
}
staticint 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);
rt = ip_route_output(net, sip, tip, 0, l3mdev_master_ifindex_rcu(dev),
RT_SCOPE_UNIVERSE); if (IS_ERR(rt)) return 1; if (rt->dst.dev != dev) {
__NET_INC_STATS(net, LINUX_MIB_ARPFILTER);
flag = 1;
}
ip_rt_put(rt); return flag;
}
/* * Check if we can use proxy ARP for this path
*/ staticinlineint arp_fwd_proxy(struct in_device *in_dev, struct net_device *dev, struct rtable *rt)
{ struct in_device *out_dev; int imi, omi = -1;
if (rt->dst.dev == dev) return 0;
if (!IN_DEV_PROXY_ARP(in_dev)) return 0;
imi = IN_DEV_MEDIUM_ID(in_dev); if (imi == 0) return 1; if (imi == -1) return 0;
/* place to check for proxy_arp for routes */
out_dev = __in_dev_get_rcu(rt->dst.dev); if (out_dev)
omi = IN_DEV_MEDIUM_ID(out_dev);
return omi != imi && omi != -1;
}
/* * Check for RFC3069 proxy arp private VLAN (allow to send back to same dev) * * RFC3069 supports proxy arp replies back to the same interface. This * is done to support (ethernet) switch features, like RFC 3069, where * the individual ports are not allowed to communicate with each * other, BUT they are allowed to talk to the upstream router. As * described in RFC 3069, it is possible to allow these hosts to * communicate through the upstream router, by proxy_arp'ing. * * RFC 3069: "VLAN Aggregation for Efficient IP Address Allocation" * * This technology is known by different names: * In RFC 3069 it is called VLAN Aggregation. * Cisco and Allied Telesyn call it Private VLAN. * Hewlett-Packard call it Source-Port filtering or port-isolation. * Ericsson call it MAC-Forced Forwarding (RFC Draft). *
*/ staticinlineint arp_fwd_pvlan(struct in_device *in_dev, struct net_device *dev, struct rtable *rt,
__be32 sip, __be32 tip)
{ /* Private VLAN is only concerned about the same ethernet segment */ if (rt->dst.dev != dev) return 0;
/* Don't reply on self probes (often done by windowz boxes)*/ if (sip == tip) return 0;
if (IN_DEV_PROXY_ARP_PVLAN(in_dev)) return 1; else return 0;
}
/* * Interface to link layer: send routine and receive handler.
*/
/* * Create an arp packet. If dest_hw is not set, we create a broadcast * message.
*/ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, constunsignedchar *dest_hw, constunsignedchar *src_hw, constunsignedchar *target_hw)
{ struct sk_buff *skb; struct arphdr *arp; unsignedchar *arp_ptr; int hlen = LL_RESERVED_SPACE(dev); int tlen = dev->needed_tailroom;
/* * Fill the device header for the ARP frame
*/ if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0) goto out;
/* * Fill out the arp protocol part. * * The arp hardware type should match the device type, except for FDDI, * which (according to RFC 1390) should always equal 1 (Ethernet).
*/ /* * Exceptions everywhere. AX.25 uses the AX.25 PID value not the * DIX code for the protocol. Make these device structure fields.
*/ switch (dev->type) { default:
arp->ar_hrd = htons(dev->type);
arp->ar_pro = htons(ETH_P_IP); break;
/* * Send an arp packet.
*/ void arp_xmit(struct sk_buff *skb)
{
rcu_read_lock(); /* Send it off, maybe filter it using firewalling first. */
NF_HOOK(NFPROTO_ARP, NF_ARP_OUT,
dev_net_rcu(skb->dev), NULL, skb, NULL, skb->dev,
arp_xmit_finish);
rcu_read_unlock();
}
EXPORT_SYMBOL(arp_xmit);
staticbool arp_is_garp(struct net *net, struct net_device *dev, int *addr_type, __be16 ar_op,
__be32 sip, __be32 tip, unsignedchar *sha, unsignedchar *tha)
{ bool is_garp = tip == sip;
/* Gratuitous ARP _replies_ also require target hwaddr to be * the same as source.
*/ if (is_garp && ar_op == htons(ARPOP_REPLY))
is_garp = /* IPv4 over IEEE 1394 doesn't provide target * hardware address field in its ARP payload.
*/
tha &&
!memcmp(tha, sha, dev->addr_len);
if (is_garp) {
*addr_type = inet_addr_type_dev_table(net, dev, sip); if (*addr_type != RTN_UNICAST)
is_garp = false;
} return is_garp;
}
/* arp_rcv below verifies the ARP header and verifies the device * is ARP'able.
*/
if (!in_dev) goto out_free_skb;
arp = arp_hdr(skb);
switch (dev_type) { default: if (arp->ar_pro != htons(ETH_P_IP) ||
htons(dev_type) != arp->ar_hrd) goto out_free_skb; break; case ARPHRD_ETHER: case ARPHRD_FDDI: case ARPHRD_IEEE802: /* * ETHERNET, and Fibre Channel (which are IEEE 802 * devices, according to RFC 2625) devices will accept ARP * hardware types of either 1 (Ethernet) or 6 (IEEE 802.2). * This is the case also of FDDI, where the RFC 1390 says that * FDDI devices should accept ARP hardware of (1) Ethernet, * however, to be more robust, we'll accept both 1 (Ethernet) * or 6 (IEEE 802.2)
*/ if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
arp->ar_pro != htons(ETH_P_IP)) goto out_free_skb; break; case ARPHRD_AX25: if (arp->ar_pro != htons(AX25_P_IP) ||
arp->ar_hrd != htons(ARPHRD_AX25)) goto out_free_skb; break; case ARPHRD_NETROM: if (arp->ar_pro != htons(AX25_P_IP) ||
arp->ar_hrd != htons(ARPHRD_NETROM)) goto out_free_skb; break;
}
/* Understand only these message types */
if (arp->ar_op != htons(ARPOP_REPLY) &&
arp->ar_op != htons(ARPOP_REQUEST)) goto out_free_skb;
/* * Extract fields
*/
arp_ptr = (unsignedchar *)(arp + 1);
sha = arp_ptr;
arp_ptr += dev->addr_len;
memcpy(&sip, arp_ptr, 4);
arp_ptr += 4; switch (dev_type) { #if IS_ENABLED(CONFIG_FIREWIRE_NET) case ARPHRD_IEEE1394: break; #endif default:
tha = arp_ptr;
arp_ptr += dev->addr_len;
}
memcpy(&tip, arp_ptr, 4); /* * Check for bad requests for 127.x.x.x and requests for multicast * addresses. If this is one such, delete it.
*/ if (ipv4_is_multicast(tip) ||
(!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip))) goto out_free_skb;
/* * For some 802.11 wireless deployments (and possibly other networks), * there will be an ARP proxy and gratuitous ARP frames are attacks * and thus should not be accepted.
*/ if (sip == tip && IN_DEV_ORCONF(in_dev, DROP_GRATUITOUS_ARP)) goto out_free_skb;
/* * Special case: We must set Frame Relay source Q.922 address
*/ if (dev_type == ARPHRD_DLCI)
sha = dev->broadcast;
/* * Process entry. The idea here is we want to send a reply if it is a * request for us or if it is a request for someone else that we hold * a proxy for. We want to add an entry to our cache if it is a reply * to us or if it is a request for our address. * (The assumption for this last is that if someone is requesting our * address, they are probably intending to talk to us, so it saves time * if we cache their address. Their address is also probably not in * our cache, since ours is not in their cache.) * * Putting this another way, we only care about replies if they are to * us, in which case we add them to the cache. For requests, we care * about those for us and those for our proxies. We reply to both, * and in the case of requests for us we add the requester to the arp * cache.
*/
if (arp_accept(in_dev, sip)) { /* Unsolicited ARP is not accepted by default. It is possible, that this option should be enabled for some devices (strip is candidate)
*/ if (!n &&
(is_garp ||
(arp->ar_op == htons(ARPOP_REPLY) &&
(addr_type == RTN_UNICAST ||
(addr_type < 0 && /* postpone calculation to as late as possible */
inet_addr_type_dev_table(net, dev, sip) ==
RTN_UNICAST)))))
n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
}
if (n) { int state = NUD_REACHABLE; int override;
/* 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.
*/
override = time_after(jiffies,
n->updated +
NEIGH_VAR(n->parms, LOCKTIME)) ||
is_garp;
/* Broadcast replies and request packets do not assert neighbour reachability.
*/ if (arp->ar_op != htons(ARPOP_REPLY) ||
skb->pkt_type != PACKET_HOST)
state = NUD_STALE;
neigh_update(n, sha, state,
override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
neigh_release(n);
}
/* do not tweak dropwatch on an ARP we will ignore */ if (dev->flags & IFF_NOARP ||
skb->pkt_type == PACKET_OTHERHOST ||
skb->pkt_type == PACKET_LOOPBACK) goto consumeskb;
skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) goto out_of_mem;
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
drop_reason = pskb_may_pull_reason(skb, arp_hdr_len(dev)); if (drop_reason != SKB_NOT_DROPPED_YET) goto freeskb;
staticint arp_req_set(struct net *net, struct arpreq *r)
{ struct neighbour *neigh; struct net_device *dev;
__be32 ip; int err;
dev = arp_req_dev(net, r); if (IS_ERR(dev)) return PTR_ERR(dev);
if (r->arp_flags & ATF_PUBL) return arp_req_set_public(net, r, dev);
switch (dev->type) { #if IS_ENABLED(CONFIG_FDDI) case ARPHRD_FDDI: /* * According to RFC 1390, FDDI devices should accept ARP * hardware types of 1 (Ethernet). However, to be more * robust, we'll accept hardware types of either 1 (Ethernet) * or 6 (IEEE 802.2).
*/ if (r->arp_ha.sa_family != ARPHRD_FDDI &&
r->arp_ha.sa_family != ARPHRD_ETHER &&
r->arp_ha.sa_family != ARPHRD_IEEE802) return -EINVAL; break; #endif default: if (r->arp_ha.sa_family != dev->type) return -EINVAL; break;
}
ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);
err = PTR_ERR(neigh); if (!IS_ERR(neigh)) { unsignedint state = NUD_STALE;
if (r->arp_flags & ATF_PERM) {
r->arp_flags |= ATF_COM;
state = NUD_PERMANENT;
}
/* Note, that it is not on notifier chain. It is necessary, that this routine was called after route cache will be flushed.
*/ void arp_ifdown(struct net_device *dev)
{
neigh_ifdown(&arp_tbl, dev);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.