==============================================================================
-include/radix.h,
-lib/radix.c:
-
- * Copyright (c) 1988, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
-
-==============================================================================
-
include/rfc2617.h,
lib/rfc2617.c:
==============================================================================
-lib/radix.c:
-
- * Adapted from HTSUtils.c in CERN httpd 3.0 (http://info.cern.ch/httpd/)
- * by Darren Hardy <hardy@cs.colorado.edu>, November 1994.
-
-==============================================================================
-
lib/Splay.cc:
* based on ftp://ftp.cs.cmu.edu/user/sleator/splaying/top-down-splay.c
Common applications for this feature are extended access controls
and local mirroring. File: redirect.c.
-\section ASN Autonomous System Numbers
-\par
- Squid supports Autonomous System (AS) numbers as another
- access control element. The routines in asn.c
- query databases which map AS numbers into lists of CIDR
- prefixes. These results are stored in a radix tree which
- allows fast searching of the AS number for a given IP address.
-
\section ConfigurationFileParsing Configuration File Parsing
\par
The primary configuration file specification is in the file
section 50 Log file handling
section 51 Filedescriptor Functions
section 52 URN Parsing
-section 53 AS Number handling
-section 53 Radix Tree data structure implementation
section 54 Interprocess Communication
section 54 Windows Interprocess Communication
section 55 HTTP Header
</descrip>
+<sect1>Cache Manager changes
+
+<p>Removed support for <em>asndb</em> cache manager report after removing
+support for <em>src_as</em> and <em>dst_as</em> ACLs and associated ASN
+lookups. Requests for that report now result in HTTP 404 errors.
Most user-facing changes are reflected in squid.conf (see below).
<sect1>Changes to existing directives<label id="modifieddirectives">
<p>
<descrip>
- <p>No changed directives in this version.
+ <tag>acl</tag>
+
+ <p>Removed support for <em>src_as</em> and <em>dst_as</em> ACLs. Based on
+ admin feedback and a history of serious implementation bugs that went
+ unnoticed for a long time, the two ACLs are considered to be essentially
+ unused. The corresponding Autonomous System Numbers (ASN) lookups can be
+ implemented (with more features) using external ACLs. Removing ASN lookup
+ support also removes ancient and neglected C code, improving Squid
+ security posture and simplifying development. Configurations using
+ <em>src_as</em> and <em>dst_as</em> ACL types are now rejected with FATAL
+ errors.
+
+ <p>Removed support for <em>asn</em> initiator in
+ <em>transaction_initiator</em> ACLs. After removing support for
+ <em>src_as</em> and <em>dst_as</em> ACLs, Squid no longer initiates ASN
+ lookups.
</descrip>
+++ /dev/null
-/*
- * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_INCLUDE_RADIX_H
-#define SQUID_INCLUDE_RADIX_H
-
-/*
- * Copyright (c) 1988, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)radix.h 8.2 (Berkeley) 10/31/94
- */
-
-/*
- * Radix search tree node layout.
- */
-
-struct squid_radix_node {
-
- struct squid_radix_mask *rn_mklist; /* list of masks contained in subtree */
-
- struct squid_radix_node *rn_p; /* parent */
- short rn_b; /* bit offset; -1-index(netmask) */
- char rn_bmask; /* node: mask for bit test */
- unsigned char rn_flags; /* enumerated next */
-#define RNF_NORMAL 1 /* leaf contains normal route */
-#define RNF_ROOT 2 /* leaf is root leaf for tree */
-#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
-
- union {
-
- struct { /* leaf only data: */
- char *rn_Key; /* object of search */
- char *rn_Mask; /* netmask, if present */
-
- struct squid_radix_node *rn_Dupedkey;
- } rn_leaf;
-
- struct { /* node only data: */
- int rn_Off; /* where to start compare */
-
- struct squid_radix_node *rn_L; /* progeny */
-
- struct squid_radix_node *rn_R; /* progeny */
- } rn_node;
- } rn_u;
-};
-
-#define rn_key rn_u.rn_leaf.rn_Key
-#define rn_mask rn_u.rn_leaf.rn_Mask
-
-/*
- * Annotations to tree concerning potential routes applying to subtrees.
- */
-
-struct squid_radix_mask {
- short rm_b; /* bit offset; -1-index(netmask) */
- char rm_unused; /* cf. rn_bmask */
- unsigned char rm_flags; /* cf. rn_flags */
-
- struct squid_radix_mask *rm_mklist; /* more masks to try */
- union {
- char *rmu_mask; /* the mask */
-
- struct squid_radix_node *rmu_leaf; /* for normal routes */
- } rm_rmu;
- int rm_refs; /* # of references to this struct */
-};
-
-struct squid_radix_node_head {
-
- struct squid_radix_node *rnh_treetop;
- int rnh_addrsize; /* permit, but not require fixed keys */
- int rnh_pktsize; /* permit, but not require fixed keys */
-
- struct squid_radix_node *(*rnh_addaddr) /* add based on sockaddr */
- (void *v, void *mask, struct squid_radix_node_head * head, struct squid_radix_node nodes[]);
-
- struct squid_radix_node *(*rnh_addpkt) /* add based on packet hdr */
- (void *v, void *mask, struct squid_radix_node_head * head, struct squid_radix_node nodes[]);
-
- struct squid_radix_node *(*rnh_deladdr) /* remove based on sockaddr */
- (void *v, void *mask, struct squid_radix_node_head * head);
-
- struct squid_radix_node *(*rnh_delpkt) /* remove based on packet hdr */
- (void *v, void *mask, struct squid_radix_node_head * head);
-
- struct squid_radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
- (void *v, struct squid_radix_node_head * head);
-
- struct squid_radix_node *(*rnh_lookup) /* locate based on sockaddr */
-
- (void *v, void *mask, struct squid_radix_node_head * head);
-
- struct squid_radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
- (void *v, struct squid_radix_node_head * head);
-
- int (*rnh_walktree) /* traverse tree */
- (struct squid_radix_node_head * head, int (*f) (struct squid_radix_node *, void *), void *w);
-
- struct squid_radix_node rnh_nodes[3]; /* empty tree for common case */
-};
-
-SQUIDCEXTERN void squid_rn_init (void);
-
-SQUIDCEXTERN int squid_rn_inithead(struct squid_radix_node_head **, int);
-SQUIDCEXTERN int squid_rn_refines(void *, void *);
-
-SQUIDCEXTERN int squid_rn_walktree(struct squid_radix_node_head *, int (*)(struct squid_radix_node *, void *), void *);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_addmask(void *, int, int);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_addroute(void *, void *, struct squid_radix_node_head *, struct squid_radix_node[2]);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_delete(void *, void *, struct squid_radix_node_head *);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_insert(void *, struct squid_radix_node_head *, int *, struct squid_radix_node[2]);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_match(void *, struct squid_radix_node_head *);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_newpair(void *, int, struct squid_radix_node[2]);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_search(void *, struct squid_radix_node *);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_search_m(void *, struct squid_radix_node *, void *);
-
-SQUIDCEXTERN struct squid_radix_node *squid_rn_lookup(void *, void *, struct squid_radix_node_head *);
-
-#endif /* SQUID_INCLUDE_RADIX_H */
-
libmiscutil_la_SOURCES = \
Splay.cc \
heap.c \
- radix.c \
util.cc
TESTS += tests/testRFC1738
+++ /dev/null
-/*
- * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/*
- * Copyright (c) 1988, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)radix.c 8.4 (Berkeley) 11/2/94
- */
-
-/*
- * DEBUG: section 53 Radix Tree data structure implementation
- */
-
-#include "squid.h"
-#include "radix.h"
-#include "util.h"
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_GRP_H
-#include <grp.h>
-#endif
-#if HAVE_GNUMALLOC_H
-#include <gnumalloc.h>
-#elif HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#if HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#if HAVE_ASSERT_H
-#include <assert.h>
-#endif
-
-int squid_max_keylen;
-struct squid_radix_mask *squid_rn_mkfreelist;
-struct squid_radix_node_head *squid_mask_rnhead;
-static char *addmask_key;
-static unsigned char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xFF};
-static char *rn_zeros, *rn_ones;
-
-/* aliases */
-#define rn_masktop (squid_mask_rnhead->rnh_treetop)
-#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
-#define rn_off rn_u.rn_node.rn_Off
-#define rn_l rn_u.rn_node.rn_L
-#define rn_r rn_u.rn_node.rn_R
-#define rm_mask rm_rmu.rmu_mask
-#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
-
-/* Helper macros */
-#define squid_R_Malloc(p, t, n) (p = (t) xmalloc((unsigned int)(n)))
-#define squid_Free(p) xfree((char *)p)
-#define squid_MKGet(m) {\
- if (squid_rn_mkfreelist) {\
- m = squid_rn_mkfreelist; \
- squid_rn_mkfreelist = (m)->rm_mklist; \
- } else \
- squid_R_Malloc(m, struct squid_radix_mask *, sizeof (*(m)));\
- }
-
-#define squid_MKFree(m) { (m)->rm_mklist = squid_rn_mkfreelist; squid_rn_mkfreelist = (m);}
-
-#ifndef min
-#define min(x,y) ((x)<(y)? (x) : (y))
-#endif
-/*
- * The data structure for the keys is a radix tree with one way
- * branching removed. The index rn_b at an internal node n represents a bit
- * position to be tested. The tree is arranged so that all descendants
- * of a node n have keys whose bits all agree up to position rn_b - 1.
- * (We say the index of n is rn_b.)
- *
- * There is at least one descendant which has a one bit at position rn_b,
- * and at least one with a zero there.
- *
- * A route is determined by a pair of key and mask. We require that the
- * bit-wise logical and of the key and mask to be the key.
- * We define the index of a route to associated with the mask to be
- * the first bit number in the mask where 0 occurs (with bit number 0
- * representing the highest order bit).
- *
- * We say a mask is normal if every bit is 0, past the index of the mask.
- * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b,
- * and m is a normal mask, then the route applies to every descendant of n.
- * If the index(m) < rn_b, this implies the trailing last few bits of k
- * before bit b are all 0, (and hence consequently true of every descendant
- * of n), so the route applies to all descendants of the node as well.
- *
- * Similar logic shows that a non-normal mask m such that
- * index(m) <= index(n) could potentially apply to many children of n.
- * Thus, for each non-host route, we attach its mask to a list at an internal
- * node as high in the tree as we can go.
- *
- * The present version of the code makes use of normal routes in short-
- * circuiting an explicit mask and compare operation when testing whether
- * a key satisfies a normal route, and also in remembering the unique leaf
- * that governs a subtree.
- */
-
-struct squid_radix_node *
-squid_rn_search(void *v_arg, struct squid_radix_node *head) {
- register struct squid_radix_node *x;
- register char *v;
-
- for (x = head, v = v_arg; x->rn_b >= 0;) {
- if (x->rn_bmask & v[x->rn_off])
- x = x->rn_r;
- else
- x = x->rn_l;
- }
- return (x);
-}
-
-struct squid_radix_node *
-squid_rn_search_m(void *v_arg, struct squid_radix_node *head, void *m_arg) {
- register struct squid_radix_node *x;
- register char *v = v_arg, *m = m_arg;
-
- for (x = head; x->rn_b >= 0;) {
- if ((x->rn_bmask & m[x->rn_off]) &&
- (x->rn_bmask & v[x->rn_off]))
- x = x->rn_r;
- else
- x = x->rn_l;
- }
- return x;
-}
-
-int
-squid_rn_refines(void *m_arg, void *n_arg)
-{
- register char *m = m_arg, *n = n_arg;
- register char *lim, *lim2 = lim = n + *(u_char *) n;
- int longer = (*(u_char *) n++) - (int) (*(u_char *) m++);
- int masks_are_equal = 1;
-
- if (longer > 0)
- lim -= longer;
- while (n < lim) {
- if (*n & ~(*m))
- return 0;
- if (*n++ != *m++)
- masks_are_equal = 0;
- }
- while (n < lim2)
- if (*n++)
- return 0;
- if (masks_are_equal && (longer < 0))
- for (lim2 = m - longer; m < lim2;)
- if (*m++)
- return 1;
- return (!masks_are_equal);
-}
-
-struct squid_radix_node *
-squid_rn_lookup(void *v_arg, void *m_arg, struct squid_radix_node_head *head) {
- register struct squid_radix_node *x;
- char *netmask = NULL;
-
- if (m_arg) {
- if ((x = squid_rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0)
- return (0);
- netmask = x->rn_key;
- }
- x = squid_rn_match(v_arg, head);
- if (x && netmask) {
- while (x && x->rn_mask != netmask)
- x = x->rn_dupedkey;
- }
- return x;
-}
-
-static int
-rn_satsifies_leaf(char *trial, register struct squid_radix_node *leaf, int skip)
-{
- register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
- char *cplim;
- int length = min(*(u_char *) cp, *(u_char *) cp2);
-
- if (cp3 == 0)
- cp3 = rn_ones;
- else
- length = min(length, *(u_char *) cp3);
- cplim = cp + length;
- cp3 += skip;
- cp2 += skip;
- for (cp += skip; cp < cplim; cp++, cp2++, cp3++)
- if ((*cp ^ *cp2) & *cp3)
- return 0;
- return 1;
-}
-
-struct squid_radix_node *
-squid_rn_match(void *v_arg, struct squid_radix_node_head *head) {
- char *v = v_arg;
- register struct squid_radix_node *t = head->rnh_treetop, *x;
- register char *cp = v, *cp2;
- char *cplim;
- struct squid_radix_node *saved_t, *top = t;
- int off = t->rn_off, vlen = *(u_char *) cp, matched_off;
- register int test, b, rn_b;
-
- /*
- * Open code squid_rn_search(v, top) to avoid overhead of extra
- * subroutine call.
- */
- for (; t->rn_b >= 0;) {
- if (t->rn_bmask & cp[t->rn_off])
- t = t->rn_r;
- else
- t = t->rn_l;
- }
- /*
- * See if we match exactly as a host destination
- * or at least learn how many bits match, for normal mask finesse.
- *
- * It doesn't hurt us to limit how many bytes to check
- * to the length of the mask, since if it matches we had a genuine
- * match and the leaf we have is the most specific one anyway;
- * if it didn't match with a shorter length it would fail
- * with a long one. This wins big for class B&C netmasks which
- * are probably the most common case...
- */
- if (t->rn_mask)
- vlen = *(u_char *) t->rn_mask;
- cp += off;
- cp2 = t->rn_key + off;
- cplim = v + vlen;
- for (; cp < cplim; cp++, cp2++)
- if (*cp != *cp2)
- goto on1;
- /*
- * This extra grot is in case we are explicitly asked
- * to look up the default. Ugh!
- */
- if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey)
- t = t->rn_dupedkey;
- return t;
-on1:
- test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */
- for (b = 7; (test >>= 1) > 0;)
- b--;
- matched_off = cp - v;
- b += matched_off << 3;
- rn_b = -1 - b;
- /*
- * If there is a host route in a duped-key chain, it will be first.
- */
- if ((saved_t = t)->rn_mask == 0)
- t = t->rn_dupedkey;
- for (; t; t = t->rn_dupedkey)
- /*
- * Even if we don't match exactly as a host,
- * we may match if the leaf we wound up at is
- * a route to a net.
- */
- if (t->rn_flags & RNF_NORMAL) {
- if (rn_b <= t->rn_b)
- return t;
- } else if (rn_satsifies_leaf(v, t, matched_off))
- return t;
- t = saved_t;
- /* start searching up the tree */
- do {
- register struct squid_radix_mask *m;
- t = t->rn_p;
- if ((m = t->rn_mklist)) {
- /*
- * If non-contiguous masks ever become important
- * we can restore the masking and open coding of
- * the search and satisfaction test and put the
- * calculation of "off" back before the "do".
- */
- do {
- if (m->rm_flags & RNF_NORMAL) {
- if (rn_b <= m->rm_b)
- return (m->rm_leaf);
- } else {
- off = min(t->rn_off, matched_off);
- x = squid_rn_search_m(v, t, m->rm_mask);
- while (x && x->rn_mask != m->rm_mask)
- x = x->rn_dupedkey;
- if (x && rn_satsifies_leaf(v, x, off))
- return x;
- }
- } while ((m = m->rm_mklist));
- }
- } while (t != top);
- return 0;
-}
-
-struct squid_radix_node *
-squid_rn_newpair(void *v, int b, struct squid_radix_node nodes[2]) {
- register struct squid_radix_node *tt = nodes, *t = tt + 1;
- t->rn_b = b;
- t->rn_bmask = 0x80 >> (b & 7);
- t->rn_l = tt;
- t->rn_off = b >> 3;
- tt->rn_b = -1;
- tt->rn_key = (char *) v;
- tt->rn_p = t;
- tt->rn_flags = t->rn_flags = RNF_ACTIVE;
- return t;
-}
-
-struct squid_radix_node *
-squid_rn_insert(void *v_arg, struct squid_radix_node_head *head, int *dupentry, struct squid_radix_node nodes[2]) {
- char *v = v_arg;
- struct squid_radix_node *top = head->rnh_treetop;
- int head_off = top->rn_off, vlen = (int) *((u_char *) v);
- register struct squid_radix_node *t = squid_rn_search(v_arg, top);
- register char *cp = v + head_off;
- register int b;
- struct squid_radix_node *tt;
- /*
- * Find first bit at which v and t->rn_key differ
- */
- {
- register char *cp2 = t->rn_key + head_off;
- register int cmp_res;
- char *cplim = v + vlen;
-
- while (cp < cplim)
- if (*cp2++ != *cp++)
- goto on1;
- *dupentry = 1;
- return t;
-on1:
- *dupentry = 0;
- cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
- for (b = (cp - v) << 3; cmp_res; b--)
- cmp_res >>= 1;
- }
- {
- register struct squid_radix_node *p, *x = top;
- cp = v;
- do {
- p = x;
- if (cp[x->rn_off] & x->rn_bmask)
- x = x->rn_r;
- else
- x = x->rn_l;
- } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */
- t = squid_rn_newpair(v_arg, b, nodes);
- tt = t->rn_l;
- if ((cp[p->rn_off] & p->rn_bmask) == 0)
- p->rn_l = t;
- else
- p->rn_r = t;
- x->rn_p = t;
- t->rn_p = p; /* frees x, p as temp vars below */
- if ((cp[t->rn_off] & t->rn_bmask) == 0) {
- t->rn_r = x;
- } else {
- t->rn_r = tt;
- t->rn_l = x;
- }
- }
- return (tt);
-}
-
-struct squid_radix_node *
-squid_rn_addmask(void *n_arg, int search, int skip) {
- char *netmask = (char *) n_arg;
- register struct squid_radix_node *x;
- register char *cp, *cplim;
- register int b = 0, mlen, j;
- int maskduplicated, m0, isnormal;
- struct squid_radix_node *saved_x;
- static int last_zeroed = 0;
-
- if ((mlen = *(u_char *) netmask) > squid_max_keylen)
- mlen = squid_max_keylen;
- if (skip == 0)
- skip = 1;
- if (mlen <= skip)
- return (squid_mask_rnhead->rnh_nodes);
- if (skip > 1)
- memcpy(addmask_key + 1, rn_ones + 1, skip - 1);
- if ((m0 = mlen) > skip)
- memcpy(addmask_key + skip, netmask + skip, mlen - skip);
- /*
- * Trim trailing zeroes.
- */
- for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;)
- cp--;
- mlen = cp - addmask_key;
- if (mlen <= skip) {
- if (m0 >= last_zeroed)
- last_zeroed = mlen;
- return (squid_mask_rnhead->rnh_nodes);
- }
- if (m0 < last_zeroed)
- memset(addmask_key + m0, '\0', last_zeroed - m0);
- *addmask_key = last_zeroed = mlen;
- x = squid_rn_search(addmask_key, rn_masktop);
- if (memcmp(addmask_key, x->rn_key, mlen) != 0)
- x = 0;
- if (x || search)
- return (x);
- squid_R_Malloc(x, struct squid_radix_node *, squid_max_keylen + 2 * sizeof(*x));
- if ((saved_x = x) == 0)
- return (0);
- memset(x, '\0', squid_max_keylen + 2 * sizeof(*x));
- netmask = cp = (char *) (x + 2);
- memcpy(cp, addmask_key, mlen);
- x = squid_rn_insert(cp, squid_mask_rnhead, &maskduplicated, x);
- if (maskduplicated) {
- fprintf(stderr, "squid_rn_addmask: mask impossibly already in tree");
- squid_Free(saved_x);
- return (x);
- }
- /*
- * Calculate index of mask, and check for normalcy.
- */
- cplim = netmask + mlen;
- isnormal = 1;
- for (cp = netmask + skip; (cp < cplim) && *(u_char *) cp == 0xff;)
- cp++;
- if (cp != cplim) {
- for (j = 0x80; (j & *cp) != 0; j >>= 1)
- b++;
- if (*cp != normal_chars[b] || cp != (cplim - 1))
- isnormal = 0;
- }
- b += (cp - netmask) << 3;
- x->rn_b = -1 - b;
- if (isnormal)
- x->rn_flags |= RNF_NORMAL;
- return (x);
-}
-
-static int /* XXX: arbitrary ordering for non-contiguous masks */
-rn_lexobetter(void *m_arg, void *n_arg)
-{
- register u_char *mp = m_arg, *np = n_arg, *lim;
-
- if (*mp > *np)
- return 1; /* not really, but need to check longer one first */
- if (*mp == *np)
- for (lim = mp + *mp; mp < lim;)
- if (*mp++ > *np++)
- return 1;
- return 0;
-}
-
-static struct squid_radix_mask *
-rn_new_radix_mask(struct squid_radix_node *tt, struct squid_radix_mask *next) {
- register struct squid_radix_mask *m;
-
- squid_MKGet(m);
- if (m == 0) {
- fprintf(stderr, "Mask for route not entered\n");
- return (0);
- }
- memset(m, '\0', sizeof *m);
- m->rm_b = tt->rn_b;
- m->rm_flags = tt->rn_flags;
- if (tt->rn_flags & RNF_NORMAL)
- m->rm_leaf = tt;
- else
- m->rm_mask = tt->rn_mask;
- m->rm_mklist = next;
- tt->rn_mklist = m;
- return m;
-}
-
-struct squid_radix_node *
-squid_rn_addroute(void *v_arg, void *n_arg, struct squid_radix_node_head *head, struct squid_radix_node treenodes[2]) {
- char *v = (char *) v_arg, *netmask = (char *) n_arg;
- register struct squid_radix_node *t, *x = NULL, *tt;
- struct squid_radix_node *saved_tt, *top = head->rnh_treetop;
- short b = 0, b_leaf = 0;
- int keyduplicated;
- char *mmask;
- struct squid_radix_mask *m, **mp;
-
- /*
- * In dealing with non-contiguous masks, there may be
- * many different routes which have the same mask.
- * We will find it useful to have a unique pointer to
- * the mask to speed avoiding duplicate references at
- * nodes and possibly save time in calculating indices.
- */
- if (netmask) {
- if ((x = squid_rn_addmask(netmask, 0, top->rn_off)) == 0)
- return (0);
- b_leaf = x->rn_b;
- b = -1 - x->rn_b;
- netmask = x->rn_key;
- }
- /*
- * Deal with duplicated keys: attach node to previous instance
- */
- saved_tt = tt = squid_rn_insert(v, head, &keyduplicated, treenodes);
- if (keyduplicated) {
- for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {
- if (tt->rn_mask == netmask)
- return (0);
- if (netmask == 0 ||
- (tt->rn_mask &&
- ((b_leaf < tt->rn_b) || /* index(netmask) > node */
- squid_rn_refines(netmask, tt->rn_mask) ||
- rn_lexobetter(netmask, tt->rn_mask))))
- break;
- }
- /*
- * If the mask is not duplicated, we wouldn't
- * find it among possible duplicate key entries
- * anyway, so the above test doesn't hurt.
- *
- * We sort the masks for a duplicated key the same way as
- * in a masklist -- most specific to least specific.
- * This may require the unfortunate nuisance of relocating
- * the head of the list.
- */
- if (tt == saved_tt) {
- struct squid_radix_node *xx = x;
- /* link in at head of list */
- tt = treenodes;
- tt->rn_dupedkey = t;
- tt->rn_flags = t->rn_flags;
- tt->rn_p = x = t->rn_p;
- if (x->rn_l == t)
- x->rn_l = tt;
- else
- x->rn_r = tt;
- saved_tt = tt;
- x = xx;
- } else {
- tt = treenodes;
- tt->rn_dupedkey = t->rn_dupedkey;
- t->rn_dupedkey = tt;
- }
- tt->rn_key = (char *) v;
- tt->rn_b = -1;
- tt->rn_flags = RNF_ACTIVE;
- }
- /*
- * Put mask in tree.
- */
- if (netmask) {
- tt->rn_mask = netmask;
- tt->rn_b = x->rn_b;
- tt->rn_flags |= x->rn_flags & RNF_NORMAL;
- }
- t = saved_tt->rn_p;
- if (keyduplicated)
- goto on2;
- b_leaf = -1 - t->rn_b;
- if (t->rn_r == saved_tt)
- x = t->rn_l;
- else
- x = t->rn_r;
- /* Promote general routes from below */
- if (x->rn_b < 0) {
- for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
- if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) {
- if ((*mp = m = rn_new_radix_mask(x, 0)))
- mp = &m->rm_mklist;
- }
- } else if (x->rn_mklist) {
- /*
- * Skip over masks whose index is > that of new node
- */
- for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
- if (m->rm_b >= b_leaf)
- break;
- t->rn_mklist = m;
- *mp = 0;
- }
-on2:
- /* Add new route to highest possible ancestor's list */
- if ((netmask == 0) || (b > t->rn_b))
- return tt; /* can't lift at all */
- b_leaf = tt->rn_b;
- do {
- x = t;
- t = t->rn_p;
- } while (b <= t->rn_b && x != top);
- /*
- * Search through routes associated with node to
- * insert new route according to index.
- * Need same criteria as when sorting dupedkeys to avoid
- * double loop on deletion.
- */
- for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) {
- if (m->rm_b < b_leaf)
- continue;
- if (m->rm_b > b_leaf)
- break;
- if (m->rm_flags & RNF_NORMAL) {
- mmask = m->rm_leaf->rn_mask;
- if (tt->rn_flags & RNF_NORMAL) {
- fprintf(stderr,
- "Non-unique normal route, mask not entered");
- return tt;
- }
- } else
- mmask = m->rm_mask;
- if (mmask == netmask) {
- m->rm_refs++;
- tt->rn_mklist = m;
- return tt;
- }
- if (squid_rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask))
- break;
- }
- *mp = rn_new_radix_mask(tt, *mp);
- return tt;
-}
-
-struct squid_radix_node *
-squid_rn_delete(void *v_arg, void *netmask_arg, struct squid_radix_node_head *head) {
- register struct squid_radix_node *t, *p, *x, *tt;
- struct squid_radix_mask *m, *saved_m, **mp;
- struct squid_radix_node *dupedkey, *saved_tt, *top;
- char *v, *netmask;
- int b, head_off, vlen;
-
- v = v_arg;
- netmask = netmask_arg;
- x = head->rnh_treetop;
- tt = squid_rn_search(v, x);
- head_off = x->rn_off;
- vlen = *(u_char *) v;
- saved_tt = tt;
- top = x;
- if (tt == 0 ||
- memcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
- return (0);
- /*
- * Delete our route from mask lists.
- */
- if (netmask) {
- if ((x = squid_rn_addmask(netmask, 1, head_off)) == 0)
- return (0);
- netmask = x->rn_key;
- while (tt->rn_mask != netmask)
- if ((tt = tt->rn_dupedkey) == 0)
- return (0);
- }
- if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)
- goto on1;
- if (tt->rn_flags & RNF_NORMAL) {
- if (m->rm_leaf != tt || m->rm_refs > 0) {
- fprintf(stderr, "squid_rn_delete: inconsistent annotation\n");
- return 0; /* dangling ref could cause disaster */
- }
- } else {
- if (m->rm_mask != tt->rn_mask) {
- fprintf(stderr, "squid_rn_delete: inconsistent annotation\n");
- goto on1;
- }
- if (--m->rm_refs >= 0)
- goto on1;
- }
- b = -1 - tt->rn_b;
- t = saved_tt->rn_p;
- if (b > t->rn_b)
- goto on1; /* Wasn't lifted at all */
- do {
- x = t;
- t = t->rn_p;
- } while (b <= t->rn_b && x != top);
- for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
- if (m == saved_m) {
- *mp = m->rm_mklist;
- squid_MKFree(m);
- break;
- }
- if (m == 0) {
- fprintf(stderr, "squid_rn_delete: couldn't find our annotation\n");
- if (tt->rn_flags & RNF_NORMAL)
- return (0); /* Dangling ref to us */
- }
-on1:
- /*
- * Eliminate us from tree
- */
- if (tt->rn_flags & RNF_ROOT)
- return (0);
- t = tt->rn_p;
- if ((dupedkey = saved_tt->rn_dupedkey)) {
- if (tt == saved_tt) {
- x = dupedkey;
- x->rn_p = t;
- if (t->rn_l == tt)
- t->rn_l = x;
- else
- t->rn_r = x;
- } else {
- for (x = p = saved_tt; p && p->rn_dupedkey != tt;)
- p = p->rn_dupedkey;
- if (p)
- p->rn_dupedkey = tt->rn_dupedkey;
- else
- fprintf(stderr, "squid_rn_delete: couldn't find us\n");
- }
- t = tt + 1;
- if (t->rn_flags & RNF_ACTIVE) {
- *++x = *t;
- p = t->rn_p;
- if (p->rn_l == t)
- p->rn_l = x;
- else
- p->rn_r = x;
- x->rn_l->rn_p = x;
- x->rn_r->rn_p = x;
- }
- goto out;
- }
- if (t->rn_l == tt)
- x = t->rn_r;
- else
- x = t->rn_l;
- p = t->rn_p;
- if (p->rn_r == t)
- p->rn_r = x;
- else
- p->rn_l = x;
- x->rn_p = p;
- /*
- * Demote routes attached to us.
- */
- if (t->rn_mklist) {
- if (x->rn_b >= 0) {
- for (mp = &x->rn_mklist; (m = *mp);)
- mp = &m->rm_mklist;
- *mp = t->rn_mklist;
- } else {
- /* If there are any key,mask pairs in a sibling
- * duped-key chain, some subset will appear sorted
- * in the same order attached to our mklist */
- for (m = t->rn_mklist; m && x; x = x->rn_dupedkey)
- if (m == x->rn_mklist) {
- struct squid_radix_mask *mm = m->rm_mklist;
- x->rn_mklist = 0;
- if (--(m->rm_refs) < 0)
- squid_MKFree(m);
- m = mm;
- }
- assert(m == NULL);
- }
- }
- /*
- * We may be holding an active internal node in the tree.
- */
- x = tt + 1;
- if (t != x) {
- *t = *x;
- t->rn_l->rn_p = t;
- t->rn_r->rn_p = t;
- p = x->rn_p;
- if (p->rn_l == x)
- p->rn_l = t;
- else
- p->rn_r = t;
- }
-out:
- tt->rn_flags &= ~RNF_ACTIVE;
- tt[1].rn_flags &= ~RNF_ACTIVE;
- return (tt);
-}
-
-int
-squid_rn_walktree(struct squid_radix_node_head *h, int (*f) (struct squid_radix_node *, void *), void *w)
-{
- int error;
- struct squid_radix_node *base, *next;
- register struct squid_radix_node *rn = h->rnh_treetop;
- /*
- * This gets complicated because we may delete the node
- * while applying the function f to it, so we need to calculate
- * the successor node in advance.
- */
- /* First time through node, go left */
- while (rn->rn_b >= 0)
- rn = rn->rn_l;
- for (;;) {
- base = rn;
- /* If at right child go back up, otherwise, go right */
- while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0)
- rn = rn->rn_p;
- /* Find the next *leaf* since next node might vanish, too */
- for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;)
- rn = rn->rn_l;
- next = rn;
- /* Process leaves */
- while ((rn = base)) {
- base = rn->rn_dupedkey;
- if (!(rn->rn_flags & RNF_ROOT) && (error = (*f) (rn, w)))
- return (error);
- }
- rn = next;
- if (rn->rn_flags & RNF_ROOT)
- return (0);
- }
- /* NOTREACHED */
-}
-
-int
-squid_rn_inithead(struct squid_radix_node_head **head, int off)
-{
- register struct squid_radix_node_head *rnh;
- register struct squid_radix_node *t, *tt, *ttt;
- if (*head)
- return (1);
- squid_R_Malloc(rnh, struct squid_radix_node_head *, sizeof(*rnh));
- if (rnh == 0)
- return (0);
- memset(rnh, '\0', sizeof(*rnh));
- *head = rnh;
- t = squid_rn_newpair(rn_zeros, off, rnh->rnh_nodes);
- ttt = rnh->rnh_nodes + 2;
- t->rn_r = ttt;
- t->rn_p = t;
- tt = t->rn_l;
- tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
- tt->rn_b = -1 - off;
- *ttt = *tt;
- ttt->rn_key = rn_ones;
- rnh->rnh_addaddr = squid_rn_addroute;
- rnh->rnh_deladdr = squid_rn_delete;
- rnh->rnh_matchaddr = squid_rn_match;
- rnh->rnh_lookup = squid_rn_lookup;
- rnh->rnh_walktree = squid_rn_walktree;
- rnh->rnh_treetop = t;
- return (1);
-}
-
-void
-squid_rn_init(void)
-{
- char *cp, *cplim;
-#ifdef KERNEL
- struct domain *dom;
-
- for (dom = domains; dom; dom = dom->dom_next)
- if (dom->dom_maxrtkey > squid_max_keylen)
- squid_max_keylen = dom->dom_maxrtkey;
-#endif
- if (squid_max_keylen == 0) {
- fprintf(stderr,
- "squid_rn_init: radix functions require squid_max_keylen be set\n");
- return;
- }
- squid_R_Malloc(rn_zeros, char *, 3 * squid_max_keylen);
- if (rn_zeros == NULL) {
- fprintf(stderr, "squid_rn_init failed.\n");
- exit(-1);
- }
- memset(rn_zeros, '\0', 3 * squid_max_keylen);
- rn_ones = cp = rn_zeros + squid_max_keylen;
- addmask_key = cplim = rn_ones + squid_max_keylen;
- while (cp < cplim)
- *cp++ = -1;
- if (squid_rn_inithead(&squid_mask_rnhead, 0) == 0) {
- fprintf(stderr, "rn_init2 failed.\n");
- exit(-1);
- }
-}
-
#include "acl/AtStep.h"
#include "acl/AtStepData.h"
#endif
-#include "acl/Asn.h"
#include "acl/Checklist.h"
#include "acl/ConnectionsEncrypted.h"
#include "acl/Data.h"
-#include "acl/DestinationAsn.h"
#include "acl/DestinationDomain.h"
#include "acl/DestinationIp.h"
#include "acl/DomainData.h"
#include "acl/ReplyMimeType.h"
#include "acl/RequestHeaderStrategy.h"
#include "acl/RequestMimeType.h"
-#include "acl/SourceAsn.h"
#include "acl/SourceDomain.h"
#include "acl/SourceIp.h"
#include "acl/SquidError.h"
RegisterMaker("any-of", [](TypeName)->Node* { return new AnyOf; }); // XXX: Add name parameter to ctor
RegisterMaker("random", [](TypeName name)->Node* { return new ACLRandom(name); });
RegisterMaker("time", [](TypeName name)->Node* { return new FinalizedParameterizedNode<CurrentTimeCheck>(name, new ACLTimeData); });
- RegisterMaker("src_as", [](TypeName name)->Node* { return new FinalizedParameterizedNode<SourceAsnCheck>(name, new ACLASN); });
- RegisterMaker("dst_as", [](TypeName name)->Node* { return new FinalizedParameterizedNode<DestinationAsnCheck>(name, new ACLASN); });
RegisterMaker("browser", [](TypeName name)->Node* { return new FinalizedParameterizedNode<RequestHeaderCheck<Http::HdrType::USER_AGENT> >(name, new ACLRegexData); });
RegisterMaker("dstdomain", [](TypeName name)->Node* { return new FinalizedParameterizedNode<DestinationDomainCheck>(name, new ACLDomainData); });
{"htcp", initHtcp},
{"icp", initIcp},
{"icmp", initIcmp},
- {"asn", initAsn},
{"ipc", initIpc},
{"adaptation", initAdaptation},
{"icon", initIcon},
initHtcp = 1<< 5, ///< HTCP client
initIcp = 1 << 6, ///< the ICP/neighbors subsystem
initIcmp = 1 << 7, ///< the ICMP RTT database (NetDB) neighbors exchange subsystem
- initAsn = 1 << 8, ///< the ASN db subsystem
initIpc = 1 << 9, ///< the IPC subsystem
initAdaptation = 1 << 10, ///< ICAP/ECAP requests generated by Squid
initIcon = 1 << 11, ///< internal icons
+++ /dev/null
-/*
- * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
- *
- * 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 53 AS Number handling */
-
-#include "squid.h"
-#include "acl/Acl.h"
-#include "acl/Asn.h"
-#include "acl/DestinationAsn.h"
-#include "acl/DestinationIp.h"
-#include "acl/FilledChecklist.h"
-#include "acl/SourceAsn.h"
-#include "base/CharacterSet.h"
-#include "FwdState.h"
-#include "HttpReply.h"
-#include "HttpRequest.h"
-#include "ipcache.h"
-#include "MasterXaction.h"
-#include "mgr/Registration.h"
-#include "parser/Tokenizer.h"
-#include "radix.h"
-#include "RequestFlags.h"
-#include "sbuf/SBuf.h"
-#include "SquidConfig.h"
-#include "Store.h"
-#include "StoreClient.h"
-
-/* BEGIN of definitions for radix tree entries */
-
-/* 32/128 bits address in memory with length */
-class m_ADDR
-{
-public:
- uint8_t len;
- Ip::Address addr;
-
- m_ADDR() : len(sizeof(Ip::Address)) {};
-};
-
-/* END of definitions for radix tree entries */
-
-/* Head for ip to asn radix tree */
-
-struct squid_radix_node_head *AS_tree_head;
-
-/* explicit instantiation required for some systems */
-
-/// \cond AUTODOCS_IGNORE
-template cbdata_type CbDataList<int>::CBDATA_CbDataList;
-/// \endcond
-
-/**
- * Structure for as number information. it could be simply
- * a list but it's coded as a structure for future
- * enhancements (e.g. expires)
- */
-struct as_info {
- CbDataList<int> *as_number;
- time_t expires; /* NOTUSED */
-};
-
-class ASState
-{
- CBDATA_CLASS(ASState);
-
-public:
- ASState() = default;
-
- ~ASState() {
- if (entry) {
- debugs(53, 3, entry->url());
- storeUnregister(sc, entry, this);
- entry->unlock("~ASState");
- }
- }
-
-public:
- StoreEntry *entry = nullptr;
- store_client *sc = nullptr;
- HttpRequest::Pointer request;
- int as_number = 0;
-
- /// for receiving a WHOIS reply body from Store and interpreting it
- Store::ParsingBuffer parsingBuffer;
-};
-
-CBDATA_CLASS_INIT(ASState);
-
-/** entry into the radix tree */
-struct rtentry_t {
- struct squid_radix_node e_nodes[2];
- as_info *e_info;
- m_ADDR e_addr;
- m_ADDR e_mask;
-};
-
-static int asnAddNet(const SBuf &, int);
-
-static void asnCacheStart(int as);
-
-static STCB asHandleReply;
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-static int destroyRadixNode(struct squid_radix_node *rn, void *w);
-static int printRadixNode(struct squid_radix_node *rn, void *sentry);
-
-#if defined(__cplusplus)
-}
-#endif
-
-static void destroyRadixNodeInfo(as_info *);
-
-static OBJH asnStats;
-
-/* PUBLIC */
-
-int
-asnMatchIp(CbDataList<int> *data, Ip::Address &addr)
-{
- struct squid_radix_node *rn;
- as_info *e;
- m_ADDR m_addr;
- CbDataList<int> *a = nullptr;
- CbDataList<int> *b = nullptr;
-
- debugs(53, 3, "asnMatchIp: Called for " << addr );
-
- if (AS_tree_head == nullptr)
- return 0;
-
- if (addr.isNoAddr())
- return 0;
-
- if (addr.isAnyAddr())
- return 0;
-
- m_addr.addr = addr;
-
- rn = squid_rn_match(&m_addr, AS_tree_head);
-
- if (rn == nullptr) {
- debugs(53, 3, "asnMatchIp: Address not in as db.");
- return 0;
- }
-
- debugs(53, 3, "asnMatchIp: Found in db!");
- e = ((rtentry_t *) rn)->e_info;
- assert(e);
-
- for (a = data; a; a = a->next)
- for (b = e->as_number; b; b = b->next)
- if (a->element == b->element) {
- debugs(53, 5, "asnMatchIp: Found a match!");
- return 1;
- }
-
- debugs(53, 5, "asnMatchIp: AS not in as db.");
- return 0;
-}
-
-void
-ACLASN::prepareForUse()
-{
- for (CbDataList<int> *i = data; i; i = i->
- next)
- asnCacheStart(i->element);
-}
-
-static void
-asnRegisterWithCacheManager(void)
-{
- Mgr::RegisterAction("asndb", "AS Number Database", asnStats, 0, 1);
-}
-
-/* initialize the radix tree structure */
-
-SQUIDCEXTERN int squid_max_keylen; /* yuck.. this is in lib/radix.c */
-
-void
-asnInit(void)
-{
- static bool inited = false;
- squid_max_keylen = 40;
-
- if (!inited) {
- inited = true;
- squid_rn_init();
- }
-
- squid_rn_inithead(&AS_tree_head, 8);
-
- asnRegisterWithCacheManager();
-}
-
-void
-asnFreeMemory(void)
-{
- squid_rn_walktree(AS_tree_head, destroyRadixNode, AS_tree_head);
-
- destroyRadixNode((struct squid_radix_node *) nullptr, (void *) AS_tree_head);
-}
-
-static void
-asnStats(StoreEntry * sentry)
-{
- storeAppendPrintf(sentry, "Address \tAS Numbers\n");
- squid_rn_walktree(AS_tree_head, printRadixNode, sentry);
-}
-
-/* PRIVATE */
-
-static void
-asnCacheStart(int as)
-{
- AnyP::Uri whoisUrl(AnyP::PROTO_WHOIS);
- whoisUrl.host(Config.as_whois_server);
- whoisUrl.defaultPort();
-
- SBuf asPath("/!gAS");
- asPath.appendf("%d", as);
- whoisUrl.path(asPath);
-
- debugs(53, 3, "AS " << as);
- ASState *asState = new ASState;
- asState->as_number = as;
- const auto mx = MasterXaction::MakePortless<XactionInitiator::initAsn>();
- asState->request = new HttpRequest(mx);
- asState->request->url = whoisUrl;
- asState->request->method = Http::METHOD_GET;
-
- // XXX: performance regression, c_str() reallocates
- const auto asres = xstrdup(whoisUrl.absolute().c_str());
-
- // XXX: Missing a hittingRequiresCollapsing() && startCollapsingOn() check.
- auto e = storeGetPublic(asres, Http::METHOD_GET);
- if (!e) {
- e = storeCreateEntry(asres, asres, RequestFlags(), Http::METHOD_GET);
- asState->sc = storeClientListAdd(e, asState);
- FwdState::fwdStart(Comm::ConnectionPointer(), e, asState->request.getRaw());
- } else {
- e->lock("Asn");
- asState->sc = storeClientListAdd(e, asState);
- }
- xfree(asres);
-
- asState->entry = e;
- storeClientCopy(asState->sc, e, asState->parsingBuffer.makeInitialSpace(), asHandleReply, asState);
-}
-
-static void
-asHandleReply(void *data, StoreIOBuffer result)
-{
- ASState *asState = (ASState *)data;
- StoreEntry *e = asState->entry;
-
- debugs(53, 3, result << " for " << asState->as_number << " with " << *e);
-
- /* First figure out whether we should abort the request */
-
- if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
- delete asState;
- return;
- }
-
- if (result.flags.error) {
- debugs(53, DBG_IMPORTANT, "ERROR: asHandleReply: Called with Error set and size=" << (unsigned int) result.length);
- delete asState;
- return;
- } else if (e->mem().baseReply().sline.status() != Http::scOkay) {
- debugs(53, DBG_IMPORTANT, "WARNING: AS " << asState->as_number << " whois request failed");
- delete asState;
- return;
- }
-
- asState->parsingBuffer.appended(result.data, result.length);
- Parser::Tokenizer tok(SBuf(asState->parsingBuffer.content().data, asState->parsingBuffer.contentSize()));
- SBuf address;
- // Word delimiters in WHOIS ASN replies. RFC 3912 mentions SP, CR, and LF.
- // Others are added to mimic an earlier isspace()-based implementation.
- static const auto WhoisSpaces = CharacterSet("ASCII_spaces", " \f\r\n\t\v");
- while (tok.token(address, WhoisSpaces)) {
- (void)asnAddNet(address, asState->as_number);
- }
- asState->parsingBuffer.consume(tok.parsedSize());
- const auto leftoverBytes = asState->parsingBuffer.contentSize();
-
- if (asState->sc->atEof()) {
- if (leftoverBytes)
- debugs(53, 2, "WHOIS: Discarding the last " << leftoverBytes << " received bytes of a truncated AS response");
- delete asState;
- return;
- }
-
- const auto remainingSpace = asState->parsingBuffer.space().positionAt(result.offset + result.length);
-
- if (!remainingSpace.length) {
- Assure(leftoverBytes);
- debugs(53, DBG_IMPORTANT, "WARNING: Ignoring the tail of a WHOIS AS response" <<
- " with an unparsable section of " << leftoverBytes <<
- " bytes ending at offset " << remainingSpace.offset);
- delete asState;
- return;
- }
-
- const decltype(StoreIOBuffer::offset) stillReasonableOffset = 100000; // an arbitrary limit in bytes
- if (remainingSpace.offset > stillReasonableOffset) {
- // stop suspicious accumulation of parsed addresses and/or work
- debugs(53, DBG_IMPORTANT, "WARNING: Ignoring the tail of a suspiciously large WHOIS AS response" <<
- " exceeding " << stillReasonableOffset << " bytes");
- delete asState;
- return;
- }
-
- storeClientCopy(asState->sc, e, remainingSpace, asHandleReply, asState);
-}
-
-/**
- * add a network (addr, mask) to the radix tree, with matching AS number
- */
-static int
-asnAddNet(const SBuf &addressAndMask, const int as_number)
-{
- struct squid_radix_node *rn;
- CbDataList<int> **Tail = nullptr;
- CbDataList<int> *q = nullptr;
- as_info *asinfo = nullptr;
-
- static const CharacterSet NonSlashSet = CharacterSet("slash", "/").complement("non-slash");
- Parser::Tokenizer tok(addressAndMask);
- SBuf addressToken;
- if (!(tok.prefix(addressToken, NonSlashSet) && tok.skip('/'))) {
- debugs(53, 3, "asnAddNet: failed, invalid response from whois server.");
- return 0;
- }
- const Ip::Address addr = addressToken.c_str();
-
- // INET6 TODO : find a better way of identifying the base IPA family for mask than this.
- const auto addrFamily = (addressToken.find('.') != SBuf::npos) ? AF_INET : AF_INET6;
-
- // generate Netbits Format Mask
- Ip::Address mask;
- mask.setNoAddr();
- int64_t bitl = 0;
- if (tok.int64(bitl, 10, false))
- mask.applyMask(bitl, addrFamily);
-
- debugs(53, 3, "asnAddNet: called for " << addr << "/" << mask );
-
- rtentry_t *e = (rtentry_t *)xcalloc(1, sizeof(rtentry_t));
-
- e->e_addr.addr = addr;
-
- e->e_mask.addr = mask;
-
- rn = squid_rn_lookup(&e->e_addr, &e->e_mask, AS_tree_head);
-
- if (rn != nullptr) {
- asinfo = ((rtentry_t *) rn)->e_info;
-
- if (asinfo->as_number->find(as_number)) {
- debugs(53, 3, "asnAddNet: Ignoring repeated network '" << addr << "/" << bitl << "' for AS " << as_number);
- } else {
- debugs(53, 3, "asnAddNet: Warning: Found a network with multiple AS numbers!");
-
- for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next);
- q = new CbDataList<int> (as_number);
-
- *(Tail) = q;
-
- e->e_info = asinfo;
- }
- } else {
- q = new CbDataList<int> (as_number);
- asinfo = (as_info *)xmalloc(sizeof(as_info));
- asinfo->as_number = q;
- squid_rn_addroute(&e->e_addr, &e->e_mask, AS_tree_head, e->e_nodes);
- rn = squid_rn_match(&e->e_addr, AS_tree_head);
- assert(rn != nullptr);
- e->e_info = asinfo;
- }
-
- if (rn == nullptr) { /* assert might expand to nothing */
- xfree(asinfo);
- delete q;
- xfree(e);
- debugs(53, 3, "asnAddNet: Could not add entry.");
- return 0;
- }
-
- e->e_info = asinfo;
- return 1;
-}
-
-static int
-destroyRadixNode(struct squid_radix_node *rn, void *w)
-{
-
- struct squid_radix_node_head *rnh = (struct squid_radix_node_head *) w;
-
- if (rn && !(rn->rn_flags & RNF_ROOT)) {
- rtentry_t *e = (rtentry_t *) rn;
- rn = squid_rn_delete(rn->rn_key, rn->rn_mask, rnh);
-
- if (rn == nullptr)
- debugs(53, 3, "destroyRadixNode: internal screwup");
-
- destroyRadixNodeInfo(e->e_info);
-
- xfree(rn);
- }
-
- return 1;
-}
-
-static void
-destroyRadixNodeInfo(as_info * e_info)
-{
- CbDataList<int> *prev = nullptr;
- CbDataList<int> *data = e_info->as_number;
-
- while (data) {
- prev = data;
- data = data->next;
- delete prev;
- }
-}
-
-static int
-printRadixNode(struct squid_radix_node *rn, void *_sentry)
-{
- StoreEntry *sentry = (StoreEntry *)_sentry;
- rtentry_t *e = (rtentry_t *) rn;
- CbDataList<int> *q;
- as_info *asinfo;
- char buf[MAX_IPSTRLEN];
- Ip::Address addr;
- Ip::Address mask;
-
- assert(e);
- assert(e->e_info);
- addr = e->e_addr.addr;
- mask = e->e_mask.addr;
- storeAppendPrintf(sentry, "%s/%d\t",
- addr.toStr(buf, MAX_IPSTRLEN),
- mask.cidr() );
- asinfo = e->e_info;
- assert(asinfo->as_number);
-
- for (q = asinfo->as_number; q; q = q->next)
- storeAppendPrintf(sentry, " %d", q->element);
-
- storeAppendPrintf(sentry, "\n");
-
- return 0;
-}
-
-ACLASN::~ACLASN()
-{
- if (data)
- delete data;
-}
-
-bool
-
-ACLASN::match(Ip::Address toMatch)
-{
- return asnMatchIp(data, toMatch);
-}
-
-SBufList
-ACLASN::dump() const
-{
- SBufList sl;
-
- CbDataList<int> *ldata = data;
-
- while (ldata != nullptr) {
- SBuf s;
- s.Printf("%d", ldata->element);
- sl.push_back(s);
- ldata = ldata->next;
- }
-
- return sl;
-}
-
-bool
-ACLASN::empty () const
-{
- return data == nullptr;
-}
-
-void
-ACLASN::parse()
-{
- CbDataList<int> **curlist = &data;
- CbDataList<int> **Tail;
- CbDataList<int> *q = nullptr;
- char *t = nullptr;
-
- for (Tail = curlist; *Tail; Tail = &((*Tail)->next));
- while ((t = ConfigParser::strtokFile())) {
- q = new CbDataList<int> (atoi(t));
- *(Tail) = q;
- Tail = &q->next;
- }
-}
-
-int
-Acl::SourceAsnCheck::match(ACLChecklist * const ch)
-{
- const auto checklist = Filled(ch);
-
- return data->match(checklist->src_addr);
-}
-
-int
-Acl::DestinationAsnCheck::match(ACLChecklist * const ch)
-{
- const auto checklist = Filled(ch);
-
- const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->url.host(), IP_LOOKUP_IF_MISS);
-
- if (ia) {
- for (const auto &ip: ia->goodAndBad()) {
- if (data->match(ip))
- return 1;
- }
-
- return 0;
-
- } else if (!checklist->request->flags.destinationIpLookedUp) {
- /* No entry in cache, lookup not attempted */
- debugs(28, 3, "can't yet compare '" << name << "' ACL for " << checklist->request->url.host());
- if (checklist->goAsync(ACLDestinationIP::StartLookup, *this))
- return -1;
- // else fall through to noaddr match, hiding the lookup failure (XXX)
- }
- Ip::Address noaddr;
- noaddr.setNoAddr();
- return data->match(noaddr);
-}
-
+++ /dev/null
-/*
- * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_SRC_ACL_ASN_H
-#define SQUID_SRC_ACL_ASN_H
-
-#include "acl/Data.h"
-#include "base/CbDataList.h"
-#include "ip/Address.h"
-
-int asnMatchIp(CbDataList<int> *, Ip::Address &);
-
-/// \ingroup ACLAPI
-void asnInit(void);
-
-/// \ingroup ACLAPI
-void asnFreeMemory(void);
-
-/// \ingroup ACLAPI
-class ACLASN : public ACLData<Ip::Address>
-{
- MEMPROXY_CLASS(ACLASN);
-
-public:
- ACLASN() : data(nullptr) {}
- ~ACLASN() override;
-
- bool match(Ip::Address) override;
- SBufList dump() const override;
- void parse() override;
- bool empty() const override;
- void prepareForUse() override;
-
-private:
- CbDataList<int> *data;
-};
-
-#endif /* SQUID_SRC_ACL_ASN_H */
-
+++ /dev/null
-/*
- * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_SRC_ACL_DESTINATIONASN_H
-#define SQUID_SRC_ACL_DESTINATIONASN_H
-
-#include "acl/Data.h"
-#include "acl/ParameterizedNode.h"
-#include "ip/forward.h"
-
-namespace Acl
-{
-
-/// a "dst_as" ACL
-class DestinationAsnCheck: public ParameterizedNode< ACLData<Ip::Address> >
-{
-public:
- /* Acl::Node API */
- int match(ACLChecklist *) override;
- bool requiresRequest() const override {return true;}
-};
-
-} // namespace Acl
-
-#endif /* SQUID_SRC_ACL_DESTINATIONASN_H */
-
AnnotationData.h \
AnyOf.cc \
AnyOf.h \
- Asn.cc \
- Asn.h \
AtStep.cc \
AtStep.h \
AtStepData.cc \
ConnMark.h \
ConnectionsEncrypted.cc \
ConnectionsEncrypted.h \
- DestinationAsn.h \
DestinationDomain.cc \
DestinationDomain.h \
DestinationIp.cc \
ReplyMimeType.h \
RequestHeaderStrategy.h \
RequestMimeType.h \
- SourceAsn.h \
SourceDomain.cc \
SourceDomain.h \
SourceIp.cc \
+++ /dev/null
-/*
- * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_SRC_ACL_SOURCEASN_H
-#define SQUID_SRC_ACL_SOURCEASN_H
-
-#include "acl/Data.h"
-#include "acl/ParameterizedNode.h"
-#include "ip/forward.h"
-
-namespace Acl
-{
-
-/// a "src_as" ACL
-class SourceAsnCheck: public ParameterizedNode< ACLData<Ip::Address> >
-{
-public:
- /* Acl::Node API */
- int match(ACLChecklist *) override;
-};
-
-} // namespace Acl
-
-#endif /* SQUID_SRC_ACL_SOURCEASN_H */
-
# based URL is used and no match is found. The name "none" is used
# if the reverse lookup fails.
- acl aclname src_as number ...
- acl aclname dst_as number ...
- # [fast]
- # Except for access control, AS numbers can be used for
- # routing of requests to specific caches. Here's an
- # example for routing all requests for AS#1241 and only
- # those to mycache.mydomain.net:
- # acl asexample dst_as 1241
- # cache_peer_access mycache.mydomain.net allow asexample
- # cache_peer_access mycache_mydomain.net deny all
-
acl aclname peername myPeer ...
acl aclname peername_regex [-i] regex-pattern ...
# [fast]
# htcp: matches HTCP requests from peers
# icp: matches ICP requests to peers
# icmp: matches ICMP RTT database (NetDB) requests to peers
- # asn: matches asns db requests
# internal: matches any of the above
# client: matches transactions containing an HTTP or FTP
# client request received at a Squid *_port
Examples:
acl macaddress arp 09:00:2b:23:45:67
- acl myexample dst_as 1241
acl password proxy_auth REQUIRED
acl fileupload req_mime_type -i ^multipart/form-data$
acl javascript rep_mime_type -i ^application/x-javascript$
Some valid actions are (see cache manager menu for a full list):
5min
60min
- asndb
authenticator
cbdata
client_list
#include "squid.h"
#include "AccessLogEntry.h"
//#include "acl/Acl.h"
-#include "acl/Asn.h"
#include "acl/forward.h"
#include "anyp/UriScheme.h"
#include "auth/Config.h"
icmpEngine.Open();
netdbInit();
- asnInit();
Acl::Node::Initialize();
peerSelectInit();
}
#if SQUID_SNMP
snmpClosePorts();
#endif
-
- asnFreeMemory();
}
}