if_ether.c (5b628e0c26d11e34ac50d8f83971db6450c9d872) | if_ether.c (54fc657d59324e260dd5cde0d6e7f60d43a41c60) |
---|---|
1/*- 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 66 unchanged lines hidden (view full) --- 75 76#include <security/mac/mac_framework.h> 77 78#define SIN(s) ((struct sockaddr_in *)s) 79#define SDL(s) ((struct sockaddr_dl *)s) 80 81SYSCTL_DECL(_net_link_ether); 82SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); | 1/*- 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 66 unchanged lines hidden (view full) --- 75 76#include <security/mac/mac_framework.h> 77 78#define SIN(s) ((struct sockaddr_in *)s) 79#define SDL(s) ((struct sockaddr_dl *)s) 80 81SYSCTL_DECL(_net_link_ether); 82SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); |
83SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, ""); |
|
83 84VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for 85 * local traffic */ 86 87/* timer values */ 88static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20 89 * minutes */ 90static VNET_DEFINE(int, arp_maxtries) = 5; 91static VNET_DEFINE(int, arp_proxyall); | 84 85VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for 86 * local traffic */ 87 88/* timer values */ 89static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20 90 * minutes */ 91static VNET_DEFINE(int, arp_maxtries) = 5; 92static VNET_DEFINE(int, arp_proxyall); |
93static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */ |
|
92 93#define V_arpt_keep VNET(arpt_keep) 94#define V_arp_maxtries VNET(arp_maxtries) 95#define V_arp_proxyall VNET(arp_proxyall) | 94 95#define V_arpt_keep VNET(arpt_keep) 96#define V_arp_maxtries VNET(arp_maxtries) 97#define V_arp_proxyall VNET(arp_proxyall) |
98#define V_arpstat VNET(arpstat) |
|
96 97SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, 98 &VNET_NAME(arpt_keep), 0, 99 "ARP entry lifetime in seconds"); 100 101SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, 102 &VNET_NAME(arp_maxtries), 0, 103 "ARP resolution attempts before returning error"); 104SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW, 105 &VNET_NAME(useloopback), 0, 106 "Use the loopback interface for local traffic"); 107SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, 108 &VNET_NAME(arp_proxyall), 0, 109 "Enable proxy ARP for all suitable requests"); | 99 100SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, 101 &VNET_NAME(arpt_keep), 0, 102 "ARP entry lifetime in seconds"); 103 104SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, 105 &VNET_NAME(arp_maxtries), 0, 106 "ARP resolution attempts before returning error"); 107SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW, 108 &VNET_NAME(useloopback), 0, 109 "Use the loopback interface for local traffic"); 110SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, 111 &VNET_NAME(arp_proxyall), 0, 112 "Enable proxy ARP for all suitable requests"); |
113SYSCTL_VNET_STRUCT(_net_link_ether_arp, OID_AUTO, stats, CTLFLAG_RW, 114 &VNET_NAME(arpstat), arpstat, 115 "ARP statistics (struct arpstat, net/if_arp.h)"); |
|
110 111static void arp_init(void); 112void arprequest(struct ifnet *, 113 struct in_addr *, struct in_addr *, u_char *); 114static void arpintr(struct mbuf *); 115static void arptimer(void *); 116#ifdef INET 117static void in_arpinput(struct mbuf *); --- 40 unchanged lines hidden (view full) --- 158 struct ifnet *ifp; 159 struct llentry *lle = (struct llentry *)arg; 160 161 if (lle == NULL) { 162 panic("%s: NULL entry!\n", __func__); 163 return; 164 } 165 ifp = lle->lle_tbl->llt_ifp; | 116 117static void arp_init(void); 118void arprequest(struct ifnet *, 119 struct in_addr *, struct in_addr *, u_char *); 120static void arpintr(struct mbuf *); 121static void arptimer(void *); 122#ifdef INET 123static void in_arpinput(struct mbuf *); --- 40 unchanged lines hidden (view full) --- 164 struct ifnet *ifp; 165 struct llentry *lle = (struct llentry *)arg; 166 167 if (lle == NULL) { 168 panic("%s: NULL entry!\n", __func__); 169 return; 170 } 171 ifp = lle->lle_tbl->llt_ifp; |
172 CURVNET_SET(ifp->if_vnet); |
|
166 IF_AFDATA_LOCK(ifp); 167 LLE_WLOCK(lle); | 173 IF_AFDATA_LOCK(ifp); 174 LLE_WLOCK(lle); |
168 if (((lle->la_flags & LLE_DELETED) 169 || (time_second >= lle->la_expire)) 170 && (!callout_pending(&lle->la_timer) && 171 callout_active(&lle->la_timer))) | 175 if (((lle->la_flags & LLE_DELETED) || 176 (time_second >= lle->la_expire)) && 177 (!callout_pending(&lle->la_timer) && 178 callout_active(&lle->la_timer))) { |
172 (void) llentry_free(lle); | 179 (void) llentry_free(lle); |
173 else { | 180 ARPSTAT_INC(timeouts); 181 } else { |
174 /* 175 * Still valid, just drop our reference 176 */ 177 LLE_FREE_LOCKED(lle); 178 } 179 IF_AFDATA_UNLOCK(ifp); | 182 /* 183 * Still valid, just drop our reference 184 */ 185 LLE_FREE_LOCKED(lle); 186 } 187 IF_AFDATA_UNLOCK(ifp); |
188 CURVNET_RESTORE(); |
|
180} 181 182/* 183 * Broadcast an ARP request. Caller specifies: 184 * - arp header source ip address 185 * - arp header target ip address 186 * - arp header source ethernet address 187 */ --- 45 unchanged lines hidden (view full) --- 233 ah->ar_op = htons(ARPOP_REQUEST); 234 bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln); 235 bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln); 236 bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln); 237 sa.sa_family = AF_ARP; 238 sa.sa_len = 2; 239 m->m_flags |= M_BCAST; 240 (*ifp->if_output)(ifp, m, &sa, NULL); | 189} 190 191/* 192 * Broadcast an ARP request. Caller specifies: 193 * - arp header source ip address 194 * - arp header target ip address 195 * - arp header source ethernet address 196 */ --- 45 unchanged lines hidden (view full) --- 242 ah->ar_op = htons(ARPOP_REQUEST); 243 bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln); 244 bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln); 245 bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln); 246 sa.sa_family = AF_ARP; 247 sa.sa_len = 2; 248 m->m_flags |= M_BCAST; 249 (*ifp->if_output)(ifp, m, &sa, NULL); |
250 ARPSTAT_INC(txrequests); |
|
241} 242 243/* 244 * Resolve an IP address into an ethernet address. 245 * On input: 246 * ifp is the interface we use 247 * rt0 is the route to the final destination (possibly useless) 248 * m is the mbuf. May be NULL if we don't have a packet. --- 85 unchanged lines hidden (view full) --- 334 goto retry; 335 } 336 /* 337 * There is an arptab entry, but no ethernet address 338 * response yet. Replace the held mbuf with this 339 * latest one. 340 */ 341 if (m != NULL) { | 251} 252 253/* 254 * Resolve an IP address into an ethernet address. 255 * On input: 256 * ifp is the interface we use 257 * rt0 is the route to the final destination (possibly useless) 258 * m is the mbuf. May be NULL if we don't have a packet. --- 85 unchanged lines hidden (view full) --- 344 goto retry; 345 } 346 /* 347 * There is an arptab entry, but no ethernet address 348 * response yet. Replace the held mbuf with this 349 * latest one. 350 */ 351 if (m != NULL) { |
342 if (la->la_hold != NULL) | 352 if (la->la_hold != NULL) { |
343 m_freem(la->la_hold); | 353 m_freem(la->la_hold); |
354 ARPSTAT_INC(dropped); 355 } |
|
344 la->la_hold = m; 345 if (renew == 0 && (flags & LLE_EXCLUSIVE)) { 346 flags &= ~LLE_EXCLUSIVE; 347 LLE_DOWNGRADE(la); 348 } 349 350 } 351 /* --- 56 unchanged lines hidden (view full) --- 408 if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { 409 log(LOG_ERR, "arp: runt packet\n"); 410 m_freem(m); 411 return; 412 } 413 ar = mtod(m, struct arphdr *); 414 } 415 | 356 la->la_hold = m; 357 if (renew == 0 && (flags & LLE_EXCLUSIVE)) { 358 flags &= ~LLE_EXCLUSIVE; 359 LLE_DOWNGRADE(la); 360 } 361 362 } 363 /* --- 56 unchanged lines hidden (view full) --- 420 if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { 421 log(LOG_ERR, "arp: runt packet\n"); 422 m_freem(m); 423 return; 424 } 425 ar = mtod(m, struct arphdr *); 426 } 427 |
428 ARPSTAT_INC(received); |
|
416 switch (ntohs(ar->ar_pro)) { 417#ifdef INET 418 case ETHERTYPE_IP: 419 in_arpinput(m); 420 return; 421#endif 422 } 423 m_freem(m); --- 64 unchanged lines hidden (view full) --- 488 return; 489 } 490 491 ah = mtod(m, struct arphdr *); 492 op = ntohs(ah->ar_op); 493 (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 494 (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 495 | 429 switch (ntohs(ar->ar_pro)) { 430#ifdef INET 431 case ETHERTYPE_IP: 432 in_arpinput(m); 433 return; 434#endif 435 } 436 m_freem(m); --- 64 unchanged lines hidden (view full) --- 501 return; 502 } 503 504 ah = mtod(m, struct arphdr *); 505 op = ntohs(ah->ar_op); 506 (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 507 (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 508 |
509 if (op == ARPOP_REPLY) 510 ARPSTAT_INC(rxreplies); 511 |
|
496 /* 497 * For a bridge, we want to check the address irrespective 498 * of the receive interface. (This will change slightly 499 * when we have clusters of interfaces). 500 * If the interface does not match, but the recieving interface 501 * is part of carp, we call carp_iamatch to see if this is a 502 * request for the virtual host ip. 503 * XXX: This is really ugly! --- 94 unchanged lines hidden (view full) --- 598 * potential misconfiguration. 599 */ 600 if (!bridged && isaddr.s_addr == myaddr.s_addr && myaddr.s_addr != 0) { 601 log(LOG_ERR, 602 "arp: %*D is using my IP address %s on %s!\n", 603 ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 604 inet_ntoa(isaddr), ifp->if_xname); 605 itaddr = myaddr; | 512 /* 513 * For a bridge, we want to check the address irrespective 514 * of the receive interface. (This will change slightly 515 * when we have clusters of interfaces). 516 * If the interface does not match, but the recieving interface 517 * is part of carp, we call carp_iamatch to see if this is a 518 * request for the virtual host ip. 519 * XXX: This is really ugly! --- 94 unchanged lines hidden (view full) --- 614 * potential misconfiguration. 615 */ 616 if (!bridged && isaddr.s_addr == myaddr.s_addr && myaddr.s_addr != 0) { 617 log(LOG_ERR, 618 "arp: %*D is using my IP address %s on %s!\n", 619 ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 620 inet_ntoa(isaddr), ifp->if_xname); 621 itaddr = myaddr; |
622 ARPSTAT_INC(dupips); |
|
606 goto reply; 607 } 608 if (ifp->if_flags & IFF_STATICARP) 609 goto reply; 610 611 bzero(&sin, sizeof(sin)); 612 sin.sin_len = sizeof(struct sockaddr_in); 613 sin.sin_family = AF_INET; --- 67 unchanged lines hidden (view full) --- 681 } 682 LLE_WUNLOCK(la); 683 if (hold != NULL) 684 (*ifp->if_output)(ifp, hold, &sa, NULL); 685 } 686reply: 687 if (op != ARPOP_REQUEST) 688 goto drop; | 623 goto reply; 624 } 625 if (ifp->if_flags & IFF_STATICARP) 626 goto reply; 627 628 bzero(&sin, sizeof(sin)); 629 sin.sin_len = sizeof(struct sockaddr_in); 630 sin.sin_family = AF_INET; --- 67 unchanged lines hidden (view full) --- 698 } 699 LLE_WUNLOCK(la); 700 if (hold != NULL) 701 (*ifp->if_output)(ifp, hold, &sa, NULL); 702 } 703reply: 704 if (op != ARPOP_REQUEST) 705 goto drop; |
706 ARPSTAT_INC(rxrequests); |
|
689 690 if (itaddr.s_addr == myaddr.s_addr) { 691 /* Shortcut.. the receiving interface is the target. */ 692 (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 693 (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 694 } else { 695 struct llentry *lle = NULL; 696 --- 72 unchanged lines hidden (view full) --- 769 (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 770 ah->ar_op = htons(ARPOP_REPLY); 771 ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 772 m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 773 m->m_pkthdr.len = m->m_len; 774 sa.sa_family = AF_ARP; 775 sa.sa_len = 2; 776 (*ifp->if_output)(ifp, m, &sa, NULL); | 707 708 if (itaddr.s_addr == myaddr.s_addr) { 709 /* Shortcut.. the receiving interface is the target. */ 710 (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 711 (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 712 } else { 713 struct llentry *lle = NULL; 714 --- 72 unchanged lines hidden (view full) --- 787 (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 788 ah->ar_op = htons(ARPOP_REPLY); 789 ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 790 m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 791 m->m_pkthdr.len = m->m_len; 792 sa.sa_family = AF_ARP; 793 sa.sa_len = 2; 794 (*ifp->if_output)(ifp, m, &sa, NULL); |
795 ARPSTAT_INC(txreplies); |
|
777 return; 778 779drop: 780 m_freem(m); 781} 782#endif 783 784void --- 41 unchanged lines hidden --- | 796 return; 797 798drop: 799 m_freem(m); 800} 801#endif 802 803void --- 41 unchanged lines hidden --- |