⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dns_cash.c.svn-base

📁 域名解析器的实现
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* include files declaration */
#include <l3/inc/phase2.h>
#include <l3/ap/dnsr/h/dns.h>
#include <l3/ap/dnsr/h/dnsr_if.h>

/*-----------------------------------------------------------------------
 * Local Variables
 *-----------------------------------------------------------------------
 */  
 
#define DNS_CACHE_SIZE          11
 
/* Global variables */
static UI32_T dns_cache_count;
static I32_T  dns_gc_mark_time;
static I32_T  dns_gc_sweep_time;

static struct dns_rr *dns_cache[DNS_CACHE_SIZE];

/* external variables declaration */

/* external functions declaration */


/*-----------------------------------------------------------------------
 * Functions
 *-----------------------------------------------------------------------
 */  
 
/*
 * This entire module is only included both DNS and its cache are installed.
 */
/*
 * Reinventing the wheel for more portable programs.
 * If you're not using ASCII, you'll have to redefine these.
 */

#ifndef GLUE_ISUPPER
#define GLUE_ISUPPER(_c_) \
  ((_c_) >= 'A' && (_c_) <= 'Z')
#endif /* GLUE_ISUPPER */

#ifndef GLUE_LOWER
#define GLUE_LOWER(_c_) \
  ((_c_) + 'a' - 'A')
#endif /* GLUE_LOWER */



/*
 * Compute hash value from DNS name.  Hash is case-insensitive.
 * Assumes there are no indirection pointers in tne name.
 *
 * As a compile-time optimization, if DNS_CACHE_SIZE == 1, we
 * return 0 immediately and the hash table degenerates to an unsorted
 * linked list.  This might be appropriate if your application is
 * tight on memory and doesn't need a big cache.
 */
 
#if DNS_CACHE_SIZE == 1

#define dns_hash(_ignored_)     (0)

#else /* DNS_CACHE_SIZE == 1 */

static unsigned dns_hash(unsigned char *name)
{
    unsigned result = 0;
    int i, n;

#if DNSR_DEBUG
        char buffer[DNS_MAX_DOMAIN_NAME];
        buffer[0] = 0;
        if ((i = dns_decode_name(buffer, sizeof(buffer), name, 0, 0)) < 0)
            DBG_L3_Printf("dns_hash(): error %d decoding name\n", i);
#endif /* DEBUG */

    while ((n = *name) != 0) 
    {
        result += n;
        for (i = 1; i <= n; ++i)
            result += (GLUE_ISUPPER(name[i]) ? GLUE_LOWER(name[i]) : name[i]);
        name += n + 1;
    }

#if DNSR_DEBUG
    DBG_L3_Printf("dns_hash(%s) = %d\n", buffer, result % DNS_CACHE_SIZE);
#endif /* DEBUG */

    return result % DNS_CACHE_SIZE;
}

#endif /* DNS_CACHE_SIZE == 1 */

/* 
 * For "well-known" RR types the RFCs require us to handle compression
 * pointers within the RDATA portion of an RR.  We have to get rid of
 * the compression pointers when caching.
 */

/*
 * Return length of uncompressed encoded name, or zero to indicate an error.
 * If destination is 0, just computes uncompressed length without copying.
 */

static int dns_uncompress_name
  (unsigned char *destination,
   unsigned char *name,
   unsigned char *msg,
   unsigned msg_len)
{
    unsigned result = 0;

    if (name == 0)
        return 0;

    while (*name != 0) 
    {
        switch (*name & DNS_COMPRESSION_MASK) 
        {
            case DNS_COMPRESSION_POINTER:
                if (msg == 0)
                    return 0;
                name = msg + ((name[0] & ~DNS_COMPRESSION_MASK) << 8) + name[1];
                if (name >= msg + msg_len)
                    return 0;
                continue;

            case 0:
                if (destination != 0) 
                {
                    memcpy((char *) destination, (char *) name, (int) (*name + 1));
                    destination += *name + 1;
                }
                result += *name + 1;
                name += *name + 1;
                continue;

            default:
                return 0;
        } /* switch */
    } /* while */

    if (destination != 0)
        *destination = 0;

    return result + 1;
}

/*
 * Uncompress the RDATA portion of an RR.  If buffer is 0, no
 * copying takes place.  Returns status code, updates *rdcount.
 */

static enum dns_error dns_uncompress_rdata
    (unsigned char *buffer,
    struct dns_rr *rr,
    unsigned char *msg,
    unsigned msg_len,
    unsigned *rdcount)
{
    unsigned char *rdata = rr->rdata;
    char *format = 0;
    int n;

    if (rr == 0 || msg == 0 || rdcount == 0)
        return DNS_ERROR_BAD_ARGS;

   /*
    * At present all the RRs that need RDATA expansion consist of one
    * or more DNS names combined with some small fixed number of data
    * bytes.  The easiest way to handle this without massive code
    * duplication is a format-driven loop.  None of the RR types that
    * need expansion are class-specific, which simplifies things.
    */

    switch (rr->type) 
    {
        case DNS_T_SOA:                      /* Two domain names and five 32-bit numbers */
            format = "ddhhhhhhhhhh";
            break;
        case DNS_T_MX:                       /* One 16-bit number and one domain name */
            format = "hd";
            break;
        case DNS_T_CNAME:                    /* One domain name */
        case DNS_T_PTR:
        case DNS_T_NS:
        case DNS_T_MB:
        case DNS_T_MG:
        case DNS_T_MR:
            format = "d";
            break;
        case DNS_T_MINFO:                    /* Two domain names */
            format = "dd";
            break;
    } /* switch */

   /*
    * Default case, no expansion needed, old rdcount ok.
    */

    if (format == 0) 
    {
        if (buffer != 0)
            memcpy(buffer, rr->rdata, rr->rdcount);
        *rdcount = rr->rdcount;
        return DNS_ERROR_OK;
    }

   /*
    * Expand according to format.
    */

    *rdcount = 0;

    while (*format != '\0') 
    {

        switch (*format++) 
        {

            case 'h':                          /* Two bytes */
                if (buffer != 0) 
                {
                    *buffer++ = rdata[0];
                    *buffer++ = rdata[1];
                }
                rdata += 2;
                *rdcount += 2;
                continue;

            case 'd':                          /* A domain name */
                if ((n = dns_uncompress_name(buffer, rdata, msg, msg_len)) == 0)
                    return DNS_ERROR_BAD_NAME;
                *rdcount += n;
                if (buffer != 0)
                    buffer += n;
                if ((n = dns_decode_name(0, 0, rdata, msg, msg_len)) < 0)
                    return n;
                rdata += n;
                continue;

            default:                           /* Anything else */
                return DNS_ERROR_IMPOSSIBLE;
        } /* switch */
    } /* while */

    return DNS_ERROR_OK;
}

/*------------------------------------------------------------------------
 * dns_lookup()
 * Purpose: Routine to look up cache entries.
 *          
 * Parameters:
 *    Input:
 *    Output:
 * returns :
 *------------------------------------------------------------------------
 */                       
 
int dns_lookup
    (unsigned char *qname,        /* Query name */
     unsigned qclass,             /* Query type */
     unsigned qtype,              /* Query class */
     struct dns_rr *rrs[],        /* Where to put results */
     int max_rrs)                 /* Length of rrs[] */
{
    struct dns_rr *r;
    int n_rrs = 0;

    if (qname == 0 || rrs == 0)
        return (int) DNS_ERROR_BAD_ARGS;
    
   /*
    * Come here when we've found a CNAME and have to restart the search.
    */
    restart_cname:
  
   /*
    * Look in the appropriate bucket.
    */
    for (r = dns_cache[dns_hash(qname)]; r != 0; r = r->next) 
    {
        int t_matched = dns_t_match(qtype, r->type);
    
       /*
        * If this RR isn't relevant to our search or has timed out, keep looking.
        */
        if (!dns_ttl_valid(r, GLUE_NOW()) || !dns_c_match(qclass, r->class) ||
            (r->negative ? (!t_matched): (!t_matched && r->type != DNS_T_CNAME)) ||
            dns_namcmp(qname, 0, 0, r->name, 0, 0) != 0)
            continue;
    
       /*
        * If we found a negative cache entry, return its error code.
        */
        if (r->negative)
            return r->errcode;
    
       /*
        * Normal RR, add it to list if there's room.
        */
        if (n_rrs >= max_rrs)
            return (int) DNS_ERROR_TRUNCATED;
        rrs[n_rrs++] = r;
    
       /*
        * If we found a CNAME instead of a match, restart the search with
        * this RR's RDATA as the new QNAME.  It's not legal for any other
        * RRs to exist with the same name and class as a CNAME RR, so
        * it's ok for us to just break out of the current search.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -