36 struct sockaddr arp_ha;
45 #include <sys/param.h>
49 #include <sys/sockio.h>
52 #include <sys/sysctl.h>
55 #include <net/route.h>
61 #include <net/if_arp.h>
64 #include <net/if_dl.h>
66 #if HAVE_NETINET_IF_ETHER_H
67 #include <netinet/if_ether.h>
70 #include <sys/ioctl.h>
100 template <
typename HardwareAddress>
108 template <
typename HardwareAddress>
109 static std::ostream &
114 asHex(ha.sa_data[0] & 0xff).minDigits(2) <<
':' <<
115 asHex(ha.sa_data[1] & 0xff).minDigits(2) <<
':' <<
116 asHex(ha.sa_data[2] & 0xff).minDigits(2) <<
':' <<
117 asHex(ha.sa_data[3] & 0xff).minDigits(2) <<
':' <<
118 asHex(ha.sa_data[4] & 0xff).minDigits(2) <<
':' <<
119 asHex(ha.sa_data[5] & 0xff).minDigits(2);
126 int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0;
128 if (sscanf(asc,
"%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) {
129 debugs(28,
DBG_CRITICAL,
"ERROR: Decode EUI-48: Invalid ethernet address '" << asc <<
"'");
134 eui[0] = (u_char) a1;
135 eui[1] = (u_char) a2;
136 eui[2] = (u_char) a3;
137 eui[3] = (u_char) a4;
138 eui[4] = (u_char) a5;
139 eui[5] = (u_char) a6;
141 debugs(28, 4,
"id=" << (
void*)
this <<
" decoded " << asc);
151 snprintf(buf, len,
"%02x:%02x:%02x:%02x:%02x:%02x",
152 eui[0] & 0xff, eui[1] & 0xff,
153 eui[2] & 0xff, eui[3] & 0xff,
154 eui[4] & 0xff, eui[5] & 0xff);
156 debugs(28, 4,
"id=" << (
void*)
this <<
" encoded " << buf);
169 unsigned char ifbuffer[
sizeof(
struct ifreq) * 64];
176 auto tmpSocket =
xsocket(AF_INET,SOCK_STREAM,0);
199 struct arpreq arpReq;
200 memset(&arpReq,
'\0',
sizeof(arpReq));
202 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
206 debugs(28, 4,
"id=" << (
void*)
this <<
" query ARP table");
207 if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
211 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
212 debugs(28, 4,
"id=" << (
void*)
this <<
" ... not an Ethernet interface: " << arpReq.arp_ha.sa_data);
217 debugs(28, 4,
"id=" <<
static_cast<void*
>(
this) <<
" got address " <<
AsEui48(&arpReq.arp_ha));
219 set(arpReq.arp_ha.sa_data, 6);
224 ifc.ifc_len =
sizeof(ifbuffer);
226 ifc.ifc_buf = (
char *)ifbuffer;
228 if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) {
236 if (ifc.ifc_len > (
int)
sizeof(ifbuffer)) {
245 debugs(28, 4,
"id=" << (
void*)
this <<
" query ARP on each interface (" << ifc.ifc_len <<
" found)");
246 while (offset < ifc.ifc_len) {
248 ifr = (
struct ifreq *) (ifbuffer + offset);
249 offset +=
sizeof(*ifr);
251 debugs(28, 4,
"id=" << (
void*)
this <<
" found interface " << ifr->ifr_name);
254 if (!strncmp(ifr->ifr_name,
"lo", 2))
257 if (strchr(ifr->ifr_name,
':'))
260 debugs(28, 4,
"id=" << (
void*)
this <<
" looking up ARP address for " << ipAddr <<
" on " << ifr->ifr_name);
264 memset(&arpReq,
'\0',
sizeof(arpReq));
266 sa = (sockaddr_in*)&arpReq.arp_pa;
269 strncpy(arpReq.arp_dev, ifr->ifr_name,
sizeof(arpReq.arp_dev) - 1);
271 arpReq.arp_dev[
sizeof(arpReq.arp_dev) - 1] =
'\0';
274 if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) {
277 if (ENXIO != xerrno && ENODEV != xerrno)
284 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
285 debugs(28, 4,
"id=" << (
void*)
this <<
"... not an Ethernet interface");
289 debugs(28, 4,
"id=" <<
static_cast<void*
>(
this) <<
" got address " <<
AsEui48(&arpReq.arp_ha) <<
290 " on " << ifr->ifr_name);
292 set(arpReq.arp_ha.sa_data, 6);
306 #elif _SQUID_SOLARIS_
309 auto tmpSocket =
xsocket(AF_INET,SOCK_STREAM,0);
318 struct arpreq arpReq;
319 memset(&arpReq,
'\0',
sizeof(arpReq));
321 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
325 if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
332 if (arpReq.arp_ha.sa_data[0] == 0 &&
333 arpReq.arp_ha.sa_data[1] == 0 &&
334 arpReq.arp_ha.sa_data[2] == 0 &&
335 arpReq.arp_ha.sa_data[3] == 0 &&
336 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
343 set(arpReq.arp_ha.sa_data, 6);
349 #elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_
355 char *lim, *buf, *next;
357 struct rt_msghdr *rtm;
359 struct sockaddr_inarp *sin;
361 struct sockaddr_dl *sdl;
366 struct arpreq arpReq;
367 memset(&arpReq,
'\0',
sizeof(arpReq));
369 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
381 mib[4] = NET_RT_FLAGS;
383 #if defined(RTF_LLDATA)
389 if (sysctl(mib, 6,
nullptr, &needed,
nullptr, 0) < 0) {
401 if (sysctl(mib, 6, buf, &needed,
nullptr, 0) < 0) {
410 for (next = buf; next < lim; next += rtm->rtm_msglen) {
412 rtm = (
struct rt_msghdr *) next;
414 sin = (
struct sockaddr_inarp *) (rtm + 1);
418 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
420 sdl = (
struct sockaddr_dl *)((
char *) sin + ROUNDUP(sin->sin_len));
422 if (ipAddr == sin->sin_addr) {
425 arpReq.arp_ha.sa_len =
sizeof(
struct sockaddr);
426 arpReq.arp_ha.sa_family = AF_UNSPEC;
427 memcpy(arpReq.arp_ha.sa_data, LLADDR(sdl), sdl->sdl_alen);
434 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
435 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
436 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
443 set(arpReq.arp_ha.sa_data, 6);
446 #elif _SQUID_WINDOWS_
448 DWORD dwNetTable = 0;
450 DWORD ipNetTableLen = 0;
452 PMIB_IPNETTABLE NetTable =
nullptr;
456 struct arpreq arpReq;
457 memset(&arpReq,
'\0',
sizeof(arpReq));
460 if (GetIpNetTable(NetTable, &ipNetTableLen,
FALSE) != ERROR_INSUFFICIENT_BUFFER) {
467 if ((NetTable = (PMIB_IPNETTABLE)
xmalloc(ipNetTableLen)) ==
NULL) {
474 if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen,
FALSE)) != NO_ERROR) {
482 for (i = 0 ; i < NetTable->dwNumEntries ; ++i) {
484 a.s_addr = NetTable->table[i].dwAddr;
485 if (c == a && (NetTable->table[i].dwType > 2)) {
486 arpReq.arp_ha.sa_family = AF_UNSPEC;
487 memcpy(arpReq.arp_ha.sa_data, NetTable->table[i].bPhysAddr, NetTable->table[i].dwPhysAddrLen);
493 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
494 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
495 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
502 set(arpReq.arp_ha.sa_data, 6);
507 debugs(28,
DBG_CRITICAL,
"ERROR: ARP / MAC / EUI-* operations not supported on this operating system.");
513 debugs(28, 3,
"id=" << (
void*)
this <<
' ' << ipAddr <<
" NOT found");