46#include <sys/eventhandler.h>
47#include <sys/kernel.h>
50#include <sys/sysctl.h>
53#include <sys/malloc.h>
55#include <sys/socket.h>
56#include <sys/syslog.h>
59#include <net/if_var.h>
61#include <net/if_types.h>
62#include <net/netisr.h>
63#include <net/ethernet.h>
65#include <net/route/nhop.h>
71#include <net/if_llatbl.h>
77#include <security/mac/mac_framework.h>
79#define SIN(s) ((const struct sockaddr_in *)(s))
95 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
98 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
118#define V_arpt_keep VNET(arpt_keep)
119#define V_arpt_down VNET(arpt_down)
120#define V_arpt_rexmit VNET(arpt_rexmit)
121#define V_arp_maxtries VNET(arp_maxtries)
122#define V_arp_proxyall VNET(arp_proxyall)
123#define V_arp_maxhold VNET(arp_maxhold)
125SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_VNET | CTLFLAG_RW,
126 &VNET_NAME(arpt_keep), 0,
127 "ARP entry lifetime in seconds");
128SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_VNET | CTLFLAG_RW,
129 &VNET_NAME(arp_maxtries), 0,
130 "ARP resolution attempts before returning error");
131SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_VNET | CTLFLAG_RW,
132 &VNET_NAME(arp_proxyall), 0,
133 "Enable proxy ARP for all suitable requests");
134SYSCTL_INT(_net_link_ether_inet, OID_AUTO, wait, CTLFLAG_VNET | CTLFLAG_RW,
135 &VNET_NAME(arpt_down), 0,
136 "Incomplete ARP entry lifetime in seconds");
138 arpstat,
"ARP statistics (struct arpstat, net/if_arp.h)");
139SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxhold, CTLFLAG_VNET | CTLFLAG_RW,
140 &VNET_NAME(arp_maxhold), 0,
141 "Number of packets to hold per ARP entry");
142SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_log_per_second,
144 "Maximum number of remotely triggered ARP messages that can be "
145 "logged per second");
159#define MAX_GARP_RETRANSMITS 16
164 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_MPSAFE,
166 "Number of times to retransmit GARP packets;"
167 " 0 to disable, maximum of 16");
170#define V_arp_log_level VNET(arp_log_level)
171SYSCTL_INT(_net_link_ether_arp, OID_AUTO, log_level, CTLFLAG_VNET | CTLFLAG_RW,
172 &VNET_NAME(arp_log_level), 0,
173 "Minimum log(9) level for recording rate limited arp log messages. "
174 "The higher will be log more (emerg=0, info=6 (default), debug=7).");
175#define ARP_LOG(pri, ...) do { \
176 if ((pri) <= V_arp_log_level && \
177 ppsratecheck(&arp_lastlog, &arp_curpps, arp_maxpps)) \
178 log((pri), "arp: " __VA_ARGS__); \
181static void arpintr(
struct mbuf *);
184static void in_arpinput(
struct mbuf *);
188 struct ifnet *ifp,
int bridged,
struct llentry *la);
190static void arp_iflladdr(
void *arg __unused,
struct ifnet *ifp);
194static const struct netisr_handler
arp_nh = {
197 .nh_proto = NETISR_ARP,
198 .nh_policy = NETISR_POLICY_SOURCE,
207 struct llentry *lle = (
struct llentry *)arg;
210 if (lle->la_flags & LLE_STATIC) {
214 if (callout_pending(&lle->lle_timer)) {
233 ifp = lle->lle_tbl->llt_ifp;
234 CURVNET_SET(ifp->if_vnet);
236 switch (lle->ln_state) {
244 llentry_request_feedback(lle);
251 if (llentry_get_hittime(lle) > 0 && lle->la_preempt > 0) {
253 struct epoch_tracker et;
256 dst = lle->r_l3addr.addr4;
267 if (lle->la_expire > time_uptime) {
279 if ((lle->la_flags & LLE_DELETED) == 0) {
282 if (lle->la_flags & LLE_VALID)
283 evt = LLENTRY_EXPIRED;
285 evt = LLENTRY_TIMEDOUT;
286 EVENTHANDLER_INVOKE(lle_event, lle, evt);
289 callout_stop(&lle->lle_timer);
297 if (lle->la_flags & LLE_LINKED) {
299 lltable_unlink_entry(lle->lle_tbl, lle);
301 IF_AFDATA_UNLOCK(ifp);
303 size_t pkts_dropped = llentry_free(lle);
305 ARPSTAT_ADD(dropped, pkts_dropped);
306 ARPSTAT_INC(timeouts);
321 struct if_encap_req ereq;
324 bzero(buf, *bufsize);
325 bzero(&ereq,
sizeof(ereq));
327 ereq.bufsize = *bufsize;
328 ereq.rtype = IFENCAP_LL;
329 ereq.family = AF_ARP;
330 ereq.lladdr = ar_tha(ah);
331 ereq.hdata = (u_char *)ah;
333 ereq.flags = IFENCAP_FLAG_BROADCAST;
334 error = ifp->if_requestencap(ifp, &ereq);
336 *bufsize = ereq.bufsize;
349 const struct in_addr *tip, u_char *enaddr)
354 u_char *carpaddr = NULL;
355 uint8_t linkhdr[LLE_MAX_LINKHDR];
369 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
370 if (ifa->ifa_addr->sa_family != AF_INET)
374 if ((*carp_iamatch_p)(ifa, &carpaddr) == 0)
376 sip = &
IA_SIN(ifa)->sin_addr;
379 sip = &
IA_SIN(ifa)->sin_addr;
387 printf(
"%s: cannot find matching address\n", __func__);
388 return (EADDRNOTAVAIL);
392 enaddr = carpaddr ? carpaddr : (u_char *)IF_LLADDR(ifp);
394 if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
396 m->m_len =
sizeof(*ah) + 2 *
sizeof(
struct in_addr) +
398 m->m_pkthdr.len = m->m_len;
399 M_ALIGN(m, m->m_len);
400 ah = mtod(m,
struct arphdr *);
401 bzero((caddr_t)ah, m->m_len);
403 mac_netinet_arp_send(ifp, m);
405 ah->ar_pro = htons(ETHERTYPE_IP);
406 ah->ar_hln = ifp->if_addrlen;
407 ah->ar_pln =
sizeof(
struct in_addr);
408 ah->ar_op = htons(ARPOP_REQUEST);
409 bcopy(enaddr, ar_sha(ah), ah->ar_hln);
410 bcopy(sip, ar_spa(ah), ah->ar_pln);
411 bcopy(tip, ar_tpa(ah), ah->ar_pln);
412 sa.sa_family = AF_ARP;
416 bzero(&ro,
sizeof(ro));
417 linkhdrsize =
sizeof(linkhdr);
419 if (error != 0 && error != EAFNOSUPPORT) {
421 ARP_LOG(LOG_ERR,
"Failed to calculate ARP header on %s: %d\n",
422 if_name(ifp), error);
426 ro.ro_prepend = linkhdr;
427 ro.ro_plen = linkhdrsize;
430 m->m_flags |= M_BCAST;
432 error = (*ifp->if_output)(ifp, m, &sa, &ro);
433 ARPSTAT_INC(txrequests);
435 ARPSTAT_INC(txerrors);
436 ARP_LOG(LOG_DEBUG,
"Failed to send ARP packet on %s: %d\n",
437 if_name(ifp), error);
444 const struct in_addr *tip, u_char *enaddr)
463 const struct sockaddr *dst, u_char *desten,
uint32_t *pflags,
464 struct llentry **plle)
466 struct llentry *la = NULL, *la_tmp;
467 struct mbuf *curr = NULL;
468 struct mbuf *
next = NULL;
480 if ((flags & LLE_CREATE) == 0)
481 la = lla_lookup(
LLTABLE(ifp), LLE_EXCLUSIVE, dst);
482 if (la == NULL && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
483 la = lltable_alloc_entry(
LLTABLE(ifp), 0, dst);
485 char addrbuf[INET_ADDRSTRLEN];
488 "arpresolve: can't allocate llinfo for %s on %s\n",
495 IF_AFDATA_WLOCK(ifp);
497 la_tmp = lla_lookup(
LLTABLE(ifp), LLE_EXCLUSIVE, dst);
500 lltable_link_entry(
LLTABLE(ifp), la);
501 IF_AFDATA_WUNLOCK(ifp);
502 if (la_tmp != NULL) {
503 lltable_free_entry(
LLTABLE(ifp), la);
512 if ((la->la_flags & LLE_VALID) &&
513 ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
514 if (flags & LLE_ADDRONLY) {
515 lladdr = la->ll_addr;
516 ll_len = ifp->if_addrlen;
518 lladdr = la->r_linkdata;
519 ll_len = la->r_hdrlen;
521 bcopy(lladdr, desten, ll_len);
524 llentry_provide_feedback(la);
526 *pflags = la->la_flags & (LLE_VALID|LLE_IFADDR);
535 renew = (la->la_asked == 0 || la->la_expire != time_uptime);
544 if (la->la_hold != NULL) {
545 next = la->la_hold->m_nextpkt;
546 m_freem(la->la_hold);
549 ARPSTAT_INC(dropped);
552 if (la->la_hold != NULL) {
554 while (curr->m_nextpkt != NULL)
555 curr = curr->m_nextpkt;
570 error = is_gw != 0 ? EHOSTUNREACH : EHOSTDOWN;
576 la->la_expire = time_uptime;
577 canceled = callout_reset(&la->lle_timer, hz *
V_arpt_down,
615 const struct sockaddr *dst, u_char *desten,
uint32_t *pflags,
616 struct llentry **plle)
618 struct llentry *la = NULL;
628 if (m->m_flags & M_BCAST) {
631 ifp->if_broadcastaddr, ifp->if_addrlen);
634 if (m->m_flags & M_MCAST) {
641 la = lla_lookup(
LLTABLE(ifp), plle ? LLE_EXCLUSIVE : LLE_UNLOCKED, dst);
642 if (la != NULL && (la->r_flags & RLLE_VALID) != 0) {
644 bcopy(la->r_linkdata, desten, la->r_hdrlen);
646 *pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR);
648 llentry_provide_feedback(la);
659 return (
arpresolve_full(ifp, is_gw, la == NULL ? LLE_CREATE : 0, m, dst,
660 desten, pflags, plle));
675 ifp = m->m_pkthdr.rcvif;
677 if (m->m_len <
sizeof(
struct arphdr) &&
678 ((m = m_pullup(m,
sizeof(
struct arphdr))) == NULL)) {
679 ARP_LOG(LOG_NOTICE,
"packet with short header received on %s\n",
683 ar = mtod(m,
struct arphdr *);
686 if (m->m_len < arphdr_len(ar)) {
687 m = m_pullup(m, arphdr_len(ar));
689 ARP_LOG(LOG_NOTICE,
"short packet received on %s\n",
693 ar = mtod(m,
struct arphdr *);
698 switch (ntohs(ar->ar_hrd)) {
700 hlen = ETHER_ADDR_LEN;
703 case ARPHRD_INFINIBAND:
705 layer =
"infiniband";
707 case ARPHRD_IEEE1394:
716 if (ar->ar_hln >= 20)
721 "packet with unknown hardware format 0x%02d received on "
722 "%s\n", ntohs(ar->ar_hrd), if_name(ifp));
727 if (hlen != 0 && hlen != ar->ar_hln) {
729 "packet with invalid %s address length %d received on %s\n",
730 layer, ar->ar_hln, if_name(ifp));
735 ARPSTAT_INC(received);
736 switch (ntohs(ar->ar_pro)) {
761static int log_arp_wrong_iface = 1;
762static int log_arp_movements = 1;
763static int log_arp_permanent_modify = 1;
764static int allow_multicast = 0;
766SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW,
767 &log_arp_wrong_iface, 0,
768 "log arp packets arriving on the wrong interface");
769SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_movements, CTLFLAG_RW,
770 &log_arp_movements, 0,
771 "log arp replies from MACs different than the one in the cache");
772SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_permanent_modify, CTLFLAG_RW,
773 &log_arp_permanent_modify, 0,
774 "log arp replies from MACs different than the one in the permanent arp entry");
775SYSCTL_INT(_net_link_ether_inet, OID_AUTO, allow_multicast, CTLFLAG_RW,
776 &allow_multicast, 0,
"accept multicast addresses");
779in_arpinput(
struct mbuf *m)
782 struct ifnet *ifp = m->m_pkthdr.rcvif;
783 struct llentry *la = NULL, *la_tmp;
787 struct in_addr isaddr, itaddr, myaddr;
788 u_int8_t *enaddr = NULL;
790 int bridged = 0, is_bridge = 0;
793 struct sockaddr *dst;
794 struct nhop_object *nh;
795 uint8_t linkhdr[LLE_MAX_LINKHDR];
800 char addrbuf[INET_ADDRSTRLEN];
805 sin.sin_family = AF_INET;
806 sin.sin_addr.s_addr = 0;
810 if (ifp->if_type == IFT_BRIDGE)
817 ah = mtod(m,
struct arphdr *);
823 if (ah->ar_pln !=
sizeof(
struct in_addr)) {
824 ARP_LOG(LOG_NOTICE,
"requested protocol length != %zu\n",
829 if (allow_multicast == 0 && ETHER_IS_MULTICAST(ar_sha(ah))) {
830 ARP_LOG(LOG_NOTICE,
"%*D is multicast\n",
831 ifp->if_addrlen, (u_char *)ar_sha(ah),
":");
835 op = ntohs(ah->ar_op);
836 (void)memcpy(&isaddr, ar_spa(ah),
sizeof (isaddr));
837 (void)memcpy(&itaddr, ar_tpa(ah),
sizeof (itaddr));
839 if (op == ARPOP_REPLY)
840 ARPSTAT_INC(rxreplies);
847 CK_LIST_FOREACH(ia,
INADDR_HASH(itaddr.s_addr), ia_hash) {
848 if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) ||
849 ia->ia_ifp == ifp) &&
851 (ia->
ia_ifa.ifa_carp == NULL ||
852 (*carp_iamatch_p)(&ia->
ia_ifa, &enaddr))) {
857 CK_LIST_FOREACH(ia,
INADDR_HASH(isaddr.s_addr), ia_hash)
858 if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) ||
859 ia->ia_ifp == ifp) &&
865#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \
866 (ia->ia_ifp->if_bridge == ifp->if_softc && \
867 !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \
868 addr == ia->ia_addr.sin_addr.s_addr)
876 CK_LIST_FOREACH(ia,
INADDR_HASH(itaddr.s_addr), ia_hash) {
877 if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) {
884#undef BDG_MEMBER_MATCHES_ARP
890 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
891 if (ifa->ifa_addr->sa_family == AF_INET &&
892 (ifa->ifa_carp == NULL ||
893 (*carp_iamatch_p)(ifa, &enaddr))) {
907 enaddr = (u_int8_t *)IF_LLADDR(ifp);
908 carped = (ia->
ia_ifa.ifa_carp != NULL);
911 if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen))
913 if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) {
914 ARP_LOG(LOG_NOTICE,
"link address is broadcast for IP address "
919 if (ifp->if_addrlen != ah->ar_hln) {
920 ARP_LOG(LOG_WARNING,
"from %*D: addr len: new %d, "
921 "i/f %d (ignored)\n", ifp->if_addrlen,
922 (u_char *) ar_sha(ah),
":", ah->ar_hln,
933 if (!bridged && !carped && isaddr.s_addr == myaddr.s_addr &&
934 myaddr.s_addr != 0) {
935 ARP_LOG(LOG_ERR,
"%*D is using my IP address %s on %s!\n",
936 ifp->if_addrlen, (u_char *)ar_sha(ah),
":",
942 if (ifp->if_flags & IFF_STATICARP)
945 bzero(&sin,
sizeof(sin));
947 sin.sin_family = AF_INET;
948 sin.sin_addr = isaddr;
949 dst = (
struct sockaddr *)&sin;
950 la = lla_lookup(
LLTABLE(ifp), LLE_EXCLUSIVE, dst);
953 else if (itaddr.s_addr == myaddr.s_addr) {
958 linkhdrsize =
sizeof(linkhdr);
959 if (lltable_calc_llheader(ifp, AF_INET, ar_sha(ah), linkhdr,
960 &linkhdrsize, &lladdr_off) != 0)
964 la = lltable_alloc_entry(
LLTABLE(ifp), 0, dst);
974 lltable_set_entry_addr(ifp, la, linkhdr, linkhdrsize,
977 IF_AFDATA_WLOCK(ifp);
979 la_tmp = lla_lookup(
LLTABLE(ifp), LLE_EXCLUSIVE, dst);
998 lltable_link_entry(
LLTABLE(ifp), la);
999 IF_AFDATA_WUNLOCK(ifp);
1001 if (la_tmp == NULL) {
1006 lltable_free_entry(
LLTABLE(ifp), la);
1015 if (op != ARPOP_REQUEST)
1017 ARPSTAT_INC(rxrequests);
1019 if (itaddr.s_addr == myaddr.s_addr) {
1021 (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
1022 (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
1028 struct llentry *lle;
1030 sin.sin_addr = itaddr;
1031 lle = lla_lookup(
LLTABLE(ifp), 0, (
struct sockaddr *)&sin);
1033 if ((lle != NULL) && (lle->la_flags & LLE_PUB)) {
1034 (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
1035 (void)memcpy(ar_sha(ah), lle->ll_addr, ah->ar_hln);
1054 if (nh->nh_ifp == ifp)
1057 (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
1058 (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
1070 if (nh->nh_ifp != ifp) {
1071 ARP_LOG(LOG_INFO,
"proxy: ignoring request"
1072 " from %s via %s\n",
1079 printf(
"arp: proxying for %s\n",
1085 if (itaddr.s_addr == myaddr.s_addr &&
1086 IN_LINKLOCAL(ntohl(itaddr.s_addr))) {
1088#ifdef DEBUG_LINKLOCAL
1089 printf(
"arp: sending reply for link-local addr %s\n",
1092 m->m_flags |= M_BCAST;
1093 m->m_flags &= ~M_MCAST;
1096 m->m_flags &= ~(M_BCAST|M_MCAST);
1098 (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln);
1099 (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln);
1100 ah->ar_op = htons(ARPOP_REPLY);
1101 ah->ar_pro = htons(ETHERTYPE_IP);
1102 m->m_len =
sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln);
1103 m->m_pkthdr.len = m->m_len;
1104 m->m_pkthdr.rcvif = NULL;
1105 sa.sa_family = AF_ARP;
1109 bzero(&ro,
sizeof(ro));
1110 linkhdrsize =
sizeof(linkhdr);
1118 if (error != 0 && error != EAFNOSUPPORT) {
1119 ARP_LOG(LOG_ERR,
"Failed to calculate ARP header on %s: %d\n",
1120 if_name(ifp), error);
1124 ro.ro_prepend = linkhdr;
1125 ro.ro_plen = linkhdrsize;
1129 (*ifp->if_output)(ifp, m, &sa, &ro);
1130 ARPSTAT_INC(txreplies);
1143 LLE_WLOCK_ASSERT(la);
1145 chain = la->la_hold;
1155 struct mbuf *m_hold, *m_hold_next;
1161 .ro_prepend = la->r_linkdata,
1162 .ro_plen = la->r_hdrlen,
1165 lltable_fill_sa_entry(la, (
struct sockaddr *)&sin);
1167 for (m_hold = chain; m_hold != NULL; m_hold = m_hold_next) {
1168 m_hold_next = m_hold->m_nextpkt;
1169 m_hold->m_nextpkt = NULL;
1171 m_clrprotoflags(m_hold);
1172 (*ifp->if_output)(ifp, m_hold, (
struct sockaddr *)&sin, &ro);
1182 int bridged,
struct llentry *la)
1184 uint8_t linkhdr[LLE_MAX_LINKHDR];
1187 char addrbuf[INET_ADDRSTRLEN];
1189 LLE_WLOCK_ASSERT(la);
1192 if (!bridged && la->lle_tbl->llt_ifp != ifp) {
1193 if (log_arp_wrong_iface)
1194 ARP_LOG(LOG_WARNING,
"%s is on %s "
1195 "but got reply from %*D on %s\n",
1197 la->lle_tbl->llt_ifp->if_xname,
1198 ifp->if_addrlen, (u_char *)ar_sha(ah),
":",
1203 if ((la->la_flags & LLE_VALID) &&
1204 bcmp(ar_sha(ah), la->ll_addr, ifp->if_addrlen)) {
1205 if (la->la_flags & LLE_STATIC) {
1207 if (log_arp_permanent_modify)
1209 "%*D attempts to modify "
1210 "permanent entry for %s on %s\n",
1212 (u_char *)ar_sha(ah),
":",
1217 if (log_arp_movements) {
1218 ARP_LOG(LOG_INFO,
"%s moved from %*D "
1222 (u_char *)la->ll_addr,
":",
1223 ifp->if_addrlen, (u_char *)ar_sha(ah),
":",
1229 linkhdrsize =
sizeof(linkhdr);
1230 if (lltable_calc_llheader(ifp, AF_INET, ar_sha(ah), linkhdr,
1231 &linkhdrsize, &lladdr_off) != 0)
1235 if (memcmp(la->r_linkdata, linkhdr, linkhdrsize) != 0 ||
1236 (la->la_flags & LLE_VALID) == 0) {
1238 if (lltable_try_set_entry_addr(ifp, la, linkhdr, linkhdrsize,
1243 llentry_mark_used(la);
1255 if (la->la_hold != NULL) {
1268 int canceled, wtime;
1270 LLE_WLOCK_ASSERT(la);
1273 EVENTHANDLER_INVOKE(lle_event, la, LLENTRY_RESOLVED);
1275 if (!(la->la_flags & LLE_STATIC)) {
1281 canceled = callout_reset(&la->lle_timer,
1293static __noinline
void
1296 struct llentry *lle, *lle_tmp;
1303 lle = lltable_alloc_entry(
LLTABLE(ifp), LLE_IFADDR | LLE_STATIC, dst);
1305 log(LOG_INFO,
"arp_ifinit: cannot create arp "
1306 "entry for interface address\n");
1310 IF_AFDATA_WLOCK(ifp);
1313 lle_tmp = lla_lookup(
LLTABLE(ifp), LLE_EXCLUSIVE, dst);
1314 if (lle_tmp != NULL)
1315 lltable_unlink_entry(
LLTABLE(ifp), lle_tmp);
1317 lltable_link_entry(
LLTABLE(ifp), lle);
1318 IF_AFDATA_WUNLOCK(ifp);
1320 if (lle_tmp != NULL)
1321 EVENTHANDLER_INVOKE(lle_event, lle_tmp, LLENTRY_EXPIRED);
1323 EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_RESOLVED);
1325 if (lle_tmp != NULL)
1326 lltable_free_entry(
LLTABLE(ifp), lle_tmp);
1337 int rexmit_count = *(
int *)arg1;
1339 error = sysctl_handle_int(oidp, &rexmit_count, 0, req);
1342 if (!error && req->newptr) {
1344 if (rexmit_count < 0) {
1349 *(
int *)arg1 = rexmit_count;
1366 IF_ADDR_WUNLOCK(ia->
ia_ifa.ifa_ifp);
1371 CURVNET_SET(ia->
ia_ifa.ifa_ifp->if_vnet);
1376 IF_ADDR_WUNLOCK(ia->
ia_ifa.ifa_ifp);
1391 IF_ADDR_WLOCK(ia->
ia_ifa.ifa_ifp);
1395 IF_ADDR_WUNLOCK(ia->
ia_ifa.ifa_ifp);
1427 IF_ADDR_WLOCK(ia->
ia_ifa.ifa_ifp);
1433 IF_ADDR_WUNLOCK(ia->
ia_ifa.ifa_ifp);
1439 struct epoch_tracker et;
1441 const struct sockaddr *dst;
1443 if (ifa->ifa_carp != NULL)
1446 dst = ifa->ifa_addr;
1451 NET_EPOCH_ENTER(et);
1473static __noinline
void
1478 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1479 if (ifa->ifa_addr->sa_family == AF_INET)
1492 if (ifp->if_afdata[AF_INET] == NULL)
1495 lltable_update_ifaddr(
LLTABLE(ifp));
1497 if ((ifp->if_flags & IFF_UP) != 0)
1505 if (IS_DEFAULT_VNET(curvnet)) {
1506 netisr_register(&
arp_nh);
1512 netisr_register_vnet(&
arp_nh);
1524vnet_arp_destroy(__unused
void *arg)
1527 netisr_unregister_vnet(&
arp_nh);
1529VNET_SYSUNINIT(vnet_arp_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
1530 vnet_arp_destroy, NULL);
static void arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, int bridged, struct llentry *la)
static void garp_timer_start(struct ifaddr *ifa)
#define MAX_GARP_RETRANSMITS
VNET_PCPUSTAT_SYSINIT(arpstat)
SYSCTL_PROC(_net_link_ether_inet, OID_AUTO, garp_rexmit_count, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_MPSAFE, &garp_rexmit_count, 0, sysctl_garp_rexmit, "I", "Number of times to retransmit GARP packets;" " 0 to disable, maximum of 16")
static int arp_fillheader(struct ifnet *ifp, struct arphdr *ah, int bcast, u_char *buf, size_t *bufsize)
static __noinline void arp_handle_ifllchange(struct ifnet *ifp)
SYSCTL_DECL(_net_link_ether)
static SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "")
SYSCTL_VNET_PCPUSTAT(_net_link_ether_arp, OID_AUTO, stats, struct arpstat, arpstat, "ARP statistics (struct arpstat, net/if_arp.h)")
static void arptimer(void *)
static struct timeval arp_lastlog
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_VNET|CTLFLAG_RW, &VNET_NAME(arpt_keep), 0, "ARP entry lifetime in seconds")
static int sysctl_garp_rexmit(SYSCTL_HANDLER_ARGS)
static eventhandler_tag iflladdr_tag
VNET_PCPUSTAT_DEFINE(struct arpstat, arpstat)
int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags, struct llentry **plle)
static void vnet_arp_init(void)
static __noinline void arp_add_ifa_lle(struct ifnet *ifp, const struct sockaddr *dst)
void arp_announce_ifaddr(struct ifnet *ifp, struct in_addr addr, u_char *enaddr)
static void arp_flush_holdchain(struct ifnet *ifp, struct llentry *la, struct mbuf *chain)
static void arpintr(struct mbuf *)
static struct mbuf * arp_grab_holdchain(struct llentry *la)
static void garp_rexmit(void *arg)
static void arp_mark_lle_reachable(struct llentry *la)
void arprequest(struct ifnet *ifp, const struct in_addr *sip, const struct in_addr *tip, u_char *enaddr)
static int garp_rexmit_count
VNET_SYSINIT(vnet_arp_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND, vnet_arp_init, 0)
static int arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags, struct llentry **plle)
VNET_DEFINE_STATIC(int, arpt_keep)
static void arp_iflladdr(void *arg __unused, struct ifnet *ifp)
static const struct netisr_handler arp_nh
void arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
static int arprequest_internal(struct ifnet *ifp, const struct in_addr *sip, const struct in_addr *tip, u_char *enaddr)
#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr)
VNET_PCPUSTAT_SYSUNINIT(igmpstat)
char * inet_ntoa_r(struct in_addr ina, char *buf)
struct nhop_object * fib4_lookup(uint32_t fibnum, struct in_addr dst, uint32_t scopeid, uint32_t flags, uint32_t flowid)
VNET_SYSUNINIT(divert, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, div_destroy, NULL)
struct sockaddr_in ia_addr
struct callout ia_garp_timer