33 struct sockaddr arp_ha;
46#include <sys/sockio.h>
49#include <sys/sysctl.h>
58#include <net/if_arp.h>
63#if HAVE_NETINET_IF_ETHER_H
64#include <netinet/if_ether.h>
99 int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0;
101 if (sscanf(asc,
"%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) {
102 debugs(28,
DBG_CRITICAL,
"ERROR: Decode EUI-48: Invalid ethernet address '" << asc <<
"'");
107 eui[0] = (u_char) a1;
108 eui[1] = (u_char) a2;
109 eui[2] = (u_char) a3;
110 eui[3] = (u_char) a4;
111 eui[4] = (u_char) a5;
112 eui[5] = (u_char) a6;
114 debugs(28, 4,
"id=" << (
void*)
this <<
" decoded " << asc);
124 snprintf(buf, len,
"%02x:%02x:%02x:%02x:%02x:%02x",
125 eui[0] & 0xff, eui[1] & 0xff,
126 eui[2] & 0xff, eui[3] & 0xff,
127 eui[4] & 0xff, eui[5] & 0xff);
129 debugs(28, 4,
"id=" << (
void*)
this <<
" encoded " << buf);
142 unsigned char ifbuffer[
sizeof(
struct ifreq) * 64];
149 int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
172 struct arpreq arpReq;
173 memset(&arpReq,
'\0',
sizeof(arpReq));
175 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
179 debugs(28, 4,
"id=" << (
void*)
this <<
" query ARP table");
180 if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
184 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
185 debugs(28, 4,
"id=" << (
void*)
this <<
" ... not an Ethernet interface: " << arpReq.arp_ha.sa_data);
190 debugs(28, 4,
"id=" << (
void*)
this <<
" got address "<< std::setfill(
'0') << std::hex <<
191 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) <<
":" <<
192 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) <<
":" <<
193 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) <<
":" <<
194 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) <<
":" <<
195 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) <<
":" <<
196 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
198 set(arpReq.arp_ha.sa_data, 6);
203 ifc.ifc_len =
sizeof(ifbuffer);
205 ifc.ifc_buf = (
char *)ifbuffer;
207 if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) {
215 if (ifc.ifc_len > (
int)
sizeof(ifbuffer)) {
224 debugs(28, 4,
"id=" << (
void*)
this <<
" query ARP on each interface (" << ifc.ifc_len <<
" found)");
225 while (offset < ifc.ifc_len) {
227 ifr = (
struct ifreq *) (ifbuffer + offset);
228 offset +=
sizeof(*ifr);
230 debugs(28, 4,
"id=" << (
void*)
this <<
" found interface " << ifr->ifr_name);
233 if (!strncmp(ifr->ifr_name,
"lo", 2))
236 if (strchr(ifr->ifr_name,
':'))
239 debugs(28, 4,
"id=" << (
void*)
this <<
" looking up ARP address for " << ipAddr <<
" on " << ifr->ifr_name);
243 memset(&arpReq,
'\0',
sizeof(arpReq));
245 sa = (sockaddr_in*)&arpReq.arp_pa;
248 strncpy(arpReq.arp_dev, ifr->ifr_name,
sizeof(arpReq.arp_dev) - 1);
250 arpReq.arp_dev[
sizeof(arpReq.arp_dev) - 1] =
'\0';
253 if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) {
256 if (ENXIO != xerrno && ENODEV != xerrno)
263 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
264 debugs(28, 4,
"id=" << (
void*)
this <<
"... not an Ethernet interface");
268 debugs(28, 4,
"id=" << (
void*)
this <<
" got address "<< std::setfill(
'0') << std::hex <<
269 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) <<
":" <<
270 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) <<
":" <<
271 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) <<
":" <<
272 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) <<
":" <<
273 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) <<
":" <<
274 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff) <<
" on "<<
275 std::setfill(
' ') << ifr->ifr_name);
277 set(arpReq.arp_ha.sa_data, 6);
294 int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
303 struct arpreq arpReq;
304 memset(&arpReq,
'\0',
sizeof(arpReq));
306 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
310 if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
317 if (arpReq.arp_ha.sa_data[0] == 0 &&
318 arpReq.arp_ha.sa_data[1] == 0 &&
319 arpReq.arp_ha.sa_data[2] == 0 &&
320 arpReq.arp_ha.sa_data[3] == 0 &&
321 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
326 debugs(28, 4,
"Got address "<< std::setfill(
'0') << std::hex <<
327 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) <<
":" <<
328 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) <<
":" <<
329 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) <<
":" <<
330 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) <<
":" <<
331 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) <<
":" <<
332 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
334 set(arpReq.arp_ha.sa_data, 6);
340#elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_
346 char *lim, *buf, *next;
348 struct rt_msghdr *rtm;
350 struct sockaddr_inarp *sin;
352 struct sockaddr_dl *sdl;
357 struct arpreq arpReq;
358 memset(&arpReq,
'\0',
sizeof(arpReq));
360 struct sockaddr_in *sa = (
struct sockaddr_in*)&arpReq.arp_pa;
372 mib[4] = NET_RT_FLAGS;
374#if defined(RTF_LLDATA)
380 if (sysctl(mib, 6,
nullptr, &needed,
nullptr, 0) < 0) {
392 if (sysctl(mib, 6, buf, &needed,
nullptr, 0) < 0) {
401 for (next = buf; next < lim; next += rtm->rtm_msglen) {
403 rtm = (
struct rt_msghdr *) next;
405 sin = (
struct sockaddr_inarp *) (rtm + 1);
409 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
411 sdl = (
struct sockaddr_dl *)((
char *) sin + ROUNDUP(sin->sin_len));
413 if (ipAddr == sin->sin_addr) {
416 arpReq.arp_ha.sa_len =
sizeof(
struct sockaddr);
417 arpReq.arp_ha.sa_family = AF_UNSPEC;
418 memcpy(arpReq.arp_ha.sa_data, LLADDR(sdl), sdl->sdl_alen);
425 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
426 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
427 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
432 debugs(28, 4,
"Got address "<< std::setfill(
'0') << std::hex <<
433 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) <<
":" <<
434 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) <<
":" <<
435 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) <<
":" <<
436 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) <<
":" <<
437 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) <<
":" <<
438 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
440 set(arpReq.arp_ha.sa_data, 6);
445 DWORD dwNetTable = 0;
447 DWORD ipNetTableLen = 0;
449 PMIB_IPNETTABLE NetTable =
nullptr;
453 struct arpreq arpReq;
454 memset(&arpReq,
'\0',
sizeof(arpReq));
457 if (GetIpNetTable(NetTable, &ipNetTableLen,
FALSE) != ERROR_INSUFFICIENT_BUFFER) {
464 if ((NetTable = (PMIB_IPNETTABLE)
xmalloc(ipNetTableLen)) ==
NULL) {
471 if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen,
FALSE)) != NO_ERROR) {
479 for (i = 0 ; i < NetTable->dwNumEntries ; ++i) {
481 a.s_addr = NetTable->table[i].dwAddr;
482 if (c == a && (NetTable->table[i].dwType > 2)) {
483 arpReq.arp_ha.sa_family = AF_UNSPEC;
484 memcpy(arpReq.arp_ha.sa_data, NetTable->table[i].bPhysAddr, NetTable->table[i].dwPhysAddrLen);
490 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
491 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
492 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) {
497 debugs(28, 4,
"Got address "<< std::setfill(
'0') << std::hex <<
498 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) <<
":" <<
499 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) <<
":" <<
500 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) <<
":" <<
501 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) <<
":" <<
502 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) <<
":" <<
503 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
505 set(arpReq.arp_ha.sa_data, 6);
510 debugs(28,
DBG_CRITICAL,
"ERROR: ARP / MAC / EUI-* operations not supported on this operating system.");
516 debugs(28, 3,
"id=" << (
void*)
this <<
' ' << ipAddr <<
" NOT found");
unsigned char eui[SZ_EUI48_BUF]
bool lookup(const Ip::Address &c)
bool encode(char *buf, const int len) const
bool decode(const char *asc)
void getSockAddr(struct sockaddr_storage &addr, const int family) const
unsigned short port() const
#define debugs(SECTION, LEVEL, CONTENT)
const char * xstrerr(int error)