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

📄 dns_util.c.svn-base

📁 域名解析器的实现
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
    if ((err = dns_decode_rcode(hdr)) != DNS_ERROR_OK)
        return err;

   /*
    * Check the Question section.
    *
    * Make sure the name server claims to be answering the question we asked.
    */
    if ((n = hdr->qdcount) > (int) n_rrs)
        n = n_rrs;
    for (i = 0; i < n; ++i) 
    {
        if (rrs[0].class != rrs[i].class || rrs[0].type != rrs[i].type ||
            dns_namcmp(rrs[0].name, 0, 0, rrs[i].name, msg, msg_len) != 0)
            return DNS_ERROR_BAD_PROTOCOL;
    }

   /*
    * Check the Answer section.
    *
    * Unless CNAME RRs are a legitimate answer to the query, check any
    * leading CNAME RRs to be sure they form a valid chain from the
    * QNAME to the name of the first non-CNAME RR.  Check the names of
    * any remaining RRs in the answer section to be sure that they
    * match the canonnicalized QNAME.  Also check the types and classes
    * of all the RRs in the Answer section.  If we find a valid chain
    * of CNAMEs but no other Answer RRs, it's the same as if we'd gotten
    * a completely empty answer section.
    */
    cqname = rrs[0].name;
    if ((n = hdr->qdcount + hdr->ancount) > (int) n_rrs)
        n = n_rrs;
    matched = FALSE;
    for (i = hdr->qdcount; i < n; ++i) 
    {
        if (!dns_c_match(rrs[0].class, rrs[i].class) ||
            dns_namcmp(cqname, (cqname == rrs[0].name ? 0 : msg),
            msg_len, rrs[i].name, msg, msg_len) != 0) 
        {
            return DNS_ERROR_BAD_PROTOCOL;
        } 
        else if (dns_t_match(rrs[0].type, rrs[i].type)) 
        {
            matched = TRUE;
        } 
        else if (matched || rrs[i].type != DNS_T_CNAME) 
        {
            return DNS_ERROR_BAD_PROTOCOL;
        } 
        else 
        {
            cqname = rrs[i].rdata;
        }
    }
    
    if (!matched)
        return DNS_ERROR_NO_RRS;


   /*
    * No sanity checks for Authority or Additional sections at present.
    */

   /*
    * If we made it here, the message is ok, so give it our blessing.
    */
    return DNS_ERROR_OK;
}


/*
 * Returns error code or number of RRs decoded.
 */

int dns_decode_rrs
    (unsigned char *msg,          /* Network message ("packet") */
    unsigned msg_len,            /* Length of message */
    struct dns_header *hdr,      /* DNS header */
    struct dns_rr rr[],          /* Where to put parsed RRs */
    unsigned nrrs,               /* How many there are */    
    UI32_T now)                /* Current time */    
{
    UI32_T n = hdr->qdcount + hdr->ancount + hdr->nscount + hdr->arcount;
    UI32_T i = 0;
    unsigned char *p = msg + DNS_HDR_LENGTH;
    int name_length;
    UI16_T  rdcount;

    while (i < n && i < nrrs) 
    {
        struct dns_rr *r = rr + (int) (i);
        
        if ((name_length = dns_decode_name(0, 0, p, msg, msg_len)) < 0)
            return name_length;
                    
        if (r != 0)
            r->name = p;
        p += name_length;

        if (r != 0)
            r->type = (UI16_T )dns_decode_bits16(p);
        p += 2;

        if (r != 0)
            r->class = (UI16_T )dns_decode_bits16(p);
        p += 2;

        if (i < hdr->qdcount) 
        {
            if (r != 0) 
            {
                r->ttl = 0;
                r->rdcount = 0;
                r->rdata = 0;
            }
        }
        else 
        {
            if (r != 0)
                r->ttl = dns_decode_bits32(p);
            p += 4;

            rdcount = (UI16_T )dns_decode_bits16(p);
            if (r != 0)
                r->rdcount = rdcount;
            p += 2;

            if (r != 0)
                r->rdata = p;
            p += rdcount;

        }

        if (r != 0) 
        {
            r->next = 0;
            r->birthdate = now;            
            r->negative = FALSE;
            r->answer = i < (unsigned)hdr->qdcount + hdr->ancount;
            r->authoritative = r->answer && hdr->aa && hdr->qdcount != 0
                && dns_namcmp(msg + DNS_HDR_LENGTH, msg, msg_len, r->name, msg, msg_len) == 0;
            r->errcode = DNS_ERROR_OK;     
        }

        if (p > msg + msg_len)
            return (int) i;
        ++i;
    } /* while */
    
    return (i);
}

enum dns_error dns_decode_rcode
    (struct dns_header *hdr)
{
    switch (hdr->rcode) 
    {
        case DNS_RCODE_OK:
            return DNS_ERROR_OK;
        case DNS_RCODE_FORMAT:
            return DNS_ERROR_FORMAT;
        case DNS_RCODE_SERVER:
            return DNS_ERROR_SERVER_FAILURE;
        case DNS_RCODE_NAME:
            return DNS_ERROR_NONEXISTANT_NAME;
        case DNS_RCODE_NIY:
            return DNS_ERROR_NIY;
        case DNS_RCODE_REFUSED:
            return DNS_ERROR_REFUSED;
        default:
            return DNS_ERROR_BAD_PROTOCOL;
    }
}

/*
 * Compare two DNS names (internal format).
 *
 * Returns an integer value.  NB: The value returned is -not- like the
 * value returned by the normal C library strcmp() function, because
 * dns_namcmp() has to be able to return error codes as well.  Sorry.
 *
 * Return value will either be an error code (DNS_ERROR_xxx value) or one
 * of the following:
 *    DNS_NAMCMP_LESS:    first argument is "less" than second argument
 *    DNS_NAMCMP_EQUAL:   first argument is "equal" to second argument
 *    DNS_NAMCMP_GREATER: first argument is "greater" than second argument.
 * These correspond to the three return cases of the C strcmp() routine.
 *
 * For the peace of mind of application authors who only want to
 * compare two names for equality, the numeric value of
 * DNS_NAMCMP_EQUAL is hereby and henceforth defined to be zero.
 *
 * The msg and msg_len parameters for either name are ignored if that
 * name doesn't contain any compression pointers.
 */

int dns_namcmp
    (unsigned char *name1,
    unsigned char *msg1,
    unsigned msg1_len,
    unsigned char *name2,
    unsigned char *msg2,
    unsigned msg2_len)
{
    if (name1 == 0 || name2 == 0)
        return (int) DNS_ERROR_BAD_ARGS;

    for (;;) 
    {
        unsigned i = *name1, j = *name2;

       /*
        * Step one: find the length of the next label in each name.
        * This may involve following multiple compression pointers.
        */

        while ((i & DNS_COMPRESSION_MASK) != 0) 
        {
            if ((i & DNS_COMPRESSION_MASK) != DNS_COMPRESSION_MASK)
                return (int) DNS_ERROR_BAD_NAME;
            if (msg1 == 0)
                return (int) DNS_ERROR_BAD_ARGS;
            name1 = msg1 + ((name1[0] & ~DNS_COMPRESSION_MASK) << 8) + name1[1];
            if (name1 >= msg1 + msg1_len)
                return (int) DNS_ERROR_BAD_NAME;
            i = *name1;
        }

        while ((j & DNS_COMPRESSION_MASK) != 0) 
        {
            if ((j & DNS_COMPRESSION_MASK) != DNS_COMPRESSION_MASK)
                return (int) DNS_ERROR_BAD_NAME;
            if (msg2 == 0)
                return (int) DNS_ERROR_BAD_ARGS;
            name2 = msg2 + ((name2[0] & ~DNS_COMPRESSION_MASK) << 8) + name2[1];
            if (name2 >= msg2 + msg2_len)
                return (int) DNS_ERROR_BAD_NAME;
            j = *name2;
        }

       /*
        * Step two: compare the lengths, returning the comparision if not equal.
        * This is also where we catch identical names.
        */

        if (i != j)
            return (i < j ? DNS_NAMCMP_LESS : DNS_NAMCMP_GREATER);
        if (i == 0)
            return DNS_NAMCMP_EQUAL;

       /*
        * Step three: compare the labels, converting case as necessary.
        */

        for (j = 1; j <= i; ++j) 
        {
            unsigned c1 = name1[j], c2 = name2[j];
            if (GLUE_ISUPPER(c1))
                c1 = GLUE_LOWER(c1);
            if (GLUE_ISUPPER(c2))
                c2 = GLUE_LOWER(c2);
            if (c1 != c2)
                return (c1 < c2 ? DNS_NAMCMP_LESS : DNS_NAMCMP_GREATER);
        }

       /*
        * Step four: advance pointers, loop for next labels.
        */

        name1 += i + 1;
        name2 += i + 1;
    } /* for loop */

   /*
    * Never get here.
    */
}


/*
 * Type and class matching.
 */

int dns_t_match
    (unsigned wild,
    unsigned tame)
{
    return (wild == tame || wild == DNS_T_ANY ||
            (wild == DNS_T_MAILA && tame == DNS_T_MX) ||
            (wild == DNS_T_MAILB &&
            (tame == DNS_T_MB || tame == DNS_T_MR ||
            tame == DNS_T_MG || tame == DNS_T_MINFO)));
}

int dns_c_match
    (unsigned wild,
    unsigned tame)
{
    return (wild == tame || wild == DNS_C_ANY);
}

/*
 * TTL comparision.
 *
 * We check for TTL == 0 explicitly because dns_gc_mark() uses this to
 * indicate a dead RR.  This allows calls to dns_gc_sweep() to be put
 * off as long as necessary without any cost to the application other
 * than increased memory usage.
 */

int dns_ttl_valid
    (struct dns_rr *r,
    UI32_T now)
{
#if 0    
    return (!r->expired && r->birthdate + r->ttl * 1000 - now < 0x80000000L);
#else
    return (!r->expired && r->birthdate + r->ttl * 1000 - now < MAX_DNS_CACHE_TTL*1000);
#endif    
}

⌨️ 快捷键说明

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