]>
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 | ||
f7f3304a | 35 | #include "squid.h" |
ee0927b6 AJ |
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 | 160 | { |
be266cb2 | 161 | #if !_SQUID_WINDOWS_ |
be266cb2 | 162 | #endif /* !_SQUID_WINDOWS_ */ |
ee0927b6 | 163 | |
b7ac5457 | 164 | Ip::Address ipAddr = c; |
ee0927b6 AJ |
165 | ipAddr.SetPort(0); |
166 | ||
4fb8bb26 | 167 | #if _SQUID_LINUX_ |
ee0927b6 AJ |
168 | |
169 | unsigned char ifbuffer[sizeof(struct ifreq) * 64]; | |
170 | struct ifconf ifc; | |
171 | ||
172 | struct ifreq *ifr; | |
173 | int offset; | |
174 | ||
66307010 AJ |
175 | /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */ |
176 | int tmpSocket = socket(AF_INET,SOCK_STREAM,0); | |
177 | ||
ee0927b6 AJ |
178 | /* |
179 | * The linux kernel 2.2 maintains per interface ARP caches and | |
180 | * thus requires an interface name when doing ARP queries. | |
181 | * | |
182 | * The older 2.0 kernels appear to use a unified ARP cache, | |
183 | * and require an empty interface name | |
184 | * | |
185 | * To support both, we attempt the lookup with a blank interface | |
186 | * name first. If that does not succeed, the try each interface | |
187 | * in turn | |
188 | */ | |
189 | ||
190 | /* | |
191 | * Set up structures for ARP lookup with blank interface name | |
192 | */ | |
9461a7bf | 193 | struct arpreq arpReq; |
ee0927b6 AJ |
194 | memset(&arpReq, '\0', sizeof(arpReq)); |
195 | ||
63ac8451 | 196 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
ee0927b6 AJ |
197 | ipAddr.GetSockAddr(*sa); |
198 | ||
199 | /* Query ARP table */ | |
66307010 | 200 | if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) { |
ee0927b6 | 201 | /* Skip non-ethernet interfaces */ |
66307010 | 202 | close(tmpSocket); |
ee0927b6 AJ |
203 | |
204 | if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { | |
205 | clear(); | |
206 | return false; | |
207 | } | |
208 | ||
209 | debugs(28, 4, "Got address "<< std::setfill('0') << std::hex << | |
210 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << | |
211 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
212 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
213 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
214 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
215 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff)); | |
216 | ||
217 | set(arpReq.arp_ha.sa_data, 6); | |
218 | return true; | |
219 | } | |
220 | ||
221 | /* lookup list of interface names */ | |
222 | ifc.ifc_len = sizeof(ifbuffer); | |
223 | ||
224 | ifc.ifc_buf = (char *)ifbuffer; | |
225 | ||
66307010 | 226 | if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) { |
ee0927b6 AJ |
227 | debugs(28, 1, "Attempt to retrieve interface list failed: " << xstrerror()); |
228 | clear(); | |
66307010 | 229 | close(tmpSocket); |
ee0927b6 AJ |
230 | return false; |
231 | } | |
232 | ||
233 | if (ifc.ifc_len > (int)sizeof(ifbuffer)) { | |
234 | debugs(28, 1, "Interface list too long - " << ifc.ifc_len); | |
235 | clear(); | |
66307010 | 236 | close(tmpSocket); |
ee0927b6 AJ |
237 | return false; |
238 | } | |
239 | ||
240 | /* Attempt ARP lookup on each interface */ | |
241 | offset = 0; | |
242 | ||
243 | while (offset < ifc.ifc_len) { | |
244 | ||
245 | ifr = (struct ifreq *) (ifbuffer + offset); | |
246 | offset += sizeof(*ifr); | |
247 | /* Skip loopback and aliased interfaces */ | |
248 | ||
249 | if (0 == strncmp(ifr->ifr_name, "lo", 2)) | |
250 | continue; | |
251 | ||
252 | if (NULL != strchr(ifr->ifr_name, ':')) | |
253 | continue; | |
254 | ||
255 | debugs(28, 4, "Looking up ARP address for " << ipAddr << " on " << ifr->ifr_name); | |
256 | ||
257 | /* Set up structures for ARP lookup */ | |
258 | ||
259 | memset(&arpReq, '\0', sizeof(arpReq)); | |
260 | ||
261 | sa = (sockaddr_in*)&arpReq.arp_pa; | |
262 | ipAddr.GetSockAddr(*sa); | |
263 | ||
264 | strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1); | |
265 | ||
266 | arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0'; | |
267 | ||
268 | /* Query ARP table */ | |
66307010 | 269 | if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) { |
ee0927b6 AJ |
270 | /* |
271 | * Query failed. Do not log failed lookups or "device | |
272 | * not supported" | |
273 | */ | |
274 | ||
275 | if (ENXIO == errno) | |
276 | (void) 0; | |
277 | else if (ENODEV == errno) | |
278 | (void) 0; | |
279 | else | |
a98c2da5 | 280 | debugs(28, 1, "ARP query " << ipAddr << " failed: " << ifr->ifr_name << ": " << xstrerror()); |
ee0927b6 AJ |
281 | |
282 | continue; | |
283 | } | |
284 | ||
285 | /* Skip non-ethernet interfaces */ | |
286 | if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) | |
287 | continue; | |
288 | ||
289 | debugs(28, 4, "Got address "<< std::setfill('0') << std::hex << | |
290 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << | |
291 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
292 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
293 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
294 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
295 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff) << " on "<< | |
296 | std::setfill(' ') << ifr->ifr_name); | |
297 | ||
298 | set(arpReq.arp_ha.sa_data, 6); | |
299 | ||
300 | /* | |
301 | * Should we stop looking here? Can the same IP address | |
302 | * exist on multiple interfaces? | |
303 | */ | |
304 | ||
305 | /* AYJ: 2009-10-06: for now we have to. We can only store one EUI at a time. */ | |
66307010 | 306 | close(tmpSocket); |
ee0927b6 AJ |
307 | return true; |
308 | } | |
309 | ||
66307010 AJ |
310 | close(tmpSocket); |
311 | ||
4fb8bb26 | 312 | #elif _SQUID_SOLARIS_ |
ee0927b6 | 313 | |
66307010 AJ |
314 | /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */ |
315 | int tmpSocket = socket(AF_INET,SOCK_STREAM,0); | |
316 | ||
ee0927b6 | 317 | /* Set up structures for ARP lookup with blank interface name */ |
9461a7bf | 318 | struct arpreq arpReq; |
ee0927b6 AJ |
319 | memset(&arpReq, '\0', sizeof(arpReq)); |
320 | ||
63ac8451 | 321 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
ee0927b6 AJ |
322 | ipAddr.GetSockAddr(*sa); |
323 | ||
324 | /* Query ARP table */ | |
66307010 | 325 | if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) { |
ee0927b6 AJ |
326 | /* |
327 | * Solaris (at least 2.6/x86) does not use arp_ha.sa_family - | |
328 | * it returns 00:00:00:00:00:00 for non-ethernet media | |
329 | */ | |
66307010 | 330 | close(tmpSocket); |
ee0927b6 AJ |
331 | |
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) { | |
337 | clear(); | |
338 | return false; | |
339 | } | |
340 | ||
341 | debugs(28, 4, "Got address "<< std::setfill('0') << std::hex << | |
342 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << | |
343 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
344 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
345 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
346 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
347 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff)); | |
348 | ||
349 | set(arpReq.arp_ha.sa_data, 6); | |
350 | return true; | |
351 | } | |
352 | ||
4fb8bb26 | 353 | #elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_ |
ee0927b6 AJ |
354 | |
355 | int mib[6]; | |
356 | ||
357 | size_t needed; | |
358 | ||
359 | char *lim, *buf, *next; | |
360 | ||
361 | struct rt_msghdr *rtm; | |
362 | ||
363 | struct sockaddr_inarp *sin; | |
364 | ||
365 | struct sockaddr_dl *sdl; | |
366 | ||
367 | /* | |
368 | * Set up structures for ARP lookup with blank interface name | |
369 | */ | |
9461a7bf | 370 | struct arpreq arpReq; |
ee0927b6 AJ |
371 | memset(&arpReq, '\0', sizeof(arpReq)); |
372 | ||
63ac8451 | 373 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
ee0927b6 AJ |
374 | ipAddr.GetSockAddr(*sa); |
375 | ||
376 | /* Query ARP table */ | |
377 | mib[0] = CTL_NET; | |
378 | ||
379 | mib[1] = PF_ROUTE; | |
380 | ||
381 | mib[2] = 0; | |
382 | ||
383 | mib[3] = AF_INET; | |
384 | ||
385 | mib[4] = NET_RT_FLAGS; | |
386 | ||
387 | mib[5] = RTF_LLINFO; | |
388 | ||
389 | if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { | |
390 | debugs(28, 0, "Can't estimate ARP table size!"); | |
391 | clear(); | |
392 | return false; | |
393 | } | |
394 | ||
395 | if ((buf = (char *)xmalloc(needed)) == NULL) { | |
396 | debugs(28, 0, "Can't allocate temporary ARP table!"); | |
397 | clear(); | |
398 | return false; | |
399 | } | |
400 | ||
401 | if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { | |
402 | debugs(28, 0, "Can't retrieve ARP table!"); | |
403 | xfree(buf); | |
404 | clear(); | |
405 | return false; | |
406 | } | |
407 | ||
408 | lim = buf + needed; | |
409 | ||
410 | for (next = buf; next < lim; next += rtm->rtm_msglen) { | |
411 | ||
412 | rtm = (struct rt_msghdr *) next; | |
413 | ||
414 | sin = (struct sockaddr_inarp *) (rtm + 1); | |
415 | /*sdl = (struct sockaddr_dl *) (sin + 1); */ | |
416 | ||
417 | #define ROUNDUP(a) \ | |
418 | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | |
419 | ||
420 | sdl = (struct sockaddr_dl *)((char *) sin + ROUNDUP(sin->sin_len)); | |
421 | ||
422 | if (ipAddr == sin->sin_addr) { | |
423 | if (sdl->sdl_alen) { | |
424 | ||
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); | |
428 | } | |
429 | } | |
430 | } | |
431 | ||
432 | xfree(buf); | |
433 | ||
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) { | |
437 | clear(); | |
438 | return false; | |
439 | } | |
440 | ||
441 | debugs(28, 4, "Got address "<< std::setfill('0') << std::hex << | |
442 | std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" << | |
443 | std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" << | |
444 | std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" << | |
445 | std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" << | |
446 | std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" << | |
447 | std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff)); | |
448 | ||
449 | set(arpReq.arp_ha.sa_data, 6); | |
450 | return true; | |
451 | ||
be266cb2 | 452 | #elif _SQUID_WINDOWS_ |
ee0927b6 AJ |
453 | |
454 | DWORD dwNetTable = 0; | |
455 | ||
456 | DWORD ipNetTableLen = 0; | |
457 | ||
458 | PMIB_IPNETTABLE NetTable = NULL; | |
459 | ||
460 | DWORD i; | |
461 | ||
9461a7bf | 462 | struct arpreq arpReq; |
ee0927b6 AJ |
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 */ |