]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/acl/Ip.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / acl / Ip.cc
index a513cd5763dbffa6b0847e37ed521fc529efe9b3..6d2d202db72049ae48cd42305616dc80718421f8 100644 (file)
@@ -1,82 +1,48 @@
 /*
- * DEBUG: section 28    Access Control
- * AUTHOR: Duane Wessels
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
  *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 28    Access Control */
+
 #include "squid.h"
 #include "acl/Checklist.h"
 #include "acl/Ip.h"
 #include "cache_cf.h"
-#include "Debug.h"
+#include "ConfigParser.h"
+#include "debug/Stream.h"
 #include "ip/tools.h"
 #include "MemBuf.h"
 #include "wordlist.h"
 
 void *
-ACLIP::operator new (size_t byteCount)
+ACLIP::operator new (size_t)
 {
     fatal ("ACLIP::operator new: unused");
     return (void *)1;
 }
 
 void
-ACLIP::operator delete (void *address)
+ACLIP::operator delete (void *)
 {
     fatal ("ACLIP::operator delete: unused");
 }
 
-/**
- * Writes an IP ACL data into a buffer, then copies the buffer into the wordlist given
- *
- \param ip     ACL data structure to display
- \param state  wordlist structure which is being generated
- */
-void
-ACLIP::DumpIpListWalkee(acl_ip_data * const & ip, void *state)
-{
-    static_cast<SBufList *>(state)->push_back(ip->toSBuf());
-}
-
 /**
  * print/format an acl_ip_data structure for debugging output.
  *
- \param buf    string buffer to write to
- \param len    size of the buffer available
+ \param buf string buffer to write to
+ \param len size of the buffer available
  */
 void
 acl_ip_data::toStr(char *buf, int len) const
 {
     char *b1 = buf;
-    char *b2 = NULL;
-    char *b3 = NULL;
+    char *b2 = nullptr;
+    char *b3 = nullptr;
     int rlen = 0;
 
     addr1.toStr(b1, len - rlen );
@@ -118,7 +84,7 @@ acl_ip_data::toSBuf() const
  * is an entry in some address-based access control element.  This
  * function is called via ACLIP::match() and the splay library.
  */
-int
+static int
 aclIpAddrNetworkCompare(acl_ip_data * const &p, acl_ip_data * const &q)
 {
     Ip::Address A = p->addr1;
@@ -214,7 +180,7 @@ acl_ip_data::DecodeMask(const char *asc, Ip::Address &mask, int ctype)
         if (mask.isIPv4()) {
             /* locate what CIDR mask was _probably_ meant to be in its native protocol format. */
             /* this will completely crap out with a security fail-open if the admin is playing mask tricks */
-            /* however, thats their fault, and we do warn. see bug 2601 for the effects if we don't do this. */
+            /* however, that's their fault, and we do warn. see bug 2601 for the effects if we don't do this. */
             unsigned int m = mask.cidr();
             debugs(28, DBG_CRITICAL, "WARNING: IPv4 netmasks are particularly nasty when used to compare IPv6 to IPv4 ranges.");
             debugs(28, DBG_CRITICAL, "WARNING: For now we will assume you meant to write /" << m);
@@ -245,8 +211,8 @@ acl_ip_data::FactoryParse(const char *t)
     LOCAL_ARRAY(char, addr1, 256);
     LOCAL_ARRAY(char, addr2, 256);
     LOCAL_ARRAY(char, mask, 256);
-    acl_ip_data *r = NULL;
-    acl_ip_data **Q = NULL;
+    acl_ip_data *r = nullptr;
+    acl_ip_data **Q = nullptr;
     Ip::Address temp;
     char c;
     unsigned int changed;
@@ -399,25 +365,30 @@ acl_ip_data::FactoryParse(const char *t)
          */
 
         debugs(28, 5, "aclIpParseIpData: Lookup Host/IP " << addr1);
-        struct addrinfo *hp = NULL, *x = NULL;
+        struct addrinfo *hp = nullptr, *x = nullptr;
         struct addrinfo hints;
-        Ip::Address *prev_addr = NULL;
+        Ip::Address *prev_addr = nullptr;
 
         memset(&hints, 0, sizeof(struct addrinfo));
 
-        int errcode = getaddrinfo(addr1,NULL,&hints,&hp);
-        if (hp == NULL) {
-            debugs(28, DBG_CRITICAL, "aclIpParseIpData: Bad host/IP: '" << addr1 <<
-                   "' in '" << t << "', flags=" << hints.ai_flags <<
-                   " : (" << errcode << ") " << gai_strerror(errcode) );
-            self_destruct();
-            return NULL;
+        int errcode = getaddrinfo(addr1,nullptr,&hints,&hp);
+        if (hp == nullptr) {
+            delete q;
+            if (strcmp(addr1, "::1") == 0) {
+                debugs(28, DBG_IMPORTANT, "aclIpParseIpData: IPv6 has not been enabled in host DNS resolver.");
+            } else {
+                debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: Bad host/IP: '" << addr1 <<
+                       "' in '" << t << "', flags=" << hints.ai_flags <<
+                       " : (" << errcode << ") " << gai_strerror(errcode) );
+                self_destruct();
+            }
+            return nullptr;
         }
 
         Q = &q;
 
-        for (x = hp; x != NULL;) {
-            if ((r = *Q) == NULL)
+        for (x = hp; x != nullptr;) {
+            if ((r = *Q) == nullptr)
                 r = *Q = new acl_ip_data;
 
             /* getaddrinfo given a host has a nasty tendency to return duplicate addr's */
@@ -427,7 +398,7 @@ acl_ip_data::FactoryParse(const char *t)
             if ( prev_addr && r->addr1 == *prev_addr) {
                 debugs(28, 3, "aclIpParseIpData: Duplicate host/IP: '" << r->addr1 << "' dropped.");
                 delete r;
-                *Q = NULL;
+                *Q = nullptr;
                 continue;
             } else
                 prev_addr = &r->addr1;
@@ -442,14 +413,14 @@ acl_ip_data::FactoryParse(const char *t)
             debugs(28, 3, "" << addr1 << " --> " << r->addr1 );
         }
 
-        if (*Q != NULL) {
-            debugs(28, DBG_CRITICAL, "aclIpParseIpData: Bad host/IP: '" << t << "'");
+        freeaddrinfo(hp);
+
+        if (*Q != nullptr) {
+            debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: Bad host/IP: '" << t << "'");
             self_destruct();
-            return NULL;
+            return nullptr;
         }
 
-        freeaddrinfo(hp);
-
         return q;
     }
 
@@ -457,33 +428,33 @@ acl_ip_data::FactoryParse(const char *t)
     if ( iptype == AF_INET6 && !Ip::EnableIpv6) {
         debugs(28, DBG_IMPORTANT, "aclIpParseIpData: IPv6 has not been enabled.");
         delete q;
-        return NULL;
+        return nullptr;
     }
 
     /* Decode addr1 */
     if (!*addr1 || !(q->addr1 = addr1)) {
-        debugs(28, DBG_CRITICAL, "aclIpParseIpData: unknown first address in '" << t << "'");
+        debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: unknown first address in '" << t << "'");
         delete q;
         self_destruct();
-        return NULL;
+        return nullptr;
     }
 
     /* Decode addr2 */
     if (!*addr2)
         q->addr2.setAnyAddr();
     else if (!(q->addr2=addr2) ) {
-        debugs(28, DBG_CRITICAL, "aclIpParseIpData: unknown second address in '" << t << "'");
+        debugs(28, DBG_CRITICAL, "ERROR: aclIpParseIpData: unknown second address in '" << t << "'");
         delete q;
         self_destruct();
-        return NULL;
+        return nullptr;
     }
 
     /* Decode mask (NULL or empty means a exact host mask) */
     if (!DecodeMask(mask, q->mask, iptype)) {
-        debugs(28, DBG_CRITICAL, "aclParseIpData: unknown netmask '" << mask << "' in '" << t << "'");
+        debugs(28, DBG_CRITICAL, "ERROR: aclParseIpData: unknown netmask '" << mask << "' in '" << t << "'");
         delete q;
         self_destruct();
-        return NULL;
+        return nullptr;
     }
 
     changed = 0;
@@ -491,9 +462,9 @@ acl_ip_data::FactoryParse(const char *t)
     changed += q->addr2.applyMask(q->mask);
 
     if (changed)
-        debugs(28, DBG_CRITICAL, "aclIpParseIpData: WARNING: Netmask masks away part of the specified IP in '" << t << "'");
+        debugs(28, DBG_CRITICAL, "WARNING: aclIpParseIpData: Netmask masks away part of the specified IP in '" << t << "'");
 
-    debugs(28,9, HERE << "Parsed: " << q->addr1 << "-" << q->addr2 << "/" << q->mask << "(/" << q->mask.cidr() <<")");
+    debugs(28,9, "Parsed: " << q->addr1 << "-" << q->addr2 << "/" << q->mask << "(/" << q->mask.cidr() <<")");
 
     /* 1.2.3.4/255.255.255.0  --> 1.2.3.0 */
     /* Same as IPv6 (not so trivial to depict) */
@@ -503,16 +474,18 @@ acl_ip_data::FactoryParse(const char *t)
 void
 ACLIP::parse()
 {
-    flags.parseFlags();
+    if (data == nullptr)
+        data = new IPSplay();
 
-    while (char *t = strtokFile()) {
+    while (char *t = ConfigParser::strtokFile()) {
         acl_ip_data *q = acl_ip_data::FactoryParse(t);
 
-        while (q != NULL) {
+        while (q != nullptr) {
             /* pop each result off the list and add it to the data tree individually */
             acl_ip_data *next_node = q->next;
-            q->next = NULL;
-            data = data->insert(q, acl_ip_data::NetworkCompare);
+            q->next = nullptr;
+            if (!data->find(q,acl_ip_data::NetworkCompare))
+                data->insert(q, acl_ip_data::NetworkCompare);
             q = next_node;
         }
     }
@@ -520,16 +493,25 @@ ACLIP::parse()
 
 ACLIP::~ACLIP()
 {
-    if (data)
-        data->destroy(IPSplay::DefaultFree);
+    if (data) {
+        data->destroy();
+        delete data;
+    }
 }
 
+struct IpAclDumpVisitor {
+    SBufList contents;
+    void operator() (acl_ip_data * const & ip) {
+        contents.push_back(ip->toSBuf());
+    }
+};
+
 SBufList
 ACLIP::dump() const
 {
-    SBufList sl;
-    data->walk(DumpIpListWalkee, &sl);
-    return sl;
+    IpAclDumpVisitor visitor;
+    data->visit(visitor);
+    return visitor.contents;
 }
 
 bool
@@ -539,7 +521,7 @@ ACLIP::empty() const
 }
 
 int
-ACLIP::match(Ip::Address &clientip)
+ACLIP::match(const Ip::Address &clientip)
 {
     static acl_ip_data ClientAddress;
     /*
@@ -552,11 +534,12 @@ ACLIP::match(Ip::Address &clientip)
     ClientAddress.addr2.setEmpty();
     ClientAddress.mask.setEmpty();
 
-    data = data->splay(&ClientAddress, aclIpAddrNetworkCompare);
-    debugs(28, 3, "aclIpMatchIp: '" << clientip << "' " << (splayLastResult ? "NOT found" : "found"));
-    return !splayLastResult;
+    const acl_ip_data * const * result =  data->find(&ClientAddress, aclIpAddrNetworkCompare);
+    debugs(28, 3, "aclIpMatchIp: '" << clientip << "' " << (result ? "found" : "NOT found"));
+    return (result != nullptr);
 }
 
-acl_ip_data::acl_ip_data() :addr1(), addr2(), mask(), next (NULL) {}
+acl_ip_data::acl_ip_data() :addr1(), addr2(), mask(), next (nullptr) {}
 
 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) {}
+