34 struct sockaddr arp_ha;
43 #include <sys/param.h>
47 #include <sys/sockio.h>
50 #include <sys/sysctl.h>
53 #include <net/route.h>
59 #include <net/if_arp.h>
62 #include <net/if_dl.h>
64 #if HAVE_NETINET_IF_ETHER_H
65 #include <netinet/if_ether.h>
68 #include <sys/ioctl.h>
98 template <
typename HardwareAddress>
106 template <
typename HardwareAddress>
107 static std::ostream &
112 asHex(ha.sa_data[0] & 0xff).minDigits(2) <<
':' <<
113 asHex(ha.sa_data[1] & 0xff).minDigits(2) <<
':' <<
114 asHex(ha.sa_data[2] & 0xff).minDigits(2) <<
':' <<
115 asHex(ha.sa_data[3] & 0xff).minDigits(2) <<
':' <<
116 asHex(ha.sa_data[4] & 0xff).minDigits(2) <<
':' <<
117 asHex(ha.sa_data[5] & 0xff).minDigits(2);
124 int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0;
126 if (sscanf(asc,
"%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) {
127 debugs(28,
DBG_CRITICAL,
"ERROR: Decode EUI-48: Invalid ethernet address '" << asc <<
"'");
132 eui[0] = (u_char) a1;
133 eui[1] = (u_char) a2;
134 eui[2] = (u_char) a3;
135 eui[3] = (u_char) a4;
136 eui[4] = (u_char) a5;
137 eui[5] = (u_char) a6;
139 debugs(28, 4,
"id=" << (
void*)
this <<
" decoded " << asc);
149 snprintf(buf, len,
"%02x:%02x:%02x:%02x:%02x:%02x",
150 eui[0] & 0xff, eui[1] & 0xff,
151 eui[2] & 0xff, eui[3] & 0xff,
152 eui[4] & 0xff, eui[5] & 0xff);
154 debugs(28, 4,
"id=" << (
void*)
this <<
" encoded " << buf);
167 unsigned char ifbuffer[
sizeof(
struct ifreq) * 64];
174 int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
197 struct arpreq arpReq;
198 memset(&arpReq,
'\0',
sizeof(arpReq));
200 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
204 debugs(28, 4,
"id=" << (
void*)
this <<
" query ARP table");
205 if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
209 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
210 debugs(28, 4,
"id=" << (
void*)
this <<
" ... not an Ethernet interface: " << arpReq.arp_ha.sa_data);
215 debugs(28, 4,
"id=" <<
static_cast<void*
>(
this) <<
" got address " <<
AsEui48(&arpReq.arp_ha));
217 set(arpReq.arp_ha.sa_data, 6);
222 ifc.ifc_len =
sizeof(ifbuffer);
224 ifc.ifc_buf = (
char *)ifbuffer;
226 if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) {
234 if (ifc.ifc_len > (
int)
sizeof(ifbuffer)) {
243 debugs(28, 4,
"id=" << (
void*)
this <<
" query ARP on each interface (" << ifc.ifc_len <<
" found)");
244 while (offset < ifc.ifc_len) {
246 ifr = (
struct ifreq *) (ifbuffer + offset);
247 offset +=
sizeof(*ifr);
249 debugs(28, 4,
"id=" << (
void*)
this <<
" found interface " << ifr->ifr_name);
252 if (!strncmp(ifr->ifr_name,
"lo", 2))
255 if (strchr(ifr->ifr_name,
':'))
258 debugs(28, 4,
"id=" << (
void*)
this <<
" looking up ARP address for " << ipAddr <<
" on " << ifr->ifr_name);
262 memset(&arpReq,
'\0',
sizeof(arpReq));
264 sa = (sockaddr_in*)&arpReq.arp_pa;
267 strncpy(arpReq.arp_dev, ifr->ifr_name,
sizeof(arpReq.arp_dev) - 1);
269 arpReq.arp_dev[
sizeof(arpReq.arp_dev) - 1] =
'\0';
272 if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) {
275 if (ENXIO != xerrno && ENODEV != xerrno)
282 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
283 debugs(28, 4,
"id=" << (
void*)
this <<
"... not an Ethernet interface");
287 debugs(28, 4,
"id=" <<
static_cast<void*
>(
this) <<
" got address " <<
AsEui48(&arpReq.arp_ha) <<
288 " on " << ifr->ifr_name);
290 set(arpReq.arp_ha.sa_data, 6);
304 #elif _SQUID_SOLARIS_
307 int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
316 struct arpreq arpReq;
317 memset(&arpReq,
'\0',
sizeof(arpReq));
319 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
323 if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
330 if (arpReq.arp_ha.sa_data[0] == 0 &&
331 arpReq.arp_ha.sa_data[1] == 0 &&
332 arpReq.arp_ha.sa_data[2] == 0 &&
333 arpReq.arp_ha.sa_data[3] == 0 &&
334 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
341 set(arpReq.arp_ha.sa_data, 6);
347 #elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_
353 char *lim, *buf, *next;
355 struct rt_msghdr *rtm;
357 struct sockaddr_inarp *sin;
359 struct sockaddr_dl *sdl;
364 struct arpreq arpReq;
365 memset(&arpReq,
'\0',
sizeof(arpReq));
367 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
379 mib[4] = NET_RT_FLAGS;
381 #if defined(RTF_LLDATA)
387 if (sysctl(mib, 6,
nullptr, &needed,
nullptr, 0) < 0) {
399 if (sysctl(mib, 6, buf, &needed,
nullptr, 0) < 0) {
408 for (next = buf; next < lim; next += rtm->rtm_msglen) {
410 rtm = (
struct rt_msghdr *) next;
412 sin = (
struct sockaddr_inarp *) (rtm + 1);
416 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
418 sdl = (
struct sockaddr_dl *)((
char *) sin + ROUNDUP(sin->sin_len));
420 if (ipAddr == sin->sin_addr) {
423 arpReq.arp_ha.sa_len =
sizeof(
struct sockaddr);
424 arpReq.arp_ha.sa_family = AF_UNSPEC;
425 memcpy(arpReq.arp_ha.sa_data, LLADDR(sdl), sdl->sdl_alen);
432 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
433 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
434 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
441 set(arpReq.arp_ha.sa_data, 6);
444 #elif _SQUID_WINDOWS_
446 DWORD dwNetTable = 0;
448 DWORD ipNetTableLen = 0;
450 PMIB_IPNETTABLE NetTable =
nullptr;
454 struct arpreq arpReq;
455 memset(&arpReq,
'\0',
sizeof(arpReq));
458 if (GetIpNetTable(NetTable, &ipNetTableLen,
FALSE) != ERROR_INSUFFICIENT_BUFFER) {
465 if ((NetTable = (PMIB_IPNETTABLE)
xmalloc(ipNetTableLen)) ==
NULL) {
472 if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen,
FALSE)) != NO_ERROR) {
480 for (i = 0 ; i < NetTable->dwNumEntries ; ++i) {
482 a.s_addr = NetTable->table[i].dwAddr;
483 if (c == a && (NetTable->table[i].dwType > 2)) {
484 arpReq.arp_ha.sa_family = AF_UNSPEC;
485 memcpy(arpReq.arp_ha.sa_data, NetTable->table[i].bPhysAddr, NetTable->table[i].dwPhysAddrLen);
491 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
492 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
493 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
500 set(arpReq.arp_ha.sa_data, 6);
505 debugs(28,
DBG_CRITICAL,
"ERROR: ARP / MAC / EUI-* operations not supported on this operating system.");
511 debugs(28, 3,
"id=" << (
void*)
this <<
' ' << ipAddr <<
" NOT found");