📄 dns_relay_cache.c
字号:
else { /* in the middle of the list */ ce->c_prev->c_next = ce->c_next; ce->c_next->c_prev = ce->c_prev; cache_entry_clear(head, ce->c_next, match, data); free_cache_element(ce); return; } } cache_entry_clear(head, ce->c_next, match, data);} /* end cache_entry_clear() *//* * get_cache_element() * * this routine will loop through the array of cache entries and return * a pointer to the first unsed one. * * return: pointer to an element, or * NULL to indicate none available. */static Cache_t *get_cache_element(){ int i; for ( i = 0; i < DNS_CACHE_POOLSIZE; i++ ) { if ( !cache_list[i].used ) { cache_list[i].used = 1; ce_inuse++; return &cache_list[i]; } } return NULL;} /* end get_cache_element() *//* * dns_cache_insert() * * this routine will attempt to insert an entry into the cache. the routine * will verify some aspects of the reply. note that the time out, tout, is * used as a make time for this cached element. * * return: 0 to indicate successfully cached, or * -1 indicates an error. */intdns_cache_insert(DnsQuestion *q, void *reply, unsigned long tout, int rsize){ Cache_t *entry; /* see if this entry is already cached. if so, just return */ if ((entry = relay_cache_search(q)) != NULL) return 0; if ( rsize > DNSMAX ) { TRACE(TRACE_WARN, "DNS relay cache error! DNS reply to be cached larger than 512!"); return -1; } if(tout == 0) return 0;// With TTL=0, it's meant for temproary transactions, so don't cache! /* get an entry for the new reply, if we can't get one, drop it */ if ((entry = get_relay_cache_element()) == NULL) return 0; entry->question.q_type = q->q_type; entry->question.q_class = q->q_class; strcpy(entry->question.q_name, q->q_name); memcpy(entry->dnsreply, reply, rsize); entry->rsize = rsize; entry->created = timer_secs(); entry->timeout = tout; insert_cache_entry(entry); return 0;} /* end dns_cache_insert() *//* * get_relay_cache_element() * * this routine will attempt to acquire a new cache element. if none are * initially available, we attempt to time out entries, then we also clear * any entries that haven't been hit or hit recently. * * return: pointer to a cache element or * NULL if none are available. */static Cache_t *get_relay_cache_element(){ Cache_t *cache; /* * attempt to find an unused element. if there are none, then attempt to * time out entries and try again. if there are still none, try clearing * any seldom used entries or entries that haven't been used for some * time. */ if ((cache = get_cache_element()) == NULL) { dns_relay_cache_entry_timeout(); if ((cache = get_cache_element()) == NULL) dns_relay_cache_nohit_entry_clear(DNS_RELAY_CACHE_NOHIT_PERIOD); else return cache; return get_cache_element(); } return cache;} /* end get_relay_cache_element() *//* * insert_cache_entry() * * this routine will just insert the cache entry into our cache. no memory * is allocated and the structure is expected to be set up. */static voidinsert_cache_entry(Cache_t *entry){#ifndef DNS_RELAY_LL_CACHE unsigned long index; Cache_t *next; char tmp[256+1]; lowercase_copy(tmp, entry->question.q_name); index = cache_string_hash((const unsigned char *)tmp); if ( relay_cache[index] == NULL ) relay_cache[index] = entry; else { next = relay_cache[index]; while ( next->c_next ) next = next->c_next; next->c_next = entry; entry->c_prev = next; }#else Cache_t *current; if ( cache_head == NULL ) cache_head = entry; else { current = cache_head; while ( current->c_next ) current = current->c_next; current->c_next = entry; entry->c_prev = current; }#endif} /* end insert_cache_entry() *//* * dns_cache_search() * * this routine will search the cache for a match to the question. if * found then the entire saved dns replay is copied to dnsbuffer. note * that it is assumed there is enough space. * * if a matching entry is located we increment the number of hits for that * entry and update a time for last access of that entry. this information * is used when elimating entries when the cache is full. * * return: number of bytes in the copied DNS reply, or * 0 which indicates no cache hit. */intdns_cache_search(DnsQuestion *q, void *dnsbuffer){ Cache_t *entry; unsigned char *buffer = (unsigned char *)dnsbuffer; if ((entry = relay_cache_search(q)) != NULL) { memcpy(buffer + 2, entry->dnsreply + 2, (entry->rsize - 2)); entry->hits++; entry->lasthit = timer_secs(); cache_hit++; return entry->rsize; } cache_miss++; return 0; } /* end dns_cache_search() */ /* * relay_cache_search() * * this routine will attempt to locate a cache entry bases on the information * of the DNS question. the routine loops through each entry to compare the * passed in question with the question that is part of the cache entry. if * * return: a pointer to the matching entry if found, or * NULL if no match. */static Cache_t *relay_cache_search(DnsQuestion *q){#ifndef DNS_RELAY_LL_CACHE unsigned long index; Cache_t *entry; char tmp[256+1]; /* hash the domain name in the question */ lowercase_copy(tmp, q->q_name); index = cache_string_hash((const unsigned char *)tmp); /* if the hashed bucket is empty, then there's no match */ if ((entry = relay_cache[index]) == NULL) return NULL; /* * the bucket is a list, we loop through each element and * compare the question to see if we have a match. */ while ( entry != NULL ) { if ( dns_question_compare(q, &entry->question) ) { U32 now=timer_secs(); if(timeout_match(entry, &now) == FALSE) return entry; else break; } entry = entry->c_next; } return NULL; /* if we get here there wasn't a match */#else Cache_t *entry = cache_head; /* * the cache is a list, we loop through all the entries until * either we find a match, or we run out of entries. */ while ( entry != NULL ) { if ( dns_question_compare(q, &entry->question) ) return entry; entry = entry->c_next; } return NULL; /* no match */#endif} /* end relay_cache_search() */#ifndef DNS_RELAY_LL_CACHE/* * cache_string_hash() * * this is the hash routine for the cache. note that it is pretty simply. * that's on purpose, this routine appears to have reasonable distribution * compared with more complex functions, but there's less computation. note * that its likely you can find a better hash function. */static unsigned long cache_string_hash(const unsigned char *str){ unsigned long h = 0; int i; for ( i = 0; *str; i++ ) h += *str++ + i; return h % DNS_RELAY_CACHE;} /* end cache_string_hash() */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -