]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/asn.cc
3 * $Id: asn.cc,v 1.68 2001/01/12 00:37:14 wessels Exp $
5 * DEBUG: section 53 AS Number handling
6 * AUTHOR: Duane Wessels, Kostas Anagnostakis
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
40 /* BEGIN of definitions for radix tree entries */
42 /* int in memory with length */
43 typedef u_char m_int
[1 + sizeof(unsigned int)];
44 #define store_m_int(i, m) \
45 (i = htonl(i), m[0] = sizeof(m_int), xmemcpy(m+1, &i, sizeof(unsigned int)))
46 #define get_m_int(i, m) \
47 (xmemcpy(&i, m+1, sizeof(unsigned int)), ntohl(i))
49 /* END of definitions for radix tree entries */
51 /* Head for ip to asn radix tree */
52 struct radix_node_head
*AS_tree_head
;
55 * Structure for as number information. it could be simply
56 * an intlist but it's coded as a structure for future
57 * enhancements (e.g. expires)
61 time_t expires
; /* NOTUSED */
73 typedef struct _ASState ASState
;
74 typedef struct _as_info as_info
;
76 /* entry into the radix tree */
78 struct radix_node e_nodes
[2];
84 typedef struct _rtentry rtentry
;
86 static int asnAddNet(char *, int);
87 static void asnCacheStart(int as
);
88 static STCB asHandleReply
;
89 static int destroyRadixNode(struct radix_node
*rn
, void *w
);
90 static int printRadixNode(struct radix_node
*rn
, void *w
);
91 static void asnAclInitialize(acl
* acls
);
92 static void asStateFree(void *data
);
93 static void destroyRadixNodeInfo(as_info
*);
96 extern struct radix_node
*rn_lookup(void *, void *, void *);
102 asnMatchIp(void *data
, struct in_addr addr
)
105 struct radix_node
*rn
;
110 lh
= ntohl(addr
.s_addr
);
111 debug(53, 3) ("asnMatchIp: Called for %s.\n", inet_ntoa(addr
));
113 if (AS_tree_head
== NULL
)
115 if (addr
.s_addr
== no_addr
.s_addr
)
117 if (addr
.s_addr
== any_addr
.s_addr
)
119 store_m_int(lh
, m_addr
);
120 rn
= rn_match(m_addr
, AS_tree_head
);
122 debug(53, 3) ("asnMatchIp: Address not in as db.\n");
125 debug(53, 3) ("asnMatchIp: Found in db!\n");
126 e
= ((rtentry
*) rn
)->e_info
;
128 for (a
= (intlist
*) data
; a
; a
= a
->next
)
129 for (b
= e
->as_number
; b
; b
= b
->next
)
131 debug(53, 5) ("asnMatchIp: Found a match!\n");
134 debug(53, 5) ("asnMatchIp: AS not in as db.\n");
139 asnAclInitialize(acl
* acls
)
143 debug(53, 3) ("asnAclInitialize\n");
144 for (a
= acls
; a
; a
= a
->next
) {
145 if (a
->type
!= ACL_DST_ASN
&& a
->type
!= ACL_SRC_ASN
)
147 for (i
= a
->data
; i
; i
= i
->next
)
152 /* initialize the radix tree structure */
154 CBDATA_TYPE(ASState
);
158 extern int max_keylen
;
159 static int inited
= 0;
161 CBDATA_INIT_TYPE(ASState
);
164 rn_inithead((void **) &AS_tree_head
, 8);
165 asnAclInitialize(Config
.aclList
);
166 cachemgrRegister("asndb", "AS Number Database", asnStats
, 0, 1);
172 rn_walktree(AS_tree_head
, destroyRadixNode
, AS_tree_head
);
173 destroyRadixNode((struct radix_node
*) 0, (void *) AS_tree_head
);
177 asnStats(StoreEntry
* sentry
)
179 storeAppendPrintf(sentry
, "Address \tAS Numbers\n");
180 rn_walktree(AS_tree_head
, printRadixNode
, sentry
);
187 asnCacheStart(int as
)
189 LOCAL_ARRAY(char, asres
, 4096);
193 asState
= CBDATA_ALLOC(ASState
, NULL
);
194 debug(53, 3) ("asnCacheStart: AS %d\n", as
);
195 snprintf(asres
, 4096, "whois://%s/!gAS%d", Config
.as_whois_server
, as
);
196 asState
->as_number
= as
;
197 req
= urlParse(METHOD_GET
, asres
);
199 asState
->request
= requestLink(req
);
200 if ((e
= storeGetPublic(asres
, METHOD_GET
)) == NULL
) {
201 e
= storeCreateEntry(asres
, asres
, null_request_flags
, METHOD_GET
);
202 asState
->sc
= storeClientListAdd(e
, asState
);
203 fwdStart(-1, e
, asState
->request
);
206 asState
->sc
= storeClientListAdd(e
, asState
);
211 storeClientCopy(asState
->sc
,
216 memAllocate(MEM_4K_BUF
),
222 asHandleReply(void *data
, char *buf
, ssize_t size
)
224 ASState
*asState
= data
;
225 StoreEntry
*e
= asState
->entry
;
228 debug(53, 3) ("asHandleReply: Called with size=%d\n", size
);
229 if (EBIT_TEST(e
->flags
, ENTRY_ABORTED
)) {
230 memFree(buf
, MEM_4K_BUF
);
231 asStateFree(asState
);
234 if (size
== 0 && e
->mem_obj
->inmem_hi
> 0) {
235 memFree(buf
, MEM_4K_BUF
);
236 asStateFree(asState
);
238 } else if (size
< 0) {
239 debug(53, 1) ("asHandleReply: Called with size=%d\n", size
);
240 memFree(buf
, MEM_4K_BUF
);
241 asStateFree(asState
);
243 } else if (HTTP_OK
!= e
->mem_obj
->reply
->sline
.status
) {
244 debug(53, 1) ("WARNING: AS %d whois request failed\n",
246 memFree(buf
, MEM_4K_BUF
);
247 asStateFree(asState
);
251 while (s
- buf
< size
&& *s
!= '\0') {
252 while (*s
&& xisspace(*s
))
254 for (t
= s
; *t
; t
++) {
259 /* oof, word should continue on next block */
263 debug(53, 3) ("asHandleReply: AS# %s (%d)\n", s
, asState
->as_number
);
264 asnAddNet(s
, asState
->as_number
);
267 asState
->seen
= asState
->offset
+ size
;
268 asState
->offset
+= (s
- buf
);
269 debug(53, 3) ("asState->seen = %d, asState->offset = %d\n",
270 asState
->seen
, asState
->offset
);
271 if (e
->store_status
== STORE_PENDING
) {
272 debug(53, 3) ("asHandleReply: store_status == STORE_PENDING: %s\n", storeUrl(e
));
273 storeClientCopy(asState
->sc
,
281 } else if (asState
->seen
< e
->mem_obj
->inmem_hi
) {
282 debug(53, 3) ("asHandleReply: asState->seen < e->mem_obj->inmem_hi %s\n", storeUrl(e
));
283 storeClientCopy(asState
->sc
,
292 debug(53, 3) ("asHandleReply: Done: %s\n", storeUrl(e
));
293 memFree(buf
, MEM_4K_BUF
);
294 asStateFree(asState
);
299 asStateFree(void *data
)
301 ASState
*asState
= data
;
302 debug(53, 3) ("asnStateFree: %s\n", storeUrl(asState
->entry
));
303 storeUnregister(asState
->sc
, asState
->entry
, asState
);
304 storeUnlockObject(asState
->entry
);
305 requestUnlink(asState
->request
);
310 /* add a network (addr, mask) to the radix tree, with matching AS
314 asnAddNet(char *as_string
, int as_number
)
316 rtentry
*e
= xmalloc(sizeof(rtentry
));
317 struct radix_node
*rn
;
318 char dbg1
[32], dbg2
[32];
319 intlist
**Tail
= NULL
;
321 as_info
*asinfo
= NULL
;
322 struct in_addr in_a
, in_m
;
327 t
= strchr(as_string
, '/');
329 debug(53, 3) ("asnAddNet: failed, invalid response from whois server.\n");
333 addr
= inet_addr(as_string
);
339 mask
= bitl
? 0xfffffffful
<< (32 - bitl
) : 0;
343 xstrncpy(dbg1
, inet_ntoa(in_a
), 32);
344 xstrncpy(dbg2
, inet_ntoa(in_m
), 32);
346 /*mask = ntohl(mask); */
347 debug(53, 3) ("asnAddNet: called for %s/%s\n", dbg1
, dbg2
);
348 memset(e
, '\0', sizeof(rtentry
));
349 store_m_int(addr
, e
->e_addr
);
350 store_m_int(mask
, e
->e_mask
);
351 rn
= rn_lookup(e
->e_addr
, e
->e_mask
, AS_tree_head
);
353 asinfo
= ((rtentry
*) rn
)->e_info
;
354 if (intlistFind(asinfo
->as_number
, as_number
)) {
355 debug(53, 3) ("asnAddNet: Ignoring repeated network '%s/%d' for AS %d\n",
356 dbg1
, bitl
, as_number
);
358 debug(53, 3) ("asnAddNet: Warning: Found a network with multiple AS numbers!\n");
359 for (Tail
= &asinfo
->as_number
; *Tail
; Tail
= &(*Tail
)->next
);
360 q
= xcalloc(1, sizeof(intlist
));
366 q
= xcalloc(1, sizeof(intlist
));
368 asinfo
= xmalloc(sizeof(asinfo
));
369 asinfo
->as_number
= q
;
370 rn
= rn_addroute(e
->e_addr
, e
->e_mask
, AS_tree_head
, e
->e_nodes
);
371 rn
= rn_match(e
->e_addr
, AS_tree_head
);
377 debug(53, 3) ("asnAddNet: Could not add entry.\n");
385 destroyRadixNode(struct radix_node
*rn
, void *w
)
387 struct radix_node_head
*rnh
= (struct radix_node_head
*) w
;
389 if (rn
&& !(rn
->rn_flags
& RNF_ROOT
)) {
390 rtentry
*e
= (rtentry
*) rn
;
391 rn
= rn_delete(rn
->rn_key
, rn
->rn_mask
, rnh
);
393 debug(53, 3) ("destroyRadixNode: internal screwup\n");
394 destroyRadixNodeInfo(e
->e_info
);
401 destroyRadixNodeInfo(as_info
* e_info
)
403 intlist
*prev
= NULL
;
404 intlist
*data
= e_info
->as_number
;
419 while ((mask
& 1) == 0) {
427 printRadixNode(struct radix_node
*rn
, void *w
)
429 StoreEntry
*sentry
= w
;
430 rtentry
*e
= (rtentry
*) rn
;
437 (void) get_m_int(addr
.s_addr
, e
->e_addr
);
438 (void) get_m_int(mask
.s_addr
, e
->e_mask
);
439 storeAppendPrintf(sentry
, "%15s/%d\t",
440 inet_ntoa(addr
), mask_len(ntohl(mask
.s_addr
)));
442 assert(asinfo
->as_number
);
443 for (q
= asinfo
->as_number
; q
; q
= q
->next
)
444 storeAppendPrintf(sentry
, " %d", q
->i
);
445 storeAppendPrintf(sentry
, "\n");