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

📄 dns_util.c.svn-base

📁 域名解析器的实现
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************************
 *		Copyright c 2000 D-Link Corporation		All rights reserved.
 *
 *		This is unpublished proprietary source code of D-Link Corporation
 *
 *		The copyright notice above does not evidence any actual or intended 
 *		publication of such source code.
 ***************************************************************************************
 */
 

/* include files declaration */
#include <l3/inc/phase2.h>
#include <l3/ap/dnsr/h/dns.h>
/*
 * Reinventing the wheel for more portable programs.
 * If you're not using ASCII, you'll have to redefine these.
 */

#ifndef GLUE_ISADIGIT
#define GLUE_ISADIGIT(_c_) \
  ((_c_) >= '0' && (_c_) <= '9')
#endif /* GLUE_ISADIGIT */

#ifndef GLUE_DIGIT
#define GLUE_DIGIT(_c_) \
  ((_c_) - '0')
#endif /* GLUE_DIGIT */

#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 */


/*
 * Notes on address sorting:
 *
 * (1) Using a preference list it's easier to count from the beginning
 *     of the list (best is zero, next best -1, etc) rather than
 *     knowing in advance how many ranks there are.  At the same time,
 *     the randomization stuff is easier to do if we use unsigned
 *     numbers.  So stand the metric number on its head, make larger
 *     numbers denote worse addresses rather than better addresses.
 *
 * (2) Within a catagory, address order should be somewhat randomized,
 *     so that repeated attempts to contact a machine with a down interface
 *     will have some chance of getting through.
 *
 *
 * Reinventing the wheel for more portable programs.
 * If you're not using ASCII, you'll have to redefine these.
 *
 *
 * Default preference list for applications that don't specify one.
 *
 * If DNS_PREFER_LOCAL_ADDRESSES is defined, we give preference to
 * addresses on locally attached subnets.
 */


/*
 * Return an unsigned number indicating how good the address is.
 * The higher the number, the WORSE the address.  The specific values
 * are of nobody's business outside this routine, and may be changed
 * without notice.
 */


/*
 * Returns error code or length of compressed name.  If buffer is
 * NULL, just skip over name, don't convert it into text format.
 */

int dns_decode_name
    (char *buffer,
    int buffer_length,
    unsigned char *name,
    unsigned char *msg,
    unsigned msg_len)
{
    int i, n, result = 0, still_counting = TRUE;
  
    if (name == 0)
        return (int) DNS_ERROR_BAD_ARGS;
  
    do 
    {
        switch ((n = *name) & DNS_COMPRESSION_MASK) 
        {
      
            case DNS_COMPRESSION_POINTER:
           /*
            * Flag bits of count byte say this is a compression pointer
            * relative to the start of the message.  Follow it.
            */
                if (msg == 0)
                    return (int) DNS_ERROR_BAD_NAME;
                if (still_counting)
                    result += 2;
                still_counting = 0;
                name = msg + ((name[0] & ~DNS_COMPRESSION_MASK) << 8) + name[1];
                if (name >= msg + msg_len)
                    return (int) DNS_ERROR_BAD_NAME;
                continue;
      
            case 0:
           /*
            * Flag bits are zero, this is a normal count byte.  Handle conversion
            * of counted string to null-terminated string, using backslash to quote
            * as necessary.
            */
                if (still_counting)
                    result += n + 1;
                if (buffer != 0) 
                {
                    for (i = 1; i <= n; ++i) 
                    {
                        switch (name[i]) 
                        {
                            case '\0':
                                if ((buffer_length -= 4) < 0)
                                    return (int) DNS_ERROR_NAME_TOO_LONG;
                                *buffer++ = '\\'; 
                                *buffer++ = '0'; *buffer++ = '0'; *buffer++ = '0';
                                break;
                            case '\\':
                            case '.':
                                if (--buffer_length < 0)
                                    return (int) DNS_ERROR_NAME_TOO_LONG;
                                *buffer++ = '\\';
                                /* Fall through */
                            default:
                                if (--buffer_length < 0)
                                    return (int) DNS_ERROR_NAME_TOO_LONG;
                                *buffer++ = name[i];
                        } /* switch */
                    } /* for loop */
                } /* if (buffer != 0) */
                
                name += n + 1;
                if (buffer != 0) 
                {
                    if (--buffer_length < 0)
                        return (int) DNS_ERROR_NAME_TOO_LONG;
                    *buffer++ = (char) (*name == 0 ? '\0' : '.');
                }
                continue;
      
            default:
           /*
            * Flag bits of count byte have unknown value, barf.
            */
                return (int) DNS_ERROR_BAD_NAME;
                
        } /* switch ((n = *name) & DNS_COMPRESSION_MASK) */
    } while (n != 0 && (buffer != 0 || still_counting));
  
    return result;
}

/*
 * Returns error code or length of encoded name.  If first argument is
 * 0, doesn't encode, just computes encoded length.
 */

int dns_encode_name
    (unsigned char *buffer,
    unsigned buffer_length,
    char *name)
{
    unsigned char *b = buffer;

    if (name == 0)
        return (int) DNS_ERROR_BAD_ARGS;

    if (buffer_length > DNS_MAX_DOMAIN_NAME)
        buffer_length = DNS_MAX_DOMAIN_NAME;

    do 
    {
        int i = 0;
        while (*name != '\0' && *name != '.') 
        {
            if ((unsigned)(b - buffer) >= buffer_length)
                return (int) DNS_ERROR_NAME_TOO_LONG;
            ++i;
            if (*name == '\\') 
            {
                ++name;
                if (GLUE_ISADIGIT(name[0])) 
                {
                    if (!GLUE_ISADIGIT(name[1]) || !GLUE_ISADIGIT(name[2]))
                        return (int) DNS_ERROR_BAD_NAME;
                    if (buffer != 0)
                        b[i] = (unsigned char)
                                (GLUE_DIGIT(name[0]) * 100 +
                                GLUE_DIGIT(name[1]) * 10 +
                                GLUE_DIGIT(name[2]));
                    name += 3;
                    continue;
                }
            }
            if (buffer != 0)
                b[i] = *name;
            ++name;
        } /* while */
        
        if (i >= DNS_MAX_DOMAIN_LABEL)
            return (int) DNS_ERROR_LABEL_TOO_LONG;
        if (buffer != 0)
            *b = (unsigned char) i;
        b += i + 1;
    } while (*name++ != '\0');

    if ((unsigned)(b - buffer) >= buffer_length)
        return (int) DNS_ERROR_NAME_TOO_LONG;
    if (buffer != 0)
        *b = 0;
    return (int) (b - buffer + 1);
}


/*
 * Returns error code.
 */

enum dns_error dns_decode_header
    (unsigned char *msg,
    unsigned msg_len,
    struct dns_header *hdr)
{
    UI32_T flags;

    if (msg_len < DNS_HDR_LENGTH)
        return DNS_ERROR_BAD_ARGS;

    flags = dns_decode_bits32(msg + DNS_HDR_FLAGS);

    hdr->qdcount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_QDCOUNT);
    hdr->ancount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_ANCOUNT);
    hdr->nscount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_NSCOUNT);
    hdr->arcount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_ARCOUNT);

    hdr->id    = (UI16_T ) DNS_LDB(flags, DNS_HDR_ID);
    hdr->resp  = (unsigned) DNS_LDB(flags, DNS_HDR_RESP);
    hdr->op    = (unsigned) DNS_LDB(flags, DNS_HDR_OP);
    hdr->aa    = (unsigned) DNS_LDB(flags, DNS_HDR_AA);
    hdr->tc    = (unsigned) DNS_LDB(flags, DNS_HDR_TC);
    hdr->rd    = (unsigned) DNS_LDB(flags, DNS_HDR_RD);
    hdr->ra    = (unsigned) DNS_LDB(flags, DNS_HDR_RA);
    hdr->rcode = (unsigned) DNS_LDB(flags, DNS_HDR_RCODE);

    #if 0
    DBG_L3_Printf("dns_decode_header qdcount = %d\n",hdr->qdcount);
    DBG_L3_Printf("dns_decode_header ancount = %d\n",hdr->ancount); 
    DBG_L3_Printf("dns_decode_header nscount = %d\n",hdr->nscount);
    DBG_L3_Printf("dns_decode_header arcount = %d\n",hdr->arcount);
    DBG_L3_Printf("dns_decode_header id = %d\n",hdr->id);
    DBG_L3_Printf("dns_decode_header resp = %d\n",hdr->resp);
    DBG_L3_Printf("dns_decode_header op = %d\n",hdr->op);
    DBG_L3_Printf("dns_decode_header aa = %d\n",hdr->aa);
    DBG_L3_Printf("dns_decode_header tc = %d\n",hdr->tc);
    DBG_L3_Printf("dns_decode_header rd = %d\n",hdr->rd);
    DBG_L3_Printf("dns_decode_header ra = %d\n",hdr->ra);  
    DBG_L3_Printf("dns_decode_header rcode = %d\n",hdr->rcode);
    #endif
    
    return DNS_ERROR_OK;
}

/*
 * Check a DNS response message for legality.
 *
 * Checks message headers.
 *
 * Checks CNAMEs in Answer section to make sure they form a valid path
 * from the QNAME to the name(s) of any other RRs in the Answer section.
 *
 * I can't think of any way that the non-CNAME RRs in the Answer
 * could legitimately have different names from each other, but
 * I'm not going to put such a check into this code until I have
 * time to double check this in the RFCs.
 *
 * Returns status code.
 */

enum dns_error dns_bless_message  
  (unsigned char *msg,          /* Network message ("packet") */
   unsigned msg_len,            /* Length of message */
   struct dns_header *hdr,      /* DNS header */
   struct dns_rr rrs[],         /* RRs from message */
   unsigned n_rrs)              /* Length of rrs[] */
{
    int i, n, matched;
    enum dns_error err;           
    unsigned char *cqname;


    if (msg == 0 || msg_len <= 0 || hdr == 0 || rrs == 0)
        return DNS_ERROR_BAD_ARGS;
                      
   /*
    * Check values in the received header.
    *
    * The message must be a response.
    * The only opcode we support is QUERY.
    * The server must claim to support recursion.
    * The server may not claim to be authoritative for all classes.
    */
    if (!hdr->resp || hdr->op != DNS_OPCODE_QUERY || !hdr->rd ||
        (hdr->aa && rrs[0].class == DNS_C_ANY))
        return DNS_ERROR_BAD_PROTOCOL;
    if (hdr->tc)
        return DNS_ERROR_TRUNCATED;
    if (!hdr->ra)
        return DNS_ERROR_NO_RECURSION;    

⌨️ 快捷键说明

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