Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/if_ether.c
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/rmlock.h> | |||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/if_dl.h> | #include <net/if_dl.h> | ||||
#include <net/if_types.h> | #include <net/if_types.h> | ||||
#include <net/netisr.h> | #include <net/netisr.h> | ||||
▲ Show 20 Lines • Show All 710 Lines • ▼ Show 20 Lines | SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_permanent_modify, CTLFLAG_RW, | ||||
&log_arp_permanent_modify, 0, | &log_arp_permanent_modify, 0, | ||||
"log arp replies from MACs different than the one in the permanent arp entry"); | "log arp replies from MACs different than the one in the permanent arp entry"); | ||||
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, allow_multicast, CTLFLAG_RW, | SYSCTL_INT(_net_link_ether_inet, OID_AUTO, allow_multicast, CTLFLAG_RW, | ||||
&allow_multicast, 0, "accept multicast addresses"); | &allow_multicast, 0, "accept multicast addresses"); | ||||
static void | static void | ||||
in_arpinput(struct mbuf *m) | in_arpinput(struct mbuf *m) | ||||
{ | { | ||||
struct rm_priotracker in_ifa_tracker; | |||||
struct arphdr *ah; | struct arphdr *ah; | ||||
struct ifnet *ifp = m->m_pkthdr.rcvif; | struct ifnet *ifp = m->m_pkthdr.rcvif; | ||||
struct llentry *la = NULL, *la_tmp; | struct llentry *la = NULL, *la_tmp; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
struct sockaddr sa; | struct sockaddr sa; | ||||
struct in_addr isaddr, itaddr, myaddr; | struct in_addr isaddr, itaddr, myaddr; | ||||
u_int8_t *enaddr = NULL; | u_int8_t *enaddr = NULL; | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | in_arpinput(struct mbuf *m) | ||||
if (op == ARPOP_REPLY) | if (op == ARPOP_REPLY) | ||||
ARPSTAT_INC(rxreplies); | ARPSTAT_INC(rxreplies); | ||||
/* | /* | ||||
* For a bridge, we want to check the address irrespective | * For a bridge, we want to check the address irrespective | ||||
* of the receive interface. (This will change slightly | * of the receive interface. (This will change slightly | ||||
* when we have clusters of interfaces). | * when we have clusters of interfaces). | ||||
*/ | */ | ||||
IN_IFADDR_RLOCK(&in_ifa_tracker); | CK_LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { | ||||
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { | |||||
if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || | if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || | ||||
ia->ia_ifp == ifp) && | ia->ia_ifp == ifp) && | ||||
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr && | itaddr.s_addr == ia->ia_addr.sin_addr.s_addr && | ||||
(ia->ia_ifa.ifa_carp == NULL || | (ia->ia_ifa.ifa_carp == NULL || | ||||
(*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) { | (*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) { | ||||
ifa_ref(&ia->ia_ifa); | ifa_ref(&ia->ia_ifa); | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | |||||
goto match; | goto match; | ||||
} | } | ||||
} | } | ||||
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) | CK_LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) | ||||
if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || | if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || | ||||
ia->ia_ifp == ifp) && | ia->ia_ifp == ifp) && | ||||
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { | isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { | ||||
ifa_ref(&ia->ia_ifa); | ifa_ref(&ia->ia_ifa); | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | |||||
goto match; | goto match; | ||||
} | } | ||||
#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ | #define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ | ||||
(ia->ia_ifp->if_bridge == ifp->if_softc && \ | (ia->ia_ifp->if_bridge == ifp->if_softc && \ | ||||
!bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ | !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ | ||||
addr == ia->ia_addr.sin_addr.s_addr) | addr == ia->ia_addr.sin_addr.s_addr) | ||||
/* | /* | ||||
* Check the case when bridge shares its MAC address with | * Check the case when bridge shares its MAC address with | ||||
* some of its children, so packets are claimed by bridge | * some of its children, so packets are claimed by bridge | ||||
* itself (bridge_input() does it first), but they are really | * itself (bridge_input() does it first), but they are really | ||||
* meant to be destined to the bridge member. | * meant to be destined to the bridge member. | ||||
*/ | */ | ||||
if (is_bridge) { | if (is_bridge) { | ||||
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { | CK_LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { | ||||
if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { | if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { | ||||
ifa_ref(&ia->ia_ifa); | ifa_ref(&ia->ia_ifa); | ||||
ifp = ia->ia_ifp; | ifp = ia->ia_ifp; | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | |||||
goto match; | goto match; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#undef BDG_MEMBER_MATCHES_ARP | #undef BDG_MEMBER_MATCHES_ARP | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | |||||
/* | /* | ||||
* No match, use the first inet address on the receive interface | * No match, use the first inet address on the receive interface | ||||
* as a dummy address for the rest of the function. | * as a dummy address for the rest of the function. | ||||
*/ | */ | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) | ||||
if (ifa->ifa_addr->sa_family == AF_INET && | if (ifa->ifa_addr->sa_family == AF_INET && | ||||
(ifa->ifa_carp == NULL || | (ifa->ifa_carp == NULL || | ||||
▲ Show 20 Lines • Show All 639 Lines • Show Last 20 Lines |