asn.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:11k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: asn.c,v 1.56.2.1 1999/02/12 19:38:22 wessels Exp $
  3.  *
  4.  * DEBUG: section 53    AS Number handling
  5.  * AUTHOR: Duane Wessels, Kostas Anagnostakis
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. #define WHOIS_PORT 43
  36. /* BEGIN of definitions for radix tree entries */
  37. /* int in memory with length */
  38. typedef u_char m_int[1 + sizeof(unsigned int)];
  39. #define store_m_int(i, m) 
  40.     (i = htonl(i), m[0] = sizeof(m_int), xmemcpy(m+1, &i, sizeof(unsigned int)))
  41. #define get_m_int(i, m) 
  42.     (xmemcpy(&i, m+1, sizeof(unsigned int)), ntohl(i))
  43. /* END of definitions for radix tree entries */
  44. /* Head for ip to asn radix tree */
  45. struct radix_node_head *AS_tree_head;
  46. /*
  47.  * Structure for as number information. it could be simply 
  48.  * an intlist but it's coded as a structure for future
  49.  * enhancements (e.g. expires)
  50.  */
  51. struct _as_info {
  52.     intlist *as_number;
  53.     time_t expires; /* NOTUSED */
  54. };
  55. struct _ASState {
  56.     StoreEntry *entry;
  57.     request_t *request;
  58.     int as_number;
  59.     off_t seen;
  60.     off_t offset;
  61. };
  62. typedef struct _ASState ASState;
  63. typedef struct _as_info as_info;
  64. /* entry into the radix tree */
  65. struct _rtentry {
  66.     struct radix_node e_nodes[2];
  67.     as_info *e_info;
  68.     m_int e_addr;
  69.     m_int e_mask;
  70. };
  71. typedef struct _rtentry rtentry;
  72. static int asnAddNet(char *, int);
  73. static void asnCacheStart(int as);
  74. static STCB asHandleReply;
  75. static int destroyRadixNode(struct radix_node *rn, void *w);
  76. static int printRadixNode(struct radix_node *rn, void *w);
  77. static void asnAclInitialize(acl * acls);
  78. static void asStateFree(void *data);
  79. static void destroyRadixNodeInfo(as_info *);
  80. static OBJH asnStats;
  81. extern struct radix_node *rn_lookup(void *, void *, void *);
  82. /* PUBLIC */
  83. int
  84. asnMatchIp(void *data, struct in_addr addr)
  85. {
  86.     unsigned long lh;
  87.     struct radix_node *rn;
  88.     as_info *e;
  89.     m_int m_addr;
  90.     intlist *a = NULL;
  91.     intlist *b = NULL;
  92.     lh = ntohl(addr.s_addr);
  93.     debug(53, 3) ("asnMatchIp: Called for %s.n", inet_ntoa(addr));
  94.     if (AS_tree_head == NULL)
  95. return 0;
  96.     if (addr.s_addr == no_addr.s_addr)
  97. return 0;
  98.     if (addr.s_addr == any_addr.s_addr)
  99. return 0;
  100.     store_m_int(lh, m_addr);
  101.     rn = rn_match(m_addr, AS_tree_head);
  102.     if (rn == NULL) {
  103. debug(53, 3) ("asnMatchIp: Address not in as db.n");
  104. return 0;
  105.     }
  106.     debug(53, 3) ("asnMatchIp: Found in db!n");
  107.     e = ((rtentry *) rn)->e_info;
  108.     assert(e);
  109.     for (a = (intlist *) data; a; a = a->next)
  110. for (b = e->as_number; b; b = b->next)
  111.     if (a->i == b->i) {
  112. debug(53, 5) ("asnMatchIp: Found a match!n");
  113. return 1;
  114.     }
  115.     debug(53, 5) ("asnMatchIp: AS not in as db.n");
  116.     return 0;
  117. }
  118. static void
  119. asnAclInitialize(acl * acls)
  120. {
  121.     acl *a;
  122.     intlist *i;
  123.     debug(53, 3) ("asnAclInitializen");
  124.     for (a = acls; a; a = a->next) {
  125. if (a->type != ACL_DST_ASN && a->type != ACL_SRC_ASN)
  126.     continue;
  127. for (i = a->data; i; i = i->next)
  128.     asnCacheStart(i->i);
  129.     }
  130. }
  131. /* initialize the radix tree structure */
  132. void
  133. asnInit(void)
  134. {
  135.     extern int max_keylen;
  136.     static int inited = 0;
  137.     max_keylen = 40;
  138.     if (0 == inited++)
  139. rn_init();
  140.     rn_inithead((void **) &AS_tree_head, 8);
  141.     asnAclInitialize(Config.aclList);
  142.     cachemgrRegister("asndb", "AS Number Database", asnStats, 0, 1);
  143. }
  144. void
  145. asnFreeMemory(void)
  146. {
  147.     rn_walktree(AS_tree_head, destroyRadixNode, AS_tree_head);
  148.     destroyRadixNode((struct radix_node *) 0, (void *) AS_tree_head);
  149. }
  150. static void
  151. asnStats(StoreEntry * sentry)
  152. {
  153.     storeAppendPrintf(sentry, "Address    tAS Numbersn");
  154.     rn_walktree(AS_tree_head, printRadixNode, sentry);
  155. }
  156. /* PRIVATE */
  157. static void
  158. asnCacheStart(int as)
  159. {
  160.     LOCAL_ARRAY(char, asres, 4096);
  161.     StoreEntry *e;
  162.     request_t *req;
  163.     ASState *asState = xcalloc(1, sizeof(ASState));
  164.     cbdataAdd(asState, cbdataXfree, 0);
  165.     debug(53, 3) ("asnCacheStart: AS %dn", as);
  166.     snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as);
  167.     asState->as_number = as;
  168.     req = urlParse(METHOD_GET, asres);
  169.     assert(NULL != req);
  170.     asState->request = requestLink(req);
  171.     if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) {
  172. e = storeCreateEntry(asres, asres, null_request_flags, METHOD_GET);
  173. storeClientListAdd(e, asState);
  174. fwdStart(-1, e, asState->request, no_addr, no_addr);
  175.     } else {
  176. storeLockObject(e);
  177. storeClientListAdd(e, asState);
  178.     }
  179.     asState->entry = e;
  180.     asState->seen = 0;
  181.     asState->offset = 0;
  182.     storeClientCopy(e,
  183. asState->seen,
  184. asState->offset,
  185. 4096,
  186. memAllocate(MEM_4K_BUF),
  187. asHandleReply,
  188. asState);
  189. }
  190. static void
  191. asHandleReply(void *data, char *buf, ssize_t size)
  192. {
  193.     ASState *asState = data;
  194.     StoreEntry *e = asState->entry;
  195.     char *s;
  196.     char *t;
  197.     debug(53, 3) ("asHandleReply: Called with size=%dn", size);
  198.     if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
  199. memFree(buf, MEM_4K_BUF);
  200. asStateFree(asState);
  201. return;
  202.     }
  203.     if (size == 0 && e->mem_obj->inmem_hi > 0) {
  204. memFree(buf, MEM_4K_BUF);
  205. asStateFree(asState);
  206. return;
  207.     } else if (size < 0) {
  208. debug(53, 1) ("asHandleReply: Called with size=%dn", size);
  209. memFree(buf, MEM_4K_BUF);
  210. asStateFree(asState);
  211. return;
  212.     }
  213.     s = buf;
  214.     while (s - buf < size && *s != '') {
  215. while (*s && xisspace(*s))
  216.     s++;
  217. for (t = s; *t; t++) {
  218.     if (xisspace(*t))
  219. break;
  220. }
  221. if (*t == '') {
  222.     /* oof, word should continue on next block */
  223.     break;
  224. }
  225. *t = '';
  226. debug(53, 3) ("asHandleReply: AS# %s (%d)n", s, asState->as_number);
  227. asnAddNet(s, asState->as_number);
  228. s = t + 1;
  229.     }
  230.     asState->seen = asState->offset + size;
  231.     asState->offset += (s - buf);
  232.     debug(53, 3) ("asState->seen = %d, asState->offset = %dn",
  233. asState->seen, asState->offset);
  234.     if (e->store_status == STORE_PENDING) {
  235. debug(53, 3) ("asHandleReply: store_status == STORE_PENDING: %sn", storeUrl(e));
  236. storeClientCopy(e,
  237.     asState->seen,
  238.     asState->offset,
  239.     SM_PAGE_SIZE,
  240.     buf,
  241.     asHandleReply,
  242.     asState);
  243.     } else if (asState->seen < e->mem_obj->inmem_hi) {
  244. debug(53, 3) ("asHandleReply: asState->seen < e->mem_obj->inmem_hi %sn", storeUrl(e));
  245. storeClientCopy(e,
  246.     asState->seen,
  247.     asState->offset,
  248.     SM_PAGE_SIZE,
  249.     buf,
  250.     asHandleReply,
  251.     asState);
  252.     } else {
  253. debug(53, 3) ("asHandleReply: Done: %sn", storeUrl(e));
  254. memFree(buf, MEM_4K_BUF);
  255. asStateFree(asState);
  256.     }
  257. }
  258. static void
  259. asStateFree(void *data)
  260. {
  261.     ASState *asState = data;
  262.     debug(53, 3) ("asnStateFree: %sn", storeUrl(asState->entry));
  263.     storeUnregister(asState->entry, asState);
  264.     storeUnlockObject(asState->entry);
  265.     requestUnlink(asState->request);
  266.     cbdataFree(asState);
  267. }
  268. /* add a network (addr, mask) to the radix tree, with matching AS
  269.  * number */
  270. static int
  271. asnAddNet(char *as_string, int as_number)
  272. {
  273.     rtentry *e = xmalloc(sizeof(rtentry));
  274.     struct radix_node *rn;
  275.     char dbg1[32], dbg2[32];
  276.     intlist **Tail = NULL;
  277.     intlist *q = NULL;
  278.     as_info *asinfo = NULL;
  279.     struct in_addr in_a, in_m;
  280.     long mask, addr;
  281.     char *t;
  282.     int bitl;
  283.     t = strchr(as_string, '/');
  284.     if (t == NULL) {
  285. debug(53, 3) ("asnAddNet: failed, invalid response from whois server.n");
  286. return 0;
  287.     }
  288.     *t = '';
  289.     addr = inet_addr(as_string);
  290.     bitl = atoi(t + 1);
  291.     if (bitl < 0)
  292. bitl = 0;
  293.     if (bitl > 32)
  294. bitl = 32;
  295.     mask = bitl ? 0xfffffffful << (32 - bitl) : 0;
  296.     in_a.s_addr = addr;
  297.     in_m.s_addr = mask;
  298.     xstrncpy(dbg1, inet_ntoa(in_a), 32);
  299.     xstrncpy(dbg2, inet_ntoa(in_m), 32);
  300.     addr = ntohl(addr);
  301.     /*mask = ntohl(mask); */
  302.     debug(53, 3) ("asnAddNet: called for %s/%sn", dbg1, dbg2);
  303.     memset(e, '', sizeof(rtentry));
  304.     store_m_int(addr, e->e_addr);
  305.     store_m_int(mask, e->e_mask);
  306.     rn = rn_lookup(e->e_addr, e->e_mask, AS_tree_head);
  307.     if (rn != NULL) {
  308. asinfo = ((rtentry *) rn)->e_info;
  309. if (intlistFind(asinfo->as_number, as_number)) {
  310.     debug(53, 3) ("asnAddNet: Ignoring repeated network '%s/%d' for AS %dn",
  311. dbg1, bitl, as_number);
  312. } else {
  313.     debug(53, 3) ("asnAddNet: Warning: Found a network with multiple AS numbers!n");
  314.     for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next);
  315.     q = xcalloc(1, sizeof(intlist));
  316.     q->i = as_number;
  317.     *(Tail) = q;
  318.     e->e_info = asinfo;
  319. }
  320.     } else {
  321. q = xcalloc(1, sizeof(intlist));
  322. q->i = as_number;
  323. asinfo = xmalloc(sizeof(asinfo));
  324. asinfo->as_number = q;
  325. rn = rn_addroute(e->e_addr, e->e_mask, AS_tree_head, e->e_nodes);
  326. rn = rn_match(e->e_addr, AS_tree_head);
  327. assert(rn != NULL);
  328. e->e_info = asinfo;
  329.     }
  330.     if (rn == 0) {
  331. xfree(e);
  332. debug(53, 3) ("asnAddNet: Could not add entry.n");
  333. return 0;
  334.     }
  335.     e->e_info = asinfo;
  336.     return 1;
  337. }
  338. static int
  339. destroyRadixNode(struct radix_node *rn, void *w)
  340. {
  341.     struct radix_node_head *rnh = (struct radix_node_head *) w;
  342.     if (rn && !(rn->rn_flags & RNF_ROOT)) {
  343. rtentry *e = (rtentry *) rn;
  344. rn = rn_delete(rn->rn_key, rn->rn_mask, rnh);
  345. if (rn == 0)
  346.     debug(53, 3) ("destroyRadixNode: internal screwupn");
  347. destroyRadixNodeInfo(e->e_info);
  348. xfree(rn);
  349.     }
  350.     return 1;
  351. }
  352. static void
  353. destroyRadixNodeInfo(as_info * e_info)
  354. {
  355.     intlist *prev = NULL;
  356.     intlist *data = e_info->as_number;
  357.     while (data) {
  358. prev = data;
  359. data = data->next;
  360. xfree(prev);
  361.     }
  362.     xfree(data);
  363. }
  364. int
  365. mask_len(int mask)
  366. {
  367.     int len = 32;
  368.     while ((mask & 1) == 0) {
  369. len--;
  370. mask >>= 1;
  371.     }
  372.     return len;
  373. }
  374. static int
  375. printRadixNode(struct radix_node *rn, void *w)
  376. {
  377.     StoreEntry *sentry = w;
  378.     rtentry *e = (rtentry *) rn;
  379.     intlist *q;
  380.     as_info *asinfo;
  381.     struct in_addr addr;
  382.     struct in_addr mask;
  383.     assert(e);
  384.     assert(e->e_info);
  385.     (void) get_m_int(addr.s_addr, e->e_addr);
  386.     (void) get_m_int(mask.s_addr, e->e_mask);
  387.     storeAppendPrintf(sentry, "%15s/%dt",
  388. inet_ntoa(addr), mask_len(ntohl(mask.s_addr)));
  389.     asinfo = e->e_info;
  390.     assert(asinfo->as_number);
  391.     for (q = asinfo->as_number; q; q = q->next)
  392. storeAppendPrintf(sentry, " %d", q->i);
  393.     storeAppendPrintf(sentry, "n");
  394.     return 0;
  395. }