]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ACLARP.cc
Import IPv6 support from squid3-ipv6 branch to 3-HEAD.
[thirdparty/squid.git] / src / ACLARP.cc
CommitLineData
cc192b50 1
48071869 2/*
cc192b50 3 * $Id: ACLARP.cc,v 1.25 2007/12/14 23:11:45 amosjeffries Exp $
48071869 4 *
5 * DEBUG: section 28 Access Control
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 *
35 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
36 */
37
6fc1da74 38#include "config.h"
5700029a 39#ifdef _SQUID_CYGWIN_
40#include <squid_windows.h>
41#endif
09f64260 42#include "squid.h"
cc192b50 43#include "IPAddress.h"
6fc1da74 44
5700029a 45#ifdef _SQUID_WIN32_
46
47struct arpreq
48{
49
cc192b50 50 IPAddress arp_pa; /* protocol address */
5700029a 51
52 struct sockaddr arp_ha; /* hardware address */
53 int arp_flags; /* flags */
54};
55
56#include <Iphlpapi.h>
57#else
58
6fc1da74 59#ifdef _SQUID_SOLARIS_
60#include <sys/sockio.h>
61#else
62#include <sys/sysctl.h>
63#endif
64#ifdef _SQUID_LINUX_
65#include <net/if_arp.h>
66#include <sys/ioctl.h>
67#else
68#include <net/if_dl.h>
69#endif
70#include <net/route.h>
71#include <net/if.h>
680ec522 72#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_)
9a2f1170 73#include <net/if_arp.h>
74#endif
6fc1da74 75#if HAVE_NETINET_IF_ETHER_H
76#include <netinet/if_ether.h>
77#endif
5700029a 78#endif
6fc1da74 79
48071869 80#include "ACLARP.h"
c913a563 81#include "wordlist.h"
48071869 82
83#if !USE_ARP_ACL
84#error USE_ARP_ACL Not defined
85#endif
86static void aclParseArpList(SplayNode<acl_arp_data *> **curlist);
87static int decode_eth(const char *asc, char *eth);
cc192b50 88static int aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IPAddress &c);
48071869 89static SplayNode<acl_arp_data *>::SPLAYCMP aclArpCompare;
90static SplayNode<acl_arp_data *>::SPLAYWALKEE aclDumpArpListWalkee;
91
92ACL::Prototype ACLARP::RegistryProtoype(&ACLARP::RegistryEntry_, "arp");
93
94ACLARP ACLARP::RegistryEntry_("arp");
95
96ACL *
97ACLARP::clone() const
98{
99 return new ACLARP(*this);
100}
101
102ACLARP::ACLARP (char const *theClass) : data (NULL), class_ (theClass)
103{}
104
105ACLARP::ACLARP (ACLARP const & old) : data (NULL), class_ (old.class_)
106{
107 /* we don't have copy constructors for the data yet */
108 assert (!old.data);
109}
110
48071869 111ACLARP::~ACLARP()
112{
113 if (data)
114 data->destroy(SplayNode<acl_arp_data*>::DefaultFree);
115}
116
117char const *
118ACLARP::typeString() const
119{
120 return class_;
121}
122
123bool
4b0f5de8 124ACLARP::empty () const
48071869 125{
290eb6b9 126 return data->empty();
48071869 127}
128
129/* ==== BEGIN ARP ACL SUPPORT ============================================= */
130
131/*
132 * From: dale@server.ctam.bitmcnit.bryansk.su (Dale)
133 * To: wessels@nlanr.net
134 * Subject: Another Squid patch... :)
135 * Date: Thu, 04 Dec 1997 19:55:01 +0300
136 * ============================================================================
137 *
138 * Working on setting up a proper firewall for a network containing some
139 * Win'95 computers at our Univ, I've discovered that some smart students
140 * avoid the restrictions easily just changing their IP addresses in Win'95
141 * Contol Panel... It has been getting boring, so I took Squid-1.1.18
142 * sources and added a new acl type for hard-wired access control:
143 *
144 * acl <name> arp <Ethernet address> ...
145 *
146 * For example,
147 *
148 * acl students arp 00:00:21:55:ed:22 00:00:21:ff:55:38
149 *
150 * NOTE: Linux code by David Luyer <luyer@ucs.uwa.edu.au>.
151 * Original (BSD-specific) code no longer works.
152 * Solaris code by R. Gancarz <radekg@solaris.elektrownia-lagisza.com.pl>
153 */
154
48071869 155/*
156 * Decode an ascii representation (asc) of an ethernet adress, and place
157 * it in eth[6].
158 */
159static int
160decode_eth(const char *asc, char *eth)
161{
162 int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0;
163
164 if (sscanf(asc, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) {
bf8fe701 165 debugs(28, 0, "decode_eth: Invalid ethernet address '" << asc << "'");
48071869 166 return 0; /* This is not valid address */
167 }
168
169 eth[0] = (u_char) a1;
170 eth[1] = (u_char) a2;
171 eth[2] = (u_char) a3;
172 eth[3] = (u_char) a4;
173 eth[4] = (u_char) a5;
174 eth[5] = (u_char) a6;
175 return 1;
176}
177
178acl_arp_data *
179aclParseArpData(const char *t)
180{
181 LOCAL_ARRAY(char, eth, 256);
182 acl_arp_data *q = new acl_arp_data;
bf8fe701 183 debugs(28, 5, "aclParseArpData: " << t);
48071869 184
185 if (sscanf(t, "%[0-9a-fA-F:]", eth) != 1) {
bf8fe701 186 debugs(28, 0, "aclParseArpData: Bad ethernet address: '" << t << "'");
48071869 187 safe_free(q);
188 return NULL;
189 }
190
191 if (!decode_eth(eth, q->eth)) {
bf8fe701 192 debugs(28, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
193 debugs(28, 0, "aclParseArpData: Ignoring invalid ARP acl entry: can't parse '" << eth << "'");
48071869 194 safe_free(q);
195 return NULL;
196 }
197
198 return q;
199}
200
201
202/*******************/
203/* aclParseArpList */
204/*******************/
205void
206ACLARP::parse()
207{
208 aclParseArpList (&data);
209}
210
211void
212aclParseArpList(SplayNode<acl_arp_data *> **curlist)
213{
214 char *t = NULL;
215 SplayNode<acl_arp_data *> **Top = curlist;
216 acl_arp_data *q = NULL;
217
218 while ((t = strtokFile())) {
219 if ((q = aclParseArpData(t)) == NULL)
220 continue;
221
222 *Top = (*Top)->insert(q, aclArpCompare);
223 }
224}
225
226int
227ACLARP::match(ACLChecklist *checklist)
228{
cc192b50 229 /* IPv6 does not do ARP */
230 if(!checklist->src_addr.IsIPv4())
231 {
232 debugs(14, 3, "ACLARP::match: IPv4 Required for ARP Lookups. Skipping " << checklist->src_addr );
233 return 0;
234 }
235
48071869 236 return aclMatchArp(&data, checklist->src_addr);
237}
238
239/***************/
240/* aclMatchArp */
241/***************/
242int
cc192b50 243aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IPAddress &c)
48071869 244{
cc192b50 245 char ntoabuf[MAX_IPSTRLEN];
48071869 246
247 struct arpreq arpReq;
248
cc192b50 249 IPAddress ipAddr = c;
250
251#if defined(_SQUID_LINUX_)
48071869 252
253 unsigned char ifbuffer[sizeof(struct ifreq) * 64];
254
255 struct ifconf ifc;
256
257 struct ifreq *ifr;
258 int offset;
259 SplayNode<acl_arp_data*> **Top = dataptr;
260 /*
261 * The linux kernel 2.2 maintains per interface ARP caches and
262 * thus requires an interface name when doing ARP queries.
263 *
264 * The older 2.0 kernels appear to use a unified ARP cache,
265 * and require an empty interface name
266 *
267 * To support both, we attempt the lookup with a blank interface
268 * name first. If that does not succeed, the try each interface
269 * in turn
270 */
cc192b50 271
48071869 272 /*
273 * Set up structures for ARP lookup with blank interface name
274 */
48071869 275 memset(&arpReq, '\0', sizeof(arpReq));
276
cc192b50 277 ipAddr.GetSockAddr(arpReq.arp_pa);
48071869 278 /* Query ARP table */
279
280 if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) {
281 /* Skip non-ethernet interfaces */
282
283 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
284 return 0;
285 }
286
bf8fe701 287 debugs(28, 4, "Got address "<< std::setfill('0') << std::hex <<
288 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" <<
289 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" <<
290 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" <<
291 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
292 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
293 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
294
48071869 295 /* Do lookup */
296 acl_arp_data X;
297 memcpy (X.eth, arpReq.arp_ha.sa_data, 6);
298 *Top = (*Top)->splay(&X, aclArpCompare);
cc192b50 299 debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
48071869 300 return (0 == splayLastResult);
301 }
302
303 /* lookup list of interface names */
304 ifc.ifc_len = sizeof(ifbuffer);
305
306 ifc.ifc_buf = (char *)ifbuffer;
307
308 if (ioctl(HttpSockets[0], SIOCGIFCONF, &ifc) < 0) {
bf8fe701 309 debugs(28, 1, "Attempt to retrieve interface list failed: " << xstrerror());
48071869 310 return 0;
311 }
312
313 if (ifc.ifc_len > (int)sizeof(ifbuffer)) {
bf8fe701 314 debugs(28, 1, "Interface list too long - " << ifc.ifc_len);
48071869 315 return 0;
316 }
317
318 /* Attempt ARP lookup on each interface */
319 offset = 0;
320
321 while (offset < ifc.ifc_len) {
322
323 ifr = (struct ifreq *) (ifbuffer + offset);
324 offset += sizeof(*ifr);
325 /* Skip loopback and aliased interfaces */
326
327 if (0 == strncmp(ifr->ifr_name, "lo", 2))
328 continue;
329
330 if (NULL != strchr(ifr->ifr_name, ':'))
331 continue;
332
cc192b50 333 debugs(28, 4, "Looking up ARP address for " << c << " on " << ifr->ifr_name);
48071869 334
335 /* Set up structures for ARP lookup */
48071869 336
337 memset(&arpReq, '\0', sizeof(arpReq));
338
cc192b50 339 ipAddr.GetSockAddr(arpReq.arp_pa);
48071869 340
341 strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1);
342
343 arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0';
344
345 /* Query ARP table */
346 if (-1 == ioctl(HttpSockets[0], SIOCGARP, &arpReq)) {
347 /*
348 * Query failed. Do not log failed lookups or "device
349 * not supported"
350 */
351
352 if (ENXIO == errno)
353 (void) 0;
354 else if (ENODEV == errno)
355 (void) 0;
356 else
bf8fe701 357 debugs(28, 1, "ARP query failed: " << ifr->ifr_name << ": " << xstrerror());
48071869 358
359 continue;
360 }
361
362 /* Skip non-ethernet interfaces */
363 if (arpReq.arp_ha.sa_family != ARPHRD_ETHER)
364 continue;
365
bf8fe701 366 debugs(28, 4, "Got address "<< std::setfill('0') << std::hex <<
367 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" <<
368 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" <<
369 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" <<
370 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
371 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
372 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff) << " on "<<
373 std::setfill(' ') << ifr->ifr_name);
48071869 374
375 /* Do lookup */
376 acl_arp_data X;
377
378 memcpy (X.eth, arpReq.arp_ha.sa_data, 6);
379
380 *Top = (*Top)->splay(&X, aclArpCompare);
381
382 /* Return if match, otherwise continue to other interfaces */
383 if (0 == splayLastResult) {
cc192b50 384 debugs(28, 3, "aclMatchArp: " << c << " found on " << ifr->ifr_name);
48071869 385 return 1;
386 }
387
388 /*
389 * Should we stop looking here? Can the same IP address
390 * exist on multiple interfaces?
391 */
392 }
393
394#elif defined(_SQUID_SOLARIS_)
395
48071869 396 SplayNode<acl_arp_data *> **Top = dataptr;
397
398 /*
399 * Set up structures for ARP lookup with blank interface name
400 */
48071869 401
402 memset(&arpReq, '\0', sizeof(arpReq));
403
cc192b50 404 ipAddr.GetSockAddr(arpReq.arp_pa);
48071869 405
406 /* Query ARP table */
407 if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) {
408 /*
409 * Solaris (at least 2.6/x86) does not use arp_ha.sa_family -
410 * it returns 00:00:00:00:00:00 for non-ethernet media
411 */
412
413 if (arpReq.arp_ha.sa_data[0] == 0 &&
414 arpReq.arp_ha.sa_data[1] == 0 &&
415 arpReq.arp_ha.sa_data[2] == 0 &&
416 arpReq.arp_ha.sa_data[3] == 0 &&
417 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0)
418 return 0;
419
bf8fe701 420 debugs(28, 4, "Got address "<< std::setfill('0') << std::hex <<
421 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" <<
422 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" <<
423 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" <<
424 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
425 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
426 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
48071869 427
428 /* Do lookup */
09f64260 429 *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare);
48071869 430
cc192b50 431 debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
48071869 432
433 return (0 == splayLastResult);
434 }
435
680ec522 436#elif defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_)
9a2f1170 437
9a2f1170 438 SplayNode<acl_arp_data *> **Top = dataptr;
439
440 int mib[6];
441
442 size_t needed;
443
444 char *lim, *buf, *next;
445
446 struct rt_msghdr *rtm;
447
448 struct sockaddr_inarp *sin;
449
450 struct sockaddr_dl *sdl;
451
452 /*
453 * Set up structures for ARP lookup with blank interface name
454 */
9a2f1170 455
456 memset(&arpReq, '\0', sizeof(arpReq));
457
cc192b50 458 ipAddr.GetSockAddr(arpReq.arp_pa);
9a2f1170 459
460 /* Query ARP table */
461 mib[0] = CTL_NET;
462
463 mib[1] = PF_ROUTE;
464
465 mib[2] = 0;
466
467 mib[3] = AF_INET;
468
469 mib[4] = NET_RT_FLAGS;
470
471 mib[5] = RTF_LLINFO;
472
473 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
bf8fe701 474 debugs(28, 0, "Can't estimate ARP table size!");
9a2f1170 475 return 0;
476 }
477
09f64260 478 if ((buf = (char *)xmalloc(needed)) == NULL) {
bf8fe701 479 debugs(28, 0, "Can't allocate temporary ARP table!");
9a2f1170 480 return 0;
481 }
482
483 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
bf8fe701 484 debugs(28, 0, "Can't retrieve ARP table!");
9a2f1170 485 xfree(buf);
486 return 0;
487 }
488
489 lim = buf + needed;
490
491 for (next = buf; next < lim; next += rtm->rtm_msglen) {
492
493 rtm = (struct rt_msghdr *) next;
494
495 sin = (struct sockaddr_inarp *) (rtm + 1);
496 /*sdl = (struct sockaddr_dl *) (sin + 1); */
497
498#define ROUNDUP(a) \
499 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
500
b3bbddff 501 sdl = (struct sockaddr_dl *)((char *) sin + ROUNDUP(sin->sin_len));
9a2f1170 502
cc192b50 503 if (c == sin->sin_addr) {
9a2f1170 504 if (sdl->sdl_alen) {
505
506 arpReq.arp_ha.sa_len = sizeof(struct sockaddr);
507 arpReq.arp_ha.sa_family = AF_UNSPEC;
508 memcpy(arpReq.arp_ha.sa_data, LLADDR(sdl), sdl->sdl_alen);
509 }
510 }
511 }
512
513 xfree(buf);
514
515 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
516 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
517 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0)
518 return 0;
519
bf8fe701 520 debugs(28, 4, "Got address "<< std::setfill('0') << std::hex <<
521 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" <<
522 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" <<
523 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" <<
524 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
525 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
526 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
9a2f1170 527
528 /* Do lookup */
09f64260 529 *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare);
9a2f1170 530
cc192b50 531 debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
9a2f1170 532
533 return (0 == splayLastResult);
534
5700029a 535#elif defined(_SQUID_WIN32_)
536
537 DWORD dwNetTable = 0;
538
539 DWORD ipNetTableLen = 0;
540
541 PMIB_IPNETTABLE NetTable = NULL;
542
543 DWORD i;
544
545 SplayNode<acl_arp_data *> **Top = dataptr;
546
922a8455 547 memset(&arpReq, '\0', sizeof(arpReq));
548
5700029a 549 /* Get size of Windows ARP table */
550 if (GetIpNetTable(NetTable, &ipNetTableLen, FALSE) != ERROR_INSUFFICIENT_BUFFER) {
bf8fe701 551 debugs(28, 0, "Can't estimate ARP table size!");
5700029a 552 return 0;
553 }
554
555 /* Allocate space for ARP table and assign pointers */
556 if ((NetTable = (PMIB_IPNETTABLE)xmalloc(ipNetTableLen)) == NULL) {
bf8fe701 557 debugs(28, 0, "Can't allocate temporary ARP table!");
5700029a 558 return 0;
559 }
560
561 /* Get actual ARP table */
562 if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen, FALSE)) != NO_ERROR) {
bf8fe701 563 debugs(28, 0, "Can't retrieve ARP table!");
5700029a 564 xfree(NetTable);
565 return 0;
566 }
567
568 /* Find MAC address from net table */
569 for (i = 0 ; i < NetTable->dwNumEntries ; i++) {
cc192b50 570 if ((c == (struct in_addr)NetTable->table[i].dwAddr) && (NetTable->table[i].dwType > 2)) {
5700029a 571 arpReq.arp_ha.sa_family = AF_UNSPEC;
922a8455 572 memcpy(arpReq.arp_ha.sa_data, NetTable->table[i].bPhysAddr, NetTable->table[i].dwPhysAddrLen);
5700029a 573 }
574 }
575
576 xfree(NetTable);
577
578 if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
579 arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
580 arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0)
581 return 0;
582
bf8fe701 583 debugs(28, 4, "Got address "<< std::setfill('0') << std::hex <<
584 std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff) << ":" <<
585 std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff) << ":" <<
586 std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff) << ":" <<
587 std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
588 std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
589 std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
5700029a 590
591 /* Do lookup */
592 *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare);
593
cc192b50 594 debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
5700029a 595
596 return (0 == splayLastResult);
597
48071869 598#else
9a2f1170 599
6bf4f823 600#error "ARP type ACL not supported on this operating system."
48071869 601
602#endif
603 /*
604 * Address was not found on any interface
605 */
cc192b50 606 debugs(28, 3, "aclMatchArp: " << c << " NOT found");
48071869 607
608 return 0;
609}
610
611static int
612aclArpCompare(acl_arp_data * const &a, acl_arp_data * const &b)
613{
614 return memcmp(a->eth, b->eth, 6);
615}
616
48071869 617static void
618aclDumpArpListWalkee(acl_arp_data * const &node, void *state)
619{
620 acl_arp_data *arp = node;
621 static char buf[24];
622 snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
5b807763 623 arp->eth[0] & 0xff, arp->eth[1] & 0xff,
624 arp->eth[2] & 0xff, arp->eth[3] & 0xff,
625 arp->eth[4] & 0xff, arp->eth[5] & 0xff);
48071869 626 wordlistAdd((wordlist **)state, buf);
627}
628
629wordlist *
630ACLARP::dump() const
631{
632 wordlist *w = NULL;
633 data->walk(aclDumpArpListWalkee, &w);
634 return w;
635}
636
637/* ==== END ARP ACL SUPPORT =============================================== */