]>
Commit | Line | Data |
---|---|---|
ee0927b6 | 1 | /* |
4ac4a490 | 2 | * Copyright (C) 1996-2017 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 | 103 | clear(); |
f53969cc | 104 | return false; /* This is not valid address */ |
ee0927b6 AJ |
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 | |
4c79ed3d | 119 | Eui::Eui48::encode(char *buf, const int len) const |
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 | 150 | if (tmpSocket < 0) { |
b69e9ffa AJ |
151 | int xerrno = errno; |
152 | debugs(28, DBG_IMPORTANT, "Attempt to open socket for EUI retrieval failed: " << xstrerr(xerrno)); | |
c3e14a35 AJ |
153 | clear(); |
154 | return false; | |
155 | } | |
66307010 | 156 | |
ee0927b6 AJ |
157 | /* |
158 | * The linux kernel 2.2 maintains per interface ARP caches and | |
159 | * thus requires an interface name when doing ARP queries. | |
160 | * | |
161 | * The older 2.0 kernels appear to use a unified ARP cache, | |
162 | * and require an empty interface name | |
163 | * | |
164 | * To support both, we attempt the lookup with a blank interface | |
165 | * name first. If that does not succeed, the try each interface | |
166 | * in turn | |
167 | */ | |
168 | ||
169 | /* | |
170 | * Set up structures for ARP lookup with blank interface name | |
171 | */ | |
9461a7bf | 172 | struct arpreq arpReq; |
ee0927b6 AJ |
173 | memset(&arpReq, '\0', sizeof(arpReq)); |
174 | ||
63ac8451 | 175 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
4dd643d5 | 176 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
177 | |
178 | /* Query ARP table */ | |
68e47c3e | 179 | debugs(28, 4, "id=" << (void*)this << " query ARP table"); |
66307010 | 180 | if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) { |
ee0927b6 | 181 | /* Skip non-ethernet interfaces */ |
66307010 | 182 | close(tmpSocket); |
ee0927b6 AJ |
183 | |
184 | if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { | |
666b30be | 185 | debugs(28, 4, "id=" << (void*)this << " ... not an Ethernet interface: " << arpReq.arp_ha.sa_data); |
ee0927b6 AJ |
186 | clear(); |
187 | return false; | |
188 | } | |
189 | ||
68e47c3e | 190 | debugs(28, 4, "id=" << (void*)this << " got address "<< std::setfill('0') << std::hex << |
ee0927b6 AJ |
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)); | |
197 | ||
198 | set(arpReq.arp_ha.sa_data, 6); | |
199 | return true; | |
200 | } | |
201 | ||
202 | /* lookup list of interface names */ | |
203 | ifc.ifc_len = sizeof(ifbuffer); | |
204 | ||
205 | ifc.ifc_buf = (char *)ifbuffer; | |
206 | ||
66307010 | 207 | if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) { |
b69e9ffa AJ |
208 | int xerrno = errno; |
209 | debugs(28, DBG_IMPORTANT, "Attempt to retrieve interface list failed: " << xstrerr(xerrno)); | |
ee0927b6 | 210 | clear(); |
66307010 | 211 | close(tmpSocket); |
ee0927b6 AJ |
212 | return false; |
213 | } | |
214 | ||
215 | if (ifc.ifc_len > (int)sizeof(ifbuffer)) { | |
e0236918 | 216 | debugs(28, DBG_IMPORTANT, "Interface list too long - " << ifc.ifc_len); |
ee0927b6 | 217 | clear(); |
66307010 | 218 | close(tmpSocket); |
ee0927b6 AJ |
219 | return false; |
220 | } | |
221 | ||
222 | /* Attempt ARP lookup on each interface */ | |
223 | offset = 0; | |
68e47c3e | 224 | debugs(28, 4, "id=" << (void*)this << " query ARP on each interface (" << ifc.ifc_len << " found)"); |
ee0927b6 AJ |
225 | while (offset < ifc.ifc_len) { |
226 | ||
227 | ifr = (struct ifreq *) (ifbuffer + offset); | |
228 | offset += sizeof(*ifr); | |
ee0927b6 | 229 | |
68e47c3e AJ |
230 | debugs(28, 4, "id=" << (void*)this << " found interface " << ifr->ifr_name); |
231 | ||
232 | /* Skip loopback and aliased interfaces */ | |
233 | if (!strncmp(ifr->ifr_name, "lo", 2)) | |
ee0927b6 AJ |
234 | continue; |
235 | ||
68e47c3e | 236 | if (strchr(ifr->ifr_name, ':')) |
ee0927b6 AJ |
237 | continue; |
238 | ||
68e47c3e | 239 | debugs(28, 4, "id=" << (void*)this << " looking up ARP address for " << ipAddr << " on " << ifr->ifr_name); |
ee0927b6 AJ |
240 | |
241 | /* Set up structures for ARP lookup */ | |
242 | ||
243 | memset(&arpReq, '\0', sizeof(arpReq)); | |
244 | ||
245 | sa = (sockaddr_in*)&arpReq.arp_pa; | |
4dd643d5 | 246 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
247 | |
248 | strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1); | |
249 | ||
250 | arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0'; | |
251 | ||
252 | /* Query ARP table */ | |
66307010 | 253 | if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) { |
b69e9ffa AJ |
254 | int xerrno = errno; |
255 | // Query failed. Do not log failed lookups or "device not supported" | |
256 | if (ENXIO != xerrno && ENODEV != xerrno) | |
257 | debugs(28, DBG_IMPORTANT, "ARP query " << ipAddr << " failed: " << ifr->ifr_name << ": " << xstrerr(xerrno)); | |
ee0927b6 AJ |
258 | |
259 | continue; | |
260 | } | |
261 | ||
262 | /* Skip non-ethernet interfaces */ | |
68e47c3e AJ |
263 | if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { |
264 | debugs(28, 4, "id=" << (void*)this << "... not an Ethernet interface"); | |
ee0927b6 | 265 | continue; |
68e47c3e | 266 | } |
ee0927b6 | 267 | |
68e47c3e | 268 | debugs(28, 4, "id=" << (void*)this << " got address "<< std::setfill('0') << std::hex << |
ee0927b6 AJ |
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); | |
276 | ||
277 | set(arpReq.arp_ha.sa_data, 6); | |
278 | ||
279 | /* | |
280 | * Should we stop looking here? Can the same IP address | |
281 | * exist on multiple interfaces? | |
282 | */ | |
283 | ||
284 | /* AYJ: 2009-10-06: for now we have to. We can only store one EUI at a time. */ | |
66307010 | 285 | close(tmpSocket); |
ee0927b6 AJ |
286 | return true; |
287 | } | |
288 | ||
66307010 AJ |
289 | close(tmpSocket); |
290 | ||
4fb8bb26 | 291 | #elif _SQUID_SOLARIS_ |
ee0927b6 | 292 | |
66307010 AJ |
293 | /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */ |
294 | int tmpSocket = socket(AF_INET,SOCK_STREAM,0); | |
c3e14a35 | 295 | if (tmpSocket < 0) { |
b69e9ffa AJ |
296 | int xerrno = errno; |
297 | debugs(28, DBG_IMPORTANT, "Attempt to open socket for EUI retrieval failed: " << xstrerr(xerrno)); | |
c3e14a35 AJ |
298 | clear(); |
299 | return false; | |
300 | } | |
66307010 | 301 | |
ee0927b6 | 302 | /* Set up structures for ARP lookup with blank interface name */ |
9461a7bf | 303 | struct arpreq arpReq; |
ee0927b6 AJ |
304 | memset(&arpReq, '\0', sizeof(arpReq)); |
305 | ||
63ac8451 | 306 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
4dd643d5 | 307 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
308 | |
309 | /* Query ARP table */ | |
66307010 | 310 | if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) { |
ee0927b6 AJ |
311 | /* |
312 | * Solaris (at least 2.6/x86) does not use arp_ha.sa_family - | |
313 | * it returns 00:00:00:00:00:00 for non-ethernet media | |
314 | */ | |
66307010 | 315 | close(tmpSocket); |
ee0927b6 AJ |
316 | |
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) { | |
322 | clear(); | |
323 | return false; | |
324 | } | |
325 | ||
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)); | |
333 | ||
334 | set(arpReq.arp_ha.sa_data, 6); | |
335 | return true; | |
cedb9107 P |
336 | } else { |
337 | close(tmpSocket); | |
ee0927b6 AJ |
338 | } |
339 | ||
4fb8bb26 | 340 | #elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_ |
ee0927b6 AJ |
341 | |
342 | int mib[6]; | |
343 | ||
344 | size_t needed; | |
345 | ||
346 | char *lim, *buf, *next; | |
347 | ||
348 | struct rt_msghdr *rtm; | |
349 | ||
350 | struct sockaddr_inarp *sin; | |
351 | ||
352 | struct sockaddr_dl *sdl; | |
353 | ||
354 | /* | |
355 | * Set up structures for ARP lookup with blank interface name | |
356 | */ | |
9461a7bf | 357 | struct arpreq arpReq; |
ee0927b6 AJ |
358 | memset(&arpReq, '\0', sizeof(arpReq)); |
359 | ||
63ac8451 | 360 | struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa; |
4dd643d5 | 361 | ipAddr.getSockAddr(*sa); |
ee0927b6 AJ |
362 | |
363 | /* Query ARP table */ | |
364 | mib[0] = CTL_NET; | |
365 | ||
366 | mib[1] = PF_ROUTE; | |
367 | ||
368 | mib[2] = 0; | |
369 | ||
370 | mib[3] = AF_INET; | |
371 | ||
372 | mib[4] = NET_RT_FLAGS; | |
373 | ||
69b8fcab LT |
374 | #if defined(RTF_LLDATA) |
375 | mib[5] = RTF_LLDATA; | |
376 | #else | |
ee0927b6 | 377 | mib[5] = RTF_LLINFO; |
69b8fcab | 378 | #endif |
ee0927b6 AJ |
379 | |
380 | if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { | |
fa84c01d | 381 | debugs(28, DBG_CRITICAL, "Can't estimate ARP table size!"); |
ee0927b6 AJ |
382 | clear(); |
383 | return false; | |
384 | } | |
385 | ||
386 | if ((buf = (char *)xmalloc(needed)) == NULL) { | |
fa84c01d | 387 | debugs(28, DBG_CRITICAL, "Can't allocate temporary ARP table!"); |
ee0927b6 AJ |
388 | clear(); |
389 | return false; | |
390 | } | |
391 | ||
392 | if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { | |
fa84c01d | 393 | debugs(28, DBG_CRITICAL, "Can't retrieve ARP table!"); |
ee0927b6 AJ |
394 | xfree(buf); |
395 | clear(); | |
396 | return false; | |
397 | } | |
398 | ||
399 | lim = buf + needed; | |
400 | ||
401 | for (next = buf; next < lim; next += rtm->rtm_msglen) { | |
402 | ||
403 | rtm = (struct rt_msghdr *) next; | |
404 | ||
405 | sin = (struct sockaddr_inarp *) (rtm + 1); | |
406 | /*sdl = (struct sockaddr_dl *) (sin + 1); */ | |
407 | ||
408 | #define ROUNDUP(a) \ | |
409 | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | |
410 | ||
411 | sdl = (struct sockaddr_dl *)((char *) sin + ROUNDUP(sin->sin_len)); | |
412 | ||
413 | if (ipAddr == sin->sin_addr) { | |
414 | if (sdl->sdl_alen) { | |
415 | ||
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); | |
419 | } | |
420 | } | |
421 | } | |
422 | ||
423 | xfree(buf); | |
424 | ||
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) { | |
428 | clear(); | |
429 | return false; | |
430 | } | |
431 | ||
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)); | |
439 | ||
440 | set(arpReq.arp_ha.sa_data, 6); | |
441 | return true; | |
442 | ||
be266cb2 | 443 | #elif _SQUID_WINDOWS_ |
ee0927b6 AJ |
444 | |
445 | DWORD dwNetTable = 0; | |
446 | ||
447 | DWORD ipNetTableLen = 0; | |
448 | ||
449 | PMIB_IPNETTABLE NetTable = NULL; | |
450 | ||
451 | DWORD i; | |
452 | ||
9461a7bf | 453 | struct arpreq arpReq; |
ee0927b6 AJ |
454 | memset(&arpReq, '\0', sizeof(arpReq)); |
455 | ||
456 | /* Get size of Windows ARP table */ | |
457 | if (GetIpNetTable(NetTable, &ipNetTableLen, FALSE) != ERROR_INSUFFICIENT_BUFFER) { | |
fa84c01d | 458 | debugs(28, DBG_CRITICAL, "Can't estimate ARP table size!"); |
ee0927b6 AJ |
459 | clear(); |
460 | return false; | |
461 | } | |
462 | ||
463 | /* Allocate space for ARP table and assign pointers */ | |
464 | if ((NetTable = (PMIB_IPNETTABLE)xmalloc(ipNetTableLen)) == NULL) { | |
fa84c01d | 465 | debugs(28, DBG_CRITICAL, "Can't allocate temporary ARP table!"); |
ee0927b6 AJ |
466 | clear(); |
467 | return false; | |
468 | } | |
469 | ||
470 | /* Get actual ARP table */ | |
471 | if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen, FALSE)) != NO_ERROR) { | |
fa84c01d | 472 | debugs(28, DBG_CRITICAL, "Can't retrieve ARP table!"); |
ee0927b6 AJ |
473 | xfree(NetTable); |
474 | clear(); | |
475 | return false; | |
476 | } | |
477 | ||
478 | /* Find MAC address from net table */ | |
cb4185f1 | 479 | for (i = 0 ; i < NetTable->dwNumEntries ; ++i) { |
ee0927b6 AJ |
480 | in_addr a; |
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); | |
485 | } | |
486 | } | |
487 | ||
488 | xfree(NetTable); | |
489 | ||
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) { | |
493 | clear(); | |
494 | return false; | |
495 | } | |
496 | ||
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)); | |
504 | ||
505 | set(arpReq.arp_ha.sa_data, 6); | |
506 | return true; | |
507 | ||
508 | #else | |
509 | ||
fa84c01d | 510 | debugs(28, DBG_CRITICAL, "ERROR: ARP / MAC / EUI-* operations not supported on this operating system."); |
ee0927b6 AJ |
511 | |
512 | #endif | |
513 | /* | |
514 | * Address was not found on any interface | |
515 | */ | |
68e47c3e | 516 | debugs(28, 3, "id=" << (void*)this << ' ' << ipAddr << " NOT found"); |
ee0927b6 AJ |
517 | |
518 | clear(); | |
519 | return false; | |
520 | } | |
521 | ||
522 | /* ==== END EUI LOOKUP SUPPORT =============================================== */ | |
523 | ||
524 | #endif /* USE_SQUID_EUI */ | |
f53969cc | 525 |