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