]>
Commit | Line | Data |
---|---|---|
ee0927b6 | 1 | /* |
bbc27441 | 2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors |
ee0927b6 | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
ee0927b6 AJ |
7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 89 EUI-48 Lookup */ |
10 | ||
f7f3304a | 11 | #include "squid.h" |
ee0927b6 AJ |
12 | |
13 | #if USE_SQUID_EUI | |
14 | ||
15 | #include "Debug.h" | |
16 | #include "eui/Eui48.h" | |
17 | #include "globals.h" | |
96d89ea0 | 18 | #include "ip/Address.h" |
ee0927b6 | 19 | |
1a30fdf5 | 20 | #include <cerrno> |
ee0927b6 AJ |
21 | |
22 | /* START Legacy includes pattern */ | |
23 | /* TODO: clean this up so we dont have per-OS requirements. | |
24 | The files are checked for existence individually | |
25 | and can be wrapped | |
26 | */ | |
27 | ||
be266cb2 | 28 | #if _SQUID_WINDOWS_ |
ee0927b6 AJ |
29 | struct arpreq { |
30 | ||
b7ac5457 | 31 | Ip::Address arp_pa; /* protocol address */ |
ee0927b6 AJ |
32 | |
33 | struct sockaddr arp_ha; /* hardware address */ | |
34 | int arp_flags; /* flags */ | |
35 | }; | |
b966288b AJ |
36 | #if HAVE_IPHLPAPI_H |
37 | #include <iphlpapi.h> | |
38 | #endif | |
ee0927b6 AJ |
39 | #endif |
40 | ||
29759678 FC |
41 | #if HAVE_SYS_PARAM_H |
42 | #include <sys/param.h> | |
43 | #endif | |
ee0927b6 AJ |
44 | #if HAVE_SYS_SOCKIO_H |
45 | /* required by Solaris */ | |
46 | #include <sys/sockio.h> | |
47 | #endif | |
48 | #if HAVE_SYS_SYSCTL_H | |
49 | #include <sys/sysctl.h> | |
50 | #endif | |
51 | #if HAVE_NET_ROUTE_H | |
52 | #include <net/route.h> | |
53 | #endif | |
54 | #if HAVE_NET_IF_H | |
55 | #include <net/if.h> | |
56 | #endif | |
57 | #if HAVE_NET_IF_ARP_H | |
58 | #include <net/if_arp.h> | |
59 | #endif | |
60 | #if HAVE_NET_IF_DL_H | |
61 | #include <net/if_dl.h> | |
62 | #endif | |
63 | #if HAVE_NETINET_IF_ETHER_H | |
64 | #include <netinet/if_ether.h> | |
65 | #endif | |
66 | #if HAVE_SYS_IOCTL_H | |
67 | #include <sys/ioctl.h> | |
68 | #endif | |
69 | ||
70 | /* ==== BEGIN EUI LOOKUP SUPPORT ============================================= */ | |
71 | ||
72 | /* | |
73 | * From: dale@server.ctam.bitmcnit.bryansk.su (Dale) | |
74 | * To: wessels@nlanr.net | |
75 | * Subject: Another Squid patch... :) | |
76 | * Date: Thu, 04 Dec 1997 19:55:01 +0300 | |
77 | * ============================================================================ | |
78 | * | |
79 | * Working on setting up a proper firewall for a network containing some | |
80 | * Win'95 computers at our Univ, I've discovered that some smart students | |
81 | * avoid the restrictions easily just changing their IP addresses in Win'95 | |
82 | * Contol Panel... It has been getting boring, so I took Squid-1.1.18 | |
83 | * sources and added a new acl type for hard-wired access control: | |
84 | * | |
85 | * acl <name> arp <Ethernet address> ... | |
86 | * | |
87 | * For example, | |
88 | * | |
89 | * acl students arp 00:00:21:55:ed:22 00:00:21:ff:55:38 | |
90 | * | |
91 | * NOTE: Linux code by David Luyer <luyer@ucs.uwa.edu.au>. | |
92 | * Original (BSD-specific) code no longer works. | |
93 | * Solaris code by R. Gancarz <radekg@solaris.elektrownia-lagisza.com.pl> | |
94 | */ | |
95 | ||
96 | bool | |
a98c2da5 | 97 | Eui::Eui48::decode(const char *asc) |
ee0927b6 AJ |
98 | { |
99 | int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0; | |
100 | ||
101 | if (sscanf(asc, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) { | |
fa84c01d | 102 | debugs(28, DBG_CRITICAL, "Decode EUI-48: Invalid ethernet address '" << asc << "'"); |
ee0927b6 AJ |
103 | clear(); |
104 | return false; /* This is not valid address */ | |
105 | } | |
106 | ||
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; | |
68e47c3e AJ |
113 | |
114 | debugs(28, 4, "id=" << (void*)this << " decoded " << asc); | |
ee0927b6 AJ |
115 | return true; |
116 | } | |
117 | ||
118 | bool | |
a98c2da5 | 119 | Eui::Eui48::encode(char *buf, const int len) |
ee0927b6 | 120 | { |
68e47c3e AJ |
121 | if (len < SZ_EUI48_BUF) |
122 | return false; | |
ee0927b6 AJ |
123 | |
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); | |
68e47c3e AJ |
128 | |
129 | debugs(28, 4, "id=" << (void*)this << " encoded " << buf); | |
ee0927b6 AJ |
130 | return true; |
131 | } | |
132 | ||
133 | // return binary representation of the EUI | |
134 | bool | |
00406b24 | 135 | Eui::Eui48::lookup(const Ip::Address &c) |
ee0927b6 | 136 | { |
b7ac5457 | 137 | Ip::Address ipAddr = c; |
4dd643d5 | 138 | ipAddr.port(0); |
ee0927b6 | 139 | |
4fb8bb26 | 140 | #if _SQUID_LINUX_ |
ee0927b6 AJ |
141 | |
142 | unsigned char ifbuffer[sizeof(struct ifreq) * 64]; | |
143 | struct ifconf ifc; | |
144 | ||
145 | struct ifreq *ifr; | |
146 | int offset; | |
147 | ||
66307010 AJ |
148 | /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */ |
149 | int tmpSocket = socket(AF_INET,SOCK_STREAM,0); | |
c3e14a35 AJ |
150 | if (tmpSocket < 0) { |
151 | debugs(28, DBG_IMPORTANT, "Attempt to open socket for EUI retrieval failed: " << xstrerror()); | |
152 | clear(); | |
153 | return false; | |
154 | } | |
66307010 | 155 | |
ee0927b6 AJ |
156 | /* |
157 | * The linux kernel 2.2 maintains per interface ARP caches and | |
158 | * thus requires an interface name when doing ARP queries. | |
159 | * | |
160 | * The older 2.0 kernels appear to use a unified ARP cache, | |
161 | * and require an empty interface name | |
162 | * | |
163 | * To support both, we attempt the lookup with a blank interface | |
164 | * name first. If that does not succeed, the try each interface | |
165 | * in turn | |
166 | */ | |
167 | ||
168 | /* | |
169 | * Set up structures for ARP lookup with blank interface name | |
170 | */ | |
9461a7bf | 171 | struct arpreq arpReq; |
ee0927b6 AJ |
172 | memset(&arpReq, '\0', sizeof(arpReq)); |
173 | ||
63ac8451 | 174 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
4dd643d5 | 175 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
176 | |
177 | /* Query ARP table */ | |
68e47c3e | 178 | debugs(28, 4, "id=" << (void*)this << " query ARP table"); |
66307010 | 179 | if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) { |
ee0927b6 | 180 | /* Skip non-ethernet interfaces */ |
66307010 | 181 | close(tmpSocket); |
ee0927b6 AJ |
182 | |
183 | if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { | |
184 | clear(); | |
185 | return false; | |
186 | } | |
187 | ||
68e47c3e | 188 | debugs(28, 4, "id=" << (void*)this << " got address "<< std::setfill('0') << std::hex << |
ee0927b6 AJ |
189 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << |
190 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
191 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
192 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
193 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
194 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff)); | |
195 | ||
196 | set(arpReq.arp_ha.sa_data, 6); | |
197 | return true; | |
198 | } | |
199 | ||
200 | /* lookup list of interface names */ | |
201 | ifc.ifc_len = sizeof(ifbuffer); | |
202 | ||
203 | ifc.ifc_buf = (char *)ifbuffer; | |
204 | ||
66307010 | 205 | if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) { |
e0236918 | 206 | debugs(28, DBG_IMPORTANT, "Attempt to retrieve interface list failed: " << xstrerror()); |
ee0927b6 | 207 | clear(); |
66307010 | 208 | close(tmpSocket); |
ee0927b6 AJ |
209 | return false; |
210 | } | |
211 | ||
212 | if (ifc.ifc_len > (int)sizeof(ifbuffer)) { | |
e0236918 | 213 | debugs(28, DBG_IMPORTANT, "Interface list too long - " << ifc.ifc_len); |
ee0927b6 | 214 | clear(); |
66307010 | 215 | close(tmpSocket); |
ee0927b6 AJ |
216 | return false; |
217 | } | |
218 | ||
219 | /* Attempt ARP lookup on each interface */ | |
220 | offset = 0; | |
68e47c3e | 221 | debugs(28, 4, "id=" << (void*)this << " query ARP on each interface (" << ifc.ifc_len << " found)"); |
ee0927b6 AJ |
222 | while (offset < ifc.ifc_len) { |
223 | ||
224 | ifr = (struct ifreq *) (ifbuffer + offset); | |
225 | offset += sizeof(*ifr); | |
ee0927b6 | 226 | |
68e47c3e AJ |
227 | debugs(28, 4, "id=" << (void*)this << " found interface " << ifr->ifr_name); |
228 | ||
229 | /* Skip loopback and aliased interfaces */ | |
230 | if (!strncmp(ifr->ifr_name, "lo", 2)) | |
ee0927b6 AJ |
231 | continue; |
232 | ||
68e47c3e | 233 | if (strchr(ifr->ifr_name, ':')) |
ee0927b6 AJ |
234 | continue; |
235 | ||
68e47c3e | 236 | debugs(28, 4, "id=" << (void*)this << " looking up ARP address for " << ipAddr << " on " << ifr->ifr_name); |
ee0927b6 AJ |
237 | |
238 | /* Set up structures for ARP lookup */ | |
239 | ||
240 | memset(&arpReq, '\0', sizeof(arpReq)); | |
241 | ||
242 | sa = (sockaddr_in*)&arpReq.arp_pa; | |
4dd643d5 | 243 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
244 | |
245 | strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1); | |
246 | ||
247 | arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0'; | |
248 | ||
249 | /* Query ARP table */ | |
66307010 | 250 | if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) { |
ee0927b6 AJ |
251 | /* |
252 | * Query failed. Do not log failed lookups or "device | |
253 | * not supported" | |
254 | */ | |
255 | ||
256 | if (ENXIO == errno) | |
257 | (void) 0; | |
258 | else if (ENODEV == errno) | |
259 | (void) 0; | |
260 | else | |
e0236918 | 261 | debugs(28, DBG_IMPORTANT, "ARP query " << ipAddr << " failed: " << ifr->ifr_name << ": " << xstrerror()); |
ee0927b6 AJ |
262 | |
263 | continue; | |
264 | } | |
265 | ||
266 | /* Skip non-ethernet interfaces */ | |
68e47c3e AJ |
267 | if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { |
268 | debugs(28, 4, "id=" << (void*)this << "... not an Ethernet interface"); | |
ee0927b6 | 269 | continue; |
68e47c3e | 270 | } |
ee0927b6 | 271 | |
68e47c3e | 272 | debugs(28, 4, "id=" << (void*)this << " got address "<< std::setfill('0') << std::hex << |
ee0927b6 AJ |
273 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << |
274 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
275 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
276 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
277 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
278 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff) << " on "<< | |
279 | std::setfill(' ') << ifr->ifr_name); | |
280 | ||
281 | set(arpReq.arp_ha.sa_data, 6); | |
282 | ||
283 | /* | |
284 | * Should we stop looking here? Can the same IP address | |
285 | * exist on multiple interfaces? | |
286 | */ | |
287 | ||
288 | /* AYJ: 2009-10-06: for now we have to. We can only store one EUI at a time. */ | |
66307010 | 289 | close(tmpSocket); |
ee0927b6 AJ |
290 | return true; |
291 | } | |
292 | ||
66307010 AJ |
293 | close(tmpSocket); |
294 | ||
4fb8bb26 | 295 | #elif _SQUID_SOLARIS_ |
ee0927b6 | 296 | |
66307010 AJ |
297 | /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */ |
298 | int tmpSocket = socket(AF_INET,SOCK_STREAM,0); | |
c3e14a35 AJ |
299 | if (tmpSocket < 0) { |
300 | debugs(28, DBG_IMPORTANT, "Attempt to open socket for EUI retrieval failed: " << xstrerror()); | |
301 | clear(); | |
302 | return false; | |
303 | } | |
66307010 | 304 | |
ee0927b6 | 305 | /* Set up structures for ARP lookup with blank interface name */ |
9461a7bf | 306 | struct arpreq arpReq; |
ee0927b6 AJ |
307 | memset(&arpReq, '\0', sizeof(arpReq)); |
308 | ||
63ac8451 | 309 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
4dd643d5 | 310 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
311 | |
312 | /* Query ARP table */ | |
66307010 | 313 | if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) { |
ee0927b6 AJ |
314 | /* |
315 | * Solaris (at least 2.6/x86) does not use arp_ha.sa_family - | |
316 | * it returns 00:00:00:00:00:00 for non-ethernet media | |
317 | */ | |
66307010 | 318 | close(tmpSocket); |
ee0927b6 AJ |
319 | |
320 | if (arpReq.arp_ha.sa_data[0] == 0 && | |
321 | arpReq.arp_ha.sa_data[1] == 0 && | |
322 | arpReq.arp_ha.sa_data[2] == 0 && | |
323 | arpReq.arp_ha.sa_data[3] == 0 && | |
324 | arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) { | |
325 | clear(); | |
326 | return false; | |
327 | } | |
328 | ||
329 | debugs(28, 4, "Got address "<< std::setfill('0') << std::hex << | |
330 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << | |
331 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
332 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
333 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
334 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
335 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff)); | |
336 | ||
337 | set(arpReq.arp_ha.sa_data, 6); | |
338 | return true; | |
cedb9107 P |
339 | } else { |
340 | close(tmpSocket); | |
ee0927b6 AJ |
341 | } |
342 | ||
4fb8bb26 | 343 | #elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_ |
ee0927b6 AJ |
344 | |
345 | int mib[6]; | |
346 | ||
347 | size_t needed; | |
348 | ||
349 | char *lim, *buf, *next; | |
350 | ||
351 | struct rt_msghdr *rtm; | |
352 | ||
353 | struct sockaddr_inarp *sin; | |
354 | ||
355 | struct sockaddr_dl *sdl; | |
356 | ||
357 | /* | |
358 | * Set up structures for ARP lookup with blank interface name | |
359 | */ | |
9461a7bf | 360 | struct arpreq arpReq; |
ee0927b6 AJ |
361 | memset(&arpReq, '\0', sizeof(arpReq)); |
362 | ||
63ac8451 | 363 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
4dd643d5 | 364 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
365 | |
366 | /* Query ARP table */ | |
367 | mib[0] = CTL_NET; | |
368 | ||
369 | mib[1] = PF_ROUTE; | |
370 | ||
371 | mib[2] = 0; | |
372 | ||
373 | mib[3] = AF_INET; | |
374 | ||
375 | mib[4] = NET_RT_FLAGS; | |
376 | ||
377 | mib[5] = RTF_LLINFO; | |
378 | ||
379 | if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { | |
fa84c01d | 380 | debugs(28, DBG_CRITICAL, "Can't estimate ARP table size!"); |
ee0927b6 AJ |
381 | clear(); |
382 | return false; | |
383 | } | |
384 | ||
385 | if ((buf = (char *)xmalloc(needed)) == NULL) { | |
fa84c01d | 386 | debugs(28, DBG_CRITICAL, "Can't allocate temporary ARP table!"); |
ee0927b6 AJ |
387 | clear(); |
388 | return false; | |
389 | } | |
390 | ||
391 | if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { | |
fa84c01d | 392 | debugs(28, DBG_CRITICAL, "Can't retrieve ARP table!"); |
ee0927b6 AJ |
393 | xfree(buf); |
394 | clear(); | |
395 | return false; | |
396 | } | |
397 | ||
398 | lim = buf + needed; | |
399 | ||
400 | for (next = buf; next < lim; next += rtm->rtm_msglen) { | |
401 | ||
402 | rtm = (struct rt_msghdr *) next; | |
403 | ||
404 | sin = (struct sockaddr_inarp *) (rtm + 1); | |
405 | /*sdl = (struct sockaddr_dl *) (sin + 1); */ | |
406 | ||
407 | #define ROUNDUP(a) \ | |
408 | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | |
409 | ||
410 | sdl = (struct sockaddr_dl *)((char *) sin + ROUNDUP(sin->sin_len)); | |
411 | ||
412 | if (ipAddr == sin->sin_addr) { | |
413 | if (sdl->sdl_alen) { | |
414 | ||
415 | arpReq.arp_ha.sa_len = sizeof(struct sockaddr); | |
416 | arpReq.arp_ha.sa_family = AF_UNSPEC; | |
417 | memcpy(arpReq.arp_ha.sa_data, LLADDR(sdl), sdl->sdl_alen); | |
418 | } | |
419 | } | |
420 | } | |
421 | ||
422 | xfree(buf); | |
423 | ||
424 | if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 && | |
425 | arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 && | |
426 | arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) { | |
427 | clear(); | |
428 | return false; | |
429 | } | |
430 | ||
431 | debugs(28, 4, "Got address "<< std::setfill('0') << std::hex << | |
432 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << | |
433 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
434 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
435 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
436 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
437 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff)); | |
438 | ||
439 | set(arpReq.arp_ha.sa_data, 6); | |
440 | return true; | |
441 | ||
be266cb2 | 442 | #elif _SQUID_WINDOWS_ |
ee0927b6 AJ |
443 | |
444 | DWORD dwNetTable = 0; | |
445 | ||
446 | DWORD ipNetTableLen = 0; | |
447 | ||
448 | PMIB_IPNETTABLE NetTable = NULL; | |
449 | ||
450 | DWORD i; | |
451 | ||
9461a7bf | 452 | struct arpreq arpReq; |
ee0927b6 AJ |
453 | memset(&arpReq, '\0', sizeof(arpReq)); |
454 | ||
455 | /* Get size of Windows ARP table */ | |
456 | if (GetIpNetTable(NetTable, &ipNetTableLen, FALSE) != ERROR_INSUFFICIENT_BUFFER) { | |
fa84c01d | 457 | debugs(28, DBG_CRITICAL, "Can't estimate ARP table size!"); |
ee0927b6 AJ |
458 | clear(); |
459 | return false; | |
460 | } | |
461 | ||
462 | /* Allocate space for ARP table and assign pointers */ | |
463 | if ((NetTable = (PMIB_IPNETTABLE)xmalloc(ipNetTableLen)) == NULL) { | |
fa84c01d | 464 | debugs(28, DBG_CRITICAL, "Can't allocate temporary ARP table!"); |
ee0927b6 AJ |
465 | clear(); |
466 | return false; | |
467 | } | |
468 | ||
469 | /* Get actual ARP table */ | |
470 | if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen, FALSE)) != NO_ERROR) { | |
fa84c01d | 471 | debugs(28, DBG_CRITICAL, "Can't retrieve ARP table!"); |
ee0927b6 AJ |
472 | xfree(NetTable); |
473 | clear(); | |
474 | return false; | |
475 | } | |
476 | ||
477 | /* Find MAC address from net table */ | |
cb4185f1 | 478 | for (i = 0 ; i < NetTable->dwNumEntries ; ++i) { |
ee0927b6 AJ |
479 | in_addr a; |
480 | a.s_addr = NetTable->table[i].dwAddr; | |
481 | if (c == a && (NetTable->table[i].dwType > 2)) { | |
482 | arpReq.arp_ha.sa_family = AF_UNSPEC; | |
483 | memcpy(arpReq.arp_ha.sa_data, NetTable->table[i].bPhysAddr, NetTable->table[i].dwPhysAddrLen); | |
484 | } | |
485 | } | |
486 | ||
487 | xfree(NetTable); | |
488 | ||
489 | if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 && | |
490 | arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 && | |
491 | arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) { | |
492 | clear(); | |
493 | return false; | |
494 | } | |
495 | ||
496 | debugs(28, 4, "Got address "<< std::setfill('0') << std::hex << | |
497 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << | |
498 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
499 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
500 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
501 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
502 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff)); | |
503 | ||
504 | set(arpReq.arp_ha.sa_data, 6); | |
505 | return true; | |
506 | ||
507 | #else | |
508 | ||
fa84c01d | 509 | debugs(28, DBG_CRITICAL, "ERROR: ARP / MAC / EUI-* operations not supported on this operating system."); |
ee0927b6 AJ |
510 | |
511 | #endif | |
512 | /* | |
513 | * Address was not found on any interface | |
514 | */ | |
68e47c3e | 515 | debugs(28, 3, "id=" << (void*)this << ' ' << ipAddr << " NOT found"); |
ee0927b6 AJ |
516 | |
517 | clear(); | |
518 | return false; | |
519 | } | |
520 | ||
521 | /* ==== END EUI LOOKUP SUPPORT =============================================== */ | |
522 | ||
523 | #endif /* USE_SQUID_EUI */ |