Ip.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 /* DEBUG: section 28 Access Control */
10 
11 #include "squid.h"
12 #include "acl/Checklist.h"
13 #include "acl/Ip.h"
14 #include "acl/SplayInserter.h"
15 #include "cache_cf.h"
16 #include "ConfigParser.h"
17 #include "debug/Stream.h"
18 #include "ip/tools.h"
19 #include "MemBuf.h"
20 #include "wordlist.h"
21 
22 #include <algorithm>
23 
24 void *
25 ACLIP::operator new (size_t)
26 {
27  fatal ("ACLIP::operator new: unused");
28  return (void *)1;
29 }
30 
31 void
32 ACLIP::operator delete (void *)
33 {
34  fatal ("ACLIP::operator delete: unused");
35 }
36 
43 void
44 acl_ip_data::toStr(char *buf, int len) const
45 {
46  char *b1 = buf;
47  char *b2 = nullptr;
48  char *b3 = nullptr;
49  int rlen = 0;
50 
51  addr1.toStr(b1, len - rlen );
52  rlen = strlen(buf);
53  b2 = buf + rlen;
54 
55  if (!addr2.isAnyAddr()) {
56  b2[0] = '-';
57  ++rlen;
58  addr2.toStr(&(b2[1]), len - rlen );
59  rlen = strlen(buf);
60  } else
61  b2[0] = '\0';
62 
63  b3 = buf + rlen;
64 
65  if (!mask.isNoAddr()) {
66  b3[0] = '/';
67  ++rlen;
68  int cidr = mask.cidr() - (addr1.isIPv4()?96:0);
69  snprintf(&(b3[1]), (len-rlen), "%u", (unsigned int)(cidr<0?0:cidr) );
70  } else
71  b3[0] = '\0';
72 }
73 
74 SBuf
76 {
77  const int bufsz = MAX_IPSTRLEN*2+6;
78  static char tmpbuf[ bufsz ];
79  toStr(tmpbuf,bufsz);
80  return SBuf(tmpbuf);
81 }
82 
85 {
86  auto ip = addr1;
87  if (!mask.isNoAddr())
88  ip.applyMask(mask);
89  return ip;
90 }
91 
94 {
95  auto ip = addr2.isAnyAddr() ? addr1 : addr2;
96  if (!mask.isNoAddr())
98  return ip;
99 }
100 
101 template <>
102 int
104 {
105  if (a->lastAddress() < b->firstAddress())
106  return -1; // the entire range a is to the left of range b
107 
108  if (a->firstAddress() > b->lastAddress())
109  return +1; // the entire range a is to the right of range b
110 
111  return 0; // equal or partially overlapping ranges
112 }
113 
114 template <>
115 bool
117 {
118  return b->firstAddress() <= a->firstAddress() && a->lastAddress() <= b->lastAddress();
119 }
120 
121 template <>
124 {
125  const auto minLeft = std::min(a->firstAddress(), b->firstAddress());
126  const auto maxRight = std::max(a->lastAddress(), b->lastAddress());
127  return new acl_ip_data(minLeft, maxRight, Ip::Address::NoAddr(), nullptr);
128 }
129 
131 static std::ostream &
132 operator <<(std::ostream &os, acl_ip_data *value)
133 {
134  if (value)
135  os << value->toSBuf();
136  return os;
137 }
138 
139 /*
140  * aclIpAddrNetworkCompare - The guts of the comparison for IP ACLs
141  * matching checks. The first argument (p) is a "host" address,
142  * i.e. the IP address of a cache client. The second argument (q)
143  * is an entry in some address-based access control element. This
144  * function is called via ACLIP::match() and the splay library.
145  */
146 static int
148 {
149  Ip::Address A = p->addr1;
150 
151  /* apply netmask */
152  A.applyMask(q->mask);
153 
154  debugs(28,9, "aclIpAddrNetworkCompare: compare: " << p->addr1 << "/" << q->mask << " (" << A << ") vs " <<
155  q->addr1 << "-" << q->addr2 << "/" << q->mask);
156 
157  if (q->addr2.isAnyAddr()) { /* single address check */
158 
159  return A.matchIPAddr( q->addr1 );
160 
161  } else { /* range address check */
162 
163  if ( (A >= q->addr1) && (A <= q->addr2) )
164  return 0; /* valid. inside range. */
165  else
166  return A.matchIPAddr( q->addr1 ); /* outside of range, 'less than' */
167  }
168 }
169 
175 bool
176 acl_ip_data::DecodeMask(const char *asc, Ip::Address &mask, int ctype)
177 {
178  char junk;
179  int a1 = 0;
180 
181  /* default is a mask that doesn't change any IP */
182  mask.setNoAddr();
183 
184  if (!asc || !*asc) {
185  return true;
186  }
187 
188  /* An int mask 128, 32 */
189  if ((sscanf(asc, "%d%c", &a1, &junk)==1) &&
190  (a1 <= 128) && (a1 >= 0)
191  ) {
192  return mask.applyMask(a1, ctype);
193  }
194 
195  /* dotted notation */
196  /* assignment returns true if asc contained an IP address as text */
197  if ((mask = asc)) {
198  /* HACK: IPv4 netmasks don't cleanly map to IPv6 masks. */
199  debugs(28, DBG_CRITICAL, "WARNING: Netmasks are deprecated. Please use CIDR masks instead.");
200  if (mask.isIPv4()) {
201  /* locate what CIDR mask was _probably_ meant to be in its native protocol format. */
202  /* this will completely crap out with a security fail-open if the admin is playing mask tricks */
203  /* however, that's their fault, and we do warn. see bug 2601 for the effects if we don't do this. */
204  unsigned int m = mask.cidr();
205  debugs(28, DBG_CRITICAL, "WARNING: IPv4 netmasks are particularly nasty when used to compare IPv6 to IPv4 ranges.");
206  debugs(28, DBG_CRITICAL, "WARNING: For now we will assume you meant to write /" << m);
207  /* reset the mask completely, and crop to the CIDR boundary back properly. */
208  mask.setNoAddr();
209  return mask.applyMask(m,AF_INET);
210  }
211  return true;
212  }
213 
214  return false;
215 }
216 
217 /* Handle either type of address, IPv6 will be discarded with a warning if disabled */
218 #define SCAN_ACL1_6 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]/%[0123456789]"
219 #define SCAN_ACL2_6 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]%c"
220 #define SCAN_ACL3_6 "%[0123456789ABCDEFabcdef:]/%[0123456789]"
221 #define SCAN_ACL4_6 "%[0123456789ABCDEFabcdef:]/%c"
222 /* We DO need to know which is which though, for proper CIDR masking. */
223 #define SCAN_ACL1_4 "%[0123456789.]-%[0123456789.]/%[0123456789.]"
224 #define SCAN_ACL2_4 "%[0123456789.]-%[0123456789.]%c"
225 #define SCAN_ACL3_4 "%[0123456789.]/%[0123456789.]"
226 #define SCAN_ACL4_4 "%[0123456789.]/%c"
227 
228 acl_ip_data *
230 {
231  LOCAL_ARRAY(char, addr1, 256);
232  LOCAL_ARRAY(char, addr2, 256);
233  LOCAL_ARRAY(char, mask, 256);
234  acl_ip_data *r = nullptr;
235  acl_ip_data **Q = nullptr;
236  Ip::Address temp;
237  char c;
238  unsigned int changed;
239  acl_ip_data *q = new acl_ip_data;
240  int iptype = AF_UNSPEC;
241 
242  debugs(28, 5, "aclIpParseIpData: " << t);
243 
244 // IPv4
245  if (sscanf(t, SCAN_ACL1_4, addr1, addr2, mask) == 3) {
246  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN1-v4: " << SCAN_ACL1_4);
247  iptype=AF_INET;
248  } else if (sscanf(t, SCAN_ACL2_4, addr1, addr2, &c) >= 2) {
249  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN2-v4: " << SCAN_ACL2_4);
250  mask[0] = '\0';
251  iptype=AF_INET;
252  } else if (sscanf(t, SCAN_ACL3_4, addr1, mask) == 2) {
253  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN3-v4: " << SCAN_ACL3_4);
254  addr2[0] = '\0';
255  iptype=AF_INET;
256  } else if (sscanf(t, SCAN_ACL4_4, addr1,&c) == 2) {
257  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN4-v4: " << SCAN_ACL4_4);
258  addr2[0] = '\0';
259  mask[0] = '\0';
260  iptype=AF_INET;
261 
262 // IPv6
263  } else if (sscanf(t, SCAN_ACL1_6, addr1, addr2, mask) == 3) {
264  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN1-v6: " << SCAN_ACL1_6);
265  iptype=AF_INET6;
266  } else if (sscanf(t, SCAN_ACL2_6, addr1, addr2, &c) >= 2) {
267  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN2-v6: " << SCAN_ACL2_6);
268  mask[0] = '\0';
269  iptype=AF_INET6;
270  } else if (sscanf(t, SCAN_ACL3_6, addr1, mask) == 2) {
271  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN3-v6: " << SCAN_ACL3_6);
272  addr2[0] = '\0';
273  iptype=AF_INET6;
274  } else if (sscanf(t, SCAN_ACL4_6, addr1, mask) == 2) {
275  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN4-v6: " << SCAN_ACL4_6);
276  addr2[0] = '\0';
277  iptype=AF_INET6;
278 
279 // Neither
280  } else if (sscanf(t, "%[^/]/%s", addr1, mask) == 2) {
281  debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: non-IP pattern: %[^/]/%s");
282  addr2[0] = '\0';
283  } else if (sscanf(t, "%s", addr1) == 1) {
284  /*
285  * Note, must use plain getaddrinfo() here because at startup
286  * ipcache hasn't been initialized
287  * TODO: offload this to one of the Ip::Address lookups.
288  */
289 
290  debugs(28, 5, "aclIpParseIpData: Lookup Host/IP " << addr1);
291  struct addrinfo *hp = nullptr, *x = nullptr;
292  struct addrinfo hints;
293  Ip::Address *prev_addr = nullptr;
294 
295  memset(&hints, 0, sizeof(struct addrinfo));
296 
297  int errcode = getaddrinfo(addr1,nullptr,&hints,&hp);
298  if (hp == nullptr) {
299  delete q;
300  if (strcmp(addr1, "::1") == 0) {
301  debugs(28, DBG_IMPORTANT, "aclIpParseIpData: IPv6 has not been enabled in host DNS resolver.");
302  } else {
303  debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: Bad host/IP: '" << addr1 <<
304  "' in '" << t << "', flags=" << hints.ai_flags <<
305  " : (" << errcode << ") " << gai_strerror(errcode) );
306  self_destruct();
307  }
308  return nullptr;
309  }
310 
311  Q = &q;
312 
313  for (x = hp; x != nullptr;) {
314  if ((r = *Q) == nullptr)
315  r = *Q = new acl_ip_data;
316 
317  /* getaddrinfo given a host has a nasty tendency to return duplicate addr's */
318  /* BUT sorted fortunately, so we can drop most of them easily */
319  r->addr1 = *x;
320  x = x->ai_next;
321  if ( prev_addr && r->addr1 == *prev_addr) {
322  debugs(28, 3, "aclIpParseIpData: Duplicate host/IP: '" << r->addr1 << "' dropped.");
323  delete r;
324  *Q = nullptr;
325  continue;
326  } else
327  prev_addr = &r->addr1;
328 
329  debugs(28, 3, "aclIpParseIpData: Located host/IP: '" << r->addr1 << "'");
330 
331  r->addr2.setAnyAddr();
332  r->mask.setNoAddr();
333 
334  Q = &r->next;
335 
336  debugs(28, 3, "" << addr1 << " --> " << r->addr1 );
337  }
338 
339  freeaddrinfo(hp);
340 
341  if (*Q != nullptr) {
342  debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: Bad host/IP: '" << t << "'");
343  self_destruct();
344  return nullptr;
345  }
346 
347  return q;
348  }
349 
350  /* ignore IPv6 addresses when built with IPv4-only */
351  if ( iptype == AF_INET6 && !Ip::EnableIpv6) {
352  debugs(28, DBG_IMPORTANT, "aclIpParseIpData: IPv6 has not been enabled.");
353  delete q;
354  return nullptr;
355  }
356 
357  /* Decode addr1 */
358  if (!*addr1 || !(q->addr1 = addr1)) {
359  debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: unknown first address in '" << t << "'");
360  delete q;
361  self_destruct();
362  return nullptr;
363  }
364 
365  /* Decode addr2 */
366  if (!*addr2)
367  q->addr2.setAnyAddr();
368  else if (!(q->addr2=addr2) ) {
369  debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: unknown second address in '" << t << "'");
370  delete q;
371  self_destruct();
372  return nullptr;
373  }
374 
375  /* Decode mask (NULL or empty means a exact host mask) */
376  if (!DecodeMask(mask, q->mask, iptype)) {
377  debugs(28, DBG_CRITICAL, "ERROR: aclParseIpData: unknown netmask '" << mask << "' in '" << t << "'");
378  delete q;
379  self_destruct();
380  return nullptr;
381  }
382 
383  changed = 0;
384  changed += q->addr1.applyMask(q->mask);
385  changed += q->addr2.applyMask(q->mask);
386 
387  if (changed)
388  debugs(28, DBG_CRITICAL, "WARNING: aclIpParseIpData: Netmask masks away part of the specified IP in '" << t << "'");
389 
390  // TODO: Either switch match() to Acl::SplayInserter<acl_ip_data*>::Compare()
391  // range logic (that does not have these problems) OR warn that some (or
392  // even all) addresses will never match this configured ACL value when
393  // `q->addr1.applyMask()` above is positive:
394  //
395  // * A single configured IP value will never match:
396  // A.matchIPAddr(q->addr1) in aclIpAddrNetworkCompare() will not return 0.
397  // For example, `acl x src 127.0.0.1/24` does not match any address.
398  //
399  // * A configured IP range will not match any q->addr1/mask IPs:
400  // (A >= q->addr1) in aclIpAddrNetworkCompare() is false and
401  // A.matchIPAddr(q->addr1) will not return 0.
402  // For example, `acl y src 10.0.0.1-10.0.0.255/24` does not match 10.0.0.1.
403 
404  debugs(28,9, "Parsed: " << q->addr1 << "-" << q->addr2 << "/" << q->mask << "(/" << q->mask.cidr() <<")");
405 
406  /* 1.2.3.4/255.255.255.0 --> 1.2.3.0 */
407  /* Same as IPv6 (not so trivial to depict) */
408  return q;
409 }
410 
413 bool
414 ACLIP::parseGlobal(const char * const token)
415 {
416  // "all" matches entire Internet
417  if (strcmp(token, "all") == 0) {
418  debugs(28, 8, "found " << token);
419  matchAnyIpv4 = true;
420  matchAnyIpv6 = true;
421  // TODO: Ignore all other ACL data parameters, with a once/ACL warning.
422  return true;
423  }
424 
425  // "ipv4" matches IPv4 Internet
426  if (strcmp(token, "ipv4") == 0) {
427  debugs(28, 8, "found " << token);
428  matchAnyIpv4 = true;
429  // TODO: Ignore all IPv4 data parameters, with a once/ACL warning.
430  return true;
431  }
432 
433  // "ipv4" matches IPv6 Internet
434  if (strcmp(token, "ipv6") == 0) {
435  debugs(28, 8, "found " << token);
436  matchAnyIpv6 = true;
437  // TODO: Ignore all IPv6 data parameters, with a once/ACL warning.
438  return true;
439  }
440 
441  /* Detect some old broken strings equivalent to 'all'.
442  * treat them nicely. But be loud until its fixed. */
443  if (strcmp(token, "0/0") == 0 ||
444  strcmp(token, "0.0.0.0/0") == 0 ||
445  strcmp(token, "0.0.0.0/0.0.0.0") == 0 ||
446  strcmp(token, "0.0.0.0-255.255.255.255") == 0 ||
447  strcmp(token, "0.0.0.0-0.0.0.0/0") == 0) {
448 
449  debugs(28,DBG_CRITICAL, "ERROR: '" << token << "' needs to be replaced by the term 'all'.");
450  debugs(28,DBG_CRITICAL, "SECURITY NOTICE: Overriding config setting. Using 'all' instead.");
451  matchAnyIpv4 = true;
452  matchAnyIpv6 = true;
453  return true;
454  }
455 
456  return false;
457 }
458 
459 void
461 {
462  if (data == nullptr)
463  data = new IPSplay();
464 
465  while (char *t = ConfigParser::strtokFile()) {
466  if (parseGlobal(t))
467  continue;
468 
470 
471  while (q != nullptr) {
472  /* pop each result off the list and add it to the data tree individually */
473  acl_ip_data *next_node = q->next;
474  q->next = nullptr;
476  q = next_node;
477  }
478  }
479 }
480 
482 {
483  if (data) {
484  data->destroy();
485  delete data;
486  }
487 }
488 
491  void operator() (acl_ip_data * const & ip) {
492  contents.push_back(ip->toSBuf());
493  }
494 };
495 
496 SBufList
497 ACLIP::dump() const
498 {
499  IpAclDumpVisitor visitor;
500 
501  if (matchAnyIpv4 && matchAnyIpv6)
502  visitor.contents.push_back(SBuf("all"));
503  else if (matchAnyIpv4)
504  visitor.contents.push_back(SBuf("ipv4"));
505  else if (matchAnyIpv6)
506  visitor.contents.push_back(SBuf("ipv6"));
507 
508  data->visit(visitor);
509  return visitor.contents;
510 }
511 
512 bool
514 {
515  return data->empty() && !matchAnyIpv4 && !matchAnyIpv6;
516 }
517 
518 int
519 ACLIP::match(const Ip::Address &clientip)
520 {
521  if (matchAnyIpv4) {
522  if (matchAnyIpv6) {
523  debugs(28, 3, clientip << " found, matched 'all'");
524  return true;
525  }
526  if (clientip.isIPv4()) {
527  debugs(28, 3, clientip << " found, matched 'ipv4'");
528  return true;
529  }
530  // fall through to look for an IPv6 match among IP parameters
531  } else if (matchAnyIpv6) {
532  if (clientip.isIPv6()) {
533  debugs(28, 3, clientip << " found, matched 'ipv6'");
534  return true;
535  }
536  // fall through to look for an IPv4 match among IP parameters
537  }
538 
539  static acl_ip_data ClientAddress;
540  /*
541  * aclIpAddrNetworkCompare() takes two acl_ip_data pointers as
542  * arguments, so we must create a fake one for the client's IP
543  * address. Since we are scanning for a single IP mask and addr2
544  * MUST be set to empty.
545  */
546  ClientAddress.addr1 = clientip;
547  ClientAddress.addr2.setEmpty();
548  ClientAddress.mask.setEmpty();
549 
550  const acl_ip_data * const * result = data->find(&ClientAddress, aclIpAddrNetworkCompare);
551  debugs(28, 3, "aclIpMatchIp: '" << clientip << "' " << (result ? "found" : "NOT found"));
552  return (result != nullptr);
553 }
554 
555 acl_ip_data::acl_ip_data() :addr1(), addr2(), mask(), next (nullptr) {}
556 
557 acl_ip_data::acl_ip_data(Ip::Address const &anAddress1, Ip::Address const &anAddress2, Ip::Address const &aMask, acl_ip_data *aNext) : addr1(anAddress1), addr2(anAddress2), mask(aMask), next(aNext) {}
558 
IPSplay * data
Definition: Ip.h:70
void fatal(const char *message)
Definition: fatal.cc:28
static int aclIpAddrNetworkCompare(acl_ip_data *const &p, acl_ip_data *const &q)
Definition: Ip.cc:147
SBuf toSBuf() const
Definition: Ip.cc:75
void turnMaskedBitsOn(const Address &mask)
Definition: Address.cc:115
static int Compare(const Value &a, const Value &b)
bool empty() const override
Definition: Ip.cc:513
const Value * find(FindValue const &, int(*compare)(FindValue const &a, Value const &b)) const
Definition: splay.h:305
void visit(ValueVisitor &) const
left-to-right visit of all stored Values
#define DBG_CRITICAL
Definition: Stream.h:37
#define SCAN_ACL3_4
Definition: Ip.cc:225
static char * strtokFile()
Definition: ConfigParser.cc:65
#define LOCAL_ARRAY(type, name, size)
Definition: squid.h:62
bool empty() const
Definition: splay.h:78
bool parseGlobal(const char *)
Definition: Ip.cc:414
static std::ostream & operator<<(std::ostream &os, acl_ip_data *value)
reports acl_ip_data using squid.conf ACL value format
Definition: Ip.cc:132
bool isAnyAddr() const
Definition: Address.cc:190
std::list< SBuf > SBufList
Definition: forward.h:22
SBufList contents
Definition: Ip.cc:490
Definition: SBuf.h:93
Ip::Address mask
Definition: Ip.h:40
void operator()(acl_ip_data *const &ip)
Definition: Ip.cc:491
const A & max(A const &lhs, A const &rhs)
Ip::Address addr2
Definition: Ip.h:38
bool isIPv4() const
Definition: Address.cc:178
#define SCAN_ACL4_4
Definition: Ip.cc:226
static Value MakeCombinedValue(const Value &a, const Value &b)
static void Merge(Splay< Value > &, Value &&)
Definition: SplayInserter.h:68
int const char size_t
Definition: stub_liblog.cc:83
void self_destruct(void)
Definition: cache_cf.cc:276
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:812
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:25
#define SCAN_ACL3_6
Definition: Ip.cc:220
void toStr(char *buf, int len) const
Definition: Ip.cc:44
void setNoAddr()
Definition: Address.cc:312
static uint32 A
Definition: md4.c:43
bool isIPv6() const
Definition: Address.cc:184
Ip::Address lastAddress() const
maximum (masked) address that matches this configured ACL value
Definition: Ip.cc:93
static const Address & NoAddr()
Definition: Address.h:321
bool matchAnyIpv6
whether match() should return 1 for any IPv6 parameter
Definition: Ip.h:79
Ip::Address addr1
Definition: Ip.h:36
int cidr() const
Definition: Address.cc:54
Splay< acl_ip_data * > IPSplay
Definition: Ip.h:58
void setEmpty()
Fast reset of the stored content to what would be after default constructor.
Definition: Address.cc:204
bool isNoAddr() const
Definition: Address.cc:304
void destroy(SPLAYFREE *=DefaultFree)
Definition: splay.h:369
#define SCAN_ACL2_6
Definition: Ip.cc:219
SBufList dump() const override
Definition: Ip.cc:497
#define SCAN_ACL1_4
Definition: Ip.cc:223
int applyMask(const Address &mask)
Definition: Address.cc:97
int match(ACLChecklist *checklist) override=0
Matches the actual data in checklist against this Acl::Node.
static bool DecodeMask(const char *asc, Ip::Address &mask, int string_format_type)
Definition: Ip.cc:176
#define SCAN_ACL4_6
Definition: Ip.cc:221
~ACLIP() override
Definition: Ip.cc:481
Definition: Ip.h:17
Ip::Address firstAddress() const
minimum (masked) address that matches this configured ACL value
Definition: Ip.cc:84
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
Definition: Address.cc:197
#define DBG_IMPORTANT
Definition: Stream.h:38
#define SCAN_ACL1_6
Definition: Ip.cc:218
bool matchAnyIpv4
whether match() should return 1 for any IPv4 parameter
Definition: Ip.h:76
acl_ip_data()
Definition: Ip.cc:555
#define SCAN_ACL2_4
Definition: Ip.cc:224
int EnableIpv6
Whether IPv6 is supported and type of support.
Definition: tools.h:25
static bool IsSubset(const Value &a, const Value &b)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
const A & min(A const &lhs, A const &rhs)
acl_ip_data * next
Definition: Ip.h:42
static acl_ip_data * FactoryParse(char const *)
Definition: Ip.cc:229
void parse() override
parses node representation in squid.conf; dies on failures
Definition: Ip.cc:460

 

Introduction

Documentation

Support

Miscellaneous