From 6dd8532932de0a73fdc194b4919c0d64a753eae2 Mon Sep 17 00:00:00 2001 From: kostas <> Date: Sun, 21 Dec 1997 17:57:52 +0000 Subject: [PATCH] Initial as number acl checking for clients plus hack for server as number routing --- src/asn.cc | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 199 insertions(+), 11 deletions(-) diff --git a/src/asn.cc b/src/asn.cc index 637944446a..ce787cd25e 100644 --- a/src/asn.cc +++ b/src/asn.cc @@ -1,13 +1,56 @@ +/* + * + * DEBUG: section 53 AS Number handling + * AUTHOR: Duane Wessels + * + * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ + * -------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from the + * Internet community. Development is led by Duane Wessels of the + * National Laboratory for Applied Network Research and funded by + * the National Science Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ #include "squid.h" #define WHOIS_PORT 43 +/* BEGIN of definitions for radix tree entries */ + +typedef u_char m_int[1 + sizeof(unsigned int)]; /* int in memory with length */ +#define store_m_int(i, m) \ + (i = htonl(i), m[0] = sizeof(m_int), memcpy(m+1, &i, sizeof(unsigned int))) +#define get_m_int(i, m) \ + (memcpy(&i, m+1, sizeof(unsigned int)), ntohl(i)) + +/* END of definitions for radix tree entries */ + +static int asndbAddNet(char *, int); static void asnLoadStart(int as); static PF asnLoadClose; static CNCB asnLoadConnected; static PF asnLoadRead; +extern struct radix_node *rn_lookup(void *, void *, void *); +/* Head for ip to asn radix tree */ +struct radix_node_head *AS_tree_head; +/* passed to asnLoadStart when reading configuration options */ struct _asnLoadData { int as; char *buf; @@ -15,11 +58,58 @@ struct _asnLoadData { off_t offset; }; + +/* structure for as number information. it could be simply + * an intlist but it's coded as a structure for future + * enhancements (e.g. expires) */ +struct _as_info { + intlist *as_number; + int expires; +}; +typedef struct _as_info as_info; + +/* entry into the radix tree */ +struct _rtentry { + struct radix_node e_nodes[2]; + as_info *e_info; + m_int e_addr; + m_int e_mask; +}; + +typedef struct _rtentry rtentry; + + + /* PUBLIC */ int asnMatchIp(void *data, struct in_addr addr) { + unsigned long lh; + struct radix_node *rn; + as_info *e; + m_int m_addr; + intlist *a = NULL, *b = NULL; + lh = ntohl(addr.s_addr); + debug(53, 4) ("asnMatchIp: Called for %s.\n", inet_ntoa(addr)); + + if (AS_tree_head == 0) + return 0; + store_m_int(lh, m_addr); + rn = rn_match(m_addr, AS_tree_head); + if (rn == 0) { + debug(53, 4) ("asnMatchIp: Address not in as db.\n"); + return 0; + } + debug(53, 4) ("asnMatchIp: Found in db!\n"); + e = ((rtentry *) rn)->e_info; + for (a = (intlist *) data; a; a = a->next) + for (b = e->as_number; b; b = b->next) + if (a->i == b->i) { + debug(53, 5) ("asnMatchIp: Found a match!\n"); + return 1; + } + debug(53, 5) ("asnMatchIp: AS not in as db.\n"); return 0; } @@ -28,7 +118,7 @@ asnAclInitialize(acl * acls) { acl *a; intlist *i; - debug(0, 0) ("asnAclInitialize: STARTING\n"); + debug(53, 1) ("asnAclInitialize: STARTING\n"); for (a = acls; a; a = a->next) { if (a->type != ACL_DST_ASN && a->type != ACL_SRC_ASN) continue; @@ -40,37 +130,48 @@ asnAclInitialize(acl * acls) /* PRIVATE */ + +/* connects to whois server to find out networks belonging to + * a certain AS */ + static void asnLoadStart(int as) { int fd; struct _asnLoadData *p = xcalloc(1, sizeof(struct _asnLoadData)); cbdataAdd(p); - debug(0, 0) ("asnLoad: AS# %d\n", as); + debug(53, 1) ("asnLoad: AS# %d\n", as); p->as = as; fd = comm_open(SOCK_STREAM, 0, any_addr, 0, COMM_NONBLOCKING, "asnLoad"); if (fd == COMM_ERROR) { - debug(0, 0) ("asnLoad: failed to open a socket\n"); + debug(53, 0) ("asnLoad: failed to open a socket\n"); return; } comm_add_close_handler(fd, asnLoadClose, p); commConnectStart(fd, "whois.ra.net", WHOIS_PORT, asnLoadConnected, p); } + +/* we're finished, so we close the connection and add the + * network numbers to the database */ + static void asnLoadClose(int fdnotused, void *data) { struct _asnLoadData *p = data; + debug(53, 6) ("asnLoadClose called\n"); cbdataFree(p); } + +/* we're connected to the whois server, so we send out the request ! */ static void asnLoadConnected(int fd, int status, void *data) { struct _asnLoadData *p = data; char buf[128]; if (status != COMM_OK) { - debug(0, 0) ("asnLoadConnected: connection failed\n"); + debug(53, 0) ("asnLoadConnected: connection failed\n"); comm_close(fd); return; } @@ -78,11 +179,14 @@ asnLoadConnected(int fd, int status, void *data) p->offset = 0; p->bufsz = 4096; p->buf = get_free_4k_page(); - debug(0, 0) ("asnLoadConnected: FD %d, '%s'\n", fd, buf); + debug(53, 1) ("asnLoadConnected: FD %d, '%s'\n", fd, buf); comm_write(fd, xstrdup(buf), strlen(buf), NULL, p, xfree); commSetSelect(fd, COMM_SELECT_READ, asnLoadRead, p, Config.Timeout.read); } +/* we got reply data waiting, copy it to our buffer structure + * to parse it later */ + static void asnLoadRead(int fd, void *data) { @@ -91,14 +195,15 @@ asnLoadRead(int fd, void *data) char *s; size_t readsz; int len; + readsz = p->bufsz - p->offset; readsz--; - debug(0, 0) ("asnLoadRead: offset = %d\n", p->offset); + debug(53, 6) ("asnLoadRead: offset = %d\n", p->offset); s = p->buf + p->offset; len = read(fd, s, readsz); - debug(0, 0) ("asnLoadRead: read %d bytes\n", len); + debug(53, 6) ("asnLoadRead: read %d bytes\n", len); if (len <= 0) { - debug(0, 0) ("asnLoadRead: got EOF\n"); + debug(53, 5) ("asnLoadRead: got EOF\n"); comm_close(fd); return; } @@ -116,19 +221,102 @@ asnLoadRead(int fd, void *data) break; } *t = '\0'; - debug(0, 0) ("asnLoadRead: AS# %d '%s'\n", p->as, s); + debug(53, 4) ("asnLoadRead: AS# %d '%s'\n", p->as, s); + asndbAddNet(s, p->as); s = t + 1; while (*s && isspace(*s)) s++; } if (*s) { /* expect more */ - debug(0, 0) ("asnLoadRead: AS# %d expecting more\n", p->as); + debug(53, 6) ("asnLoadRead: AS# %d expecting more\n", p->as); xstrncpy(p->buf, s, p->bufsz); p->offset = strlen(p->buf); - debug(0, 0) ("asnLoadRead: p->buf = '%s'\n", p->buf); + debug(53, 6) ("asnLoadRead: p->buf = '%s'\n", p->buf); } else { p->offset = 0; } commSetSelect(fd, COMM_SELECT_READ, asnLoadRead, p, Config.Timeout.read); } + + +/* initialize the radix tree structure */ + +void +asndbInit() +{ + extern int max_keylen; + max_keylen = 40; + rn_init(); + rn_inithead((void **) &AS_tree_head, 8); + +} + +/* add a network (addr, mask) to the radix tree, with matching AS + * number */ + +static int +asndbAddNet(char *as_string, int as_number) +{ + rtentry *e = xmalloc(sizeof(rtentry)); + struct radix_node *rn; + char dbg1[32], dbg2[32]; + intlist **Tail = NULL; + intlist *q = NULL; + as_info *info = NULL; + struct in_addr in_a, in_m; + long mask, addr; + char *t; + int bitl; + + t = index(as_string, '/'); + if (t == NULL) { + debug(53, 3) ("asndbAddNet: failed, no network.\n"); + return 0; + } + *t = '\0'; + addr = inet_addr(as_string); + bitl = atoi(t + 1); + mask = (1 << bitl) - 1; + + in_a.s_addr = addr; + in_m.s_addr = mask; + strcpy(dbg1, inet_ntoa(in_a)); + strcpy(dbg2, inet_ntoa(in_m)); + addr = ntohl(addr); + mask = ntohl(mask); + debug(53, 3) ("asndbAddNet: called for %s/%s (%x/%x)\n", dbg1, dbg2, addr, mask); + memset(e, '\0', sizeof(rtentry)); + store_m_int(addr, e->e_addr); + store_m_int(mask, e->e_mask); + rn = rn_lookup(e->e_addr, e->e_mask, AS_tree_head); + if (rn != 0) { + debug(53, 3) ("Oops. Found a network with multiple AS numbers!\n"); + info = ((rtentry *) rn)->e_info; + for (Tail = &(info->as_number); *Tail; Tail = &((*Tail)->next)); + q = xcalloc(1, sizeof(intlist)); + q->i = as_number; + *(Tail) = q; + e->e_info = info; + } else { + q = xcalloc(1, sizeof(intlist)); + q->i = as_number; + /* *(Tail) = q; */ + info = xmalloc(sizeof(as_info)); + info->as_number = q; + rn = rn_addroute(e->e_addr, e->e_mask, AS_tree_head, e->e_nodes); + rn = rn_match(e->e_addr, AS_tree_head); + if (rn == NULL) + fatal_dump("cannot add entry...\n"); + e->e_info = info; + + } + if (rn == 0) { + xfree(e); + debug(53, 3) ("Could not add entry.\n"); + return 0; + } + e->e_info = info; + debug(53, 3) ("added successfully.\n"); + return 1; +} -- 2.47.3