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

📄 dns.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
*                                                                            
*    This function takes a domain name and converts it to a format a DNS     
*    server expects.                                                         
*                                                                            
* INPUTS                                                                     
*                                                                            
*    dst                       The converted name.                           
*    src                       The original name.                            
*                                                                            
* OUTPUTS                                                                    
*                                                                            
*    INT:                                                                    
*      > 0                       The size of the new name.                   
*      NU_INVALID_PARM                                                       
*      < 0                       Failure                                     
*                                                                            
******************************************************************************/
INT DNS_Pack_Domain_Name (CHAR *dst, CHAR *src)
{
    CHAR        *p;
    CHAR        *original_dest;
    INT         n;

    /* If this is a null string return an error. */
    if (!*src)
        return (NU_INVALID_PARM);

    p = original_dest = dst;

    do
    {
        /* Move past the byte where the length will be saved. */
        dst++;

        /* Assume all labels have been copied until proven otherwise. */
        *p = 0;

        /* Copy the label. */
        for ( n = 0;
              *src && (*src != '.') && (n <= DNS_MAX_LABEL_SIZE);
              *dst++ = *src++, ++n );

        /* Check to see if the label exceded the maximum length. */
        if ( n > DNS_MAX_LABEL_SIZE)
            return (NU_INVALID_LABEL);

        /* Store the length of the label. */
        *p = (UINT8)(dst - p - 1);

        /* Point to where the next length value will be stored. */
        p = dst;

        if (*src)
            src++;

    } while (*src);

    /* The end of the name is marked with a 0 length label. */
    *p = 0;

    dst++;

    return (INT)(dst - original_dest);

} /* DNS_Pack_Domain_Name */

/****************************************************************************
* FUNCTION                                                                   
*                                                                            
*   DNS_Unpack_Domain_Name                                                   
*                                                                            
* DESCRIPTION                                                                
*                                                                            
*    This function packed name and converts it to a character string.        
*                                                                            
* INPUTS                                                                     
*                                                                            
*    dst                       The new name.                                 
*    src                       The original name.                            
*    buf_begin                 Pointer to start od response packet.          
*                                                                            
* OUTPUTS                                                                    
*                                                                            
*    INT                       The size of the new name.                     
*                                                                            
******************************************************************************/
INT DNS_Unpack_Domain_Name(CHAR *dst, CHAR *src, CHAR *buf_begin)
{
    INT16           size;
    INT             i, retval = 0;
    CHAR            *savesrc;

    savesrc = src;

    /* The end of the name is marked by a 0 length label. */
    while (*src)
    {
        /* Get the size of the label. */
        size = *src;

        /* Check to see if this is a pointer instead of a label size. */
        while ((size & 0xC0) == 0xC0)
        {
            /* If we have not encountered a pointer yet compute the size of the
               name so far. */
            if (!retval)
            {
                retval = (INT)(src - savesrc + 2);
            }

            src++;

            /* Point to the new location. */
            src = &buf_begin[(size & 0x3f) * 256 + *src];
            size = *src;
        }

        /* Move the pointer past the label size. */
        src++;

        /* Copy the label. */
        for (i = 0; i < (size & 0x3f); i++)
        {
            *dst++ = *src++;
        }

        /* Insert the period between labels. */
        *dst++ = '.';
    }

    /* Add the terminator. */
    *(--dst) = 0;

    /* Account for the terminator on src. */
    src++;

    /* If the name included a pointer then the return value has already been
       computed. */
    if (!retval)
    {
        retval = (INT)(src - savesrc);
    }

    return (retval);
}  /* DNS_Unpack_Domain_Name */

/****************************************************************************
* FUNCTION                                                                   
*                                                                            
*   DNS_Extract_Data                                                         
*                                                                            
* DESCRIPTION                                                                
*                                                                            
*    This function takes a DNS response and extracts either an IP address or 
*    a domain name, which ever the case may be.                              
*                                                                            
* INPUTS                                                                     
*                                                                            
*    pkt                       A pointer to the DNS response.                
*    data                      Put the address or name here.                 
*    ttl                       Put the Time To Live here.                    
*    type                      The type of query.                            
*                                                                            
* OUTPUTS                                                                    
*                                                                            
*    NU_SUCCESS                Indicates success.                            
*    NU_DNS_ERROR                                                            
*    NU_MEM_ALLOC                                                            
*     < 0                      Indicates failure.                            
*                                                                            
******************************************************************************/
STATUS DNS_Extract_Data (DNS_PKT_HEADER *pkt, CHAR *data, UNSIGNED *ttl,
                         INT type)
{
    DNS_RR          *rr_ptr;
    INT             name_size, n_answers, rcode;
    UINT16          length;
    CHAR            *p_ptr, *name;
    CHAR            answer_received = 0;

    /* Get the number of answers in this message. */
    n_answers = GET16(pkt, DNS_ANCOUNT_OFFSET);

    /* Extract the return code. */
    rcode = DNS_RCODE_MASK & GET16(pkt, DNS_FLAGS_OFFSET);

    /* Was an error returned? */
    if (rcode)
        return (NU_DNS_ERROR);

    /* If there is at least one answer and this is a response, process it. */
    if ((n_answers > 0) && (GET16(pkt, DNS_FLAGS_OFFSET) & DNS_QR))
    {
        /* Point to where the question starts. */
        p_ptr = (CHAR *)(pkt + 1);

        /* Allocate a block of memory to put the name in. */
        if (NU_Allocate_Memory (&System_Memory, (VOID **)&name,
                                DNS_MAX_NAME_SIZE,
                                NU_NO_SUSPEND) != NU_SUCCESS)
        {
            return (NU_NO_MEMORY);
        }

        /* Extract the name. */
        name_size = DNS_Unpack_Domain_Name (name, p_ptr, (CHAR *)pkt);

        /*  Move the pointer past the name QTYPE and QCLASS to point at the
            answer section of the response. */
        p_ptr += name_size + 4;

        /*
        *  At this point, there may be several answers.  We will take the first
        *  one which has an IP number.  There may be other types of answers that
        *  we want to support later.
        */
        while ((n_answers--) > 0)
        {
            /* Extract the name from the answer. */
            name_size = DNS_Unpack_Domain_Name (name, p_ptr, (CHAR *)pkt);

            /* Move the pointer past the name. */
            p_ptr += name_size;

            /* Point to the resource record. */
            rr_ptr = (DNS_RR *)p_ptr;

            /* Verify the type and class. */
            if ((GET16(p_ptr, DNS_TYPE_OFFSET) == type) &&
                (GET16(p_ptr, DNS_CLASS_OFFSET) == DNS_CLASS_IN))
            {
                switch (type)
                {
                    case DNS_TYPE_A :

                        /* The answer has the correct type and class. Copy
                           the IP addr. */
                        GET_STRING (rr_ptr, DNS_RDATA_OFFSET, data,  4);
                        break;

                    case DNS_TYPE_PTR :

                        /* The answer has the correct type and class. Get the name. */
                        DNS_Unpack_Domain_Name (data, rr_ptr->dns_rdata,
                                                (CHAR *)pkt);
                        break;

                    default :
                        return -1;
                }

                /* Get the time to live for this RR. */
                *ttl = GET32(rr_ptr, DNS_TTL_OFFSET);

                /* Indicate an answer was found. */
                answer_received = 1;

                break;
            }

            /* Copy the length of this answer. */
            length = GET16(rr_ptr, DNS_RDLENGTH_OFFSET);

            /* Point to the next answer, if any.  The rdlength field is the
               length of the data section of the RR.  Add 10 for the sizes of
               the type, class, ttl, and rdlength.
            */
            p_ptr += (10 + length);
        }
            NU_Deallocate_Memory(name);
    }


    if (answer_received)
        return (NU_SUCCESS);
    else
        return (-1);

}  /* DNS_Extract_Data */

/****************************************************************************
* FUNCTION                                                                   
*                                                                            
*   DNS_Add_Host                                                             
*                                                                            
* DESCRIPTION                                                                
*                                                                            
*    This function adds a new host to the "hosts file".                      
*    A block of memory is alocated each time we want to add a new host.      
*    This can be wasteful of memory because Nucleus PLUS has a minimum       
*    allocation size of 50 bytes.  The alternative would have been to        
*    allocate enough memory for several of these at one time.  The problem   
*    with that is the RFC defines the maximum size of a name at 255 bytes.   
*    We would have to assume that a maximum sized name would have to be      
*    stored and allocate memory accordingly.  Since most names are nowhere   
*    close to 255 bytes this method would have been even more wasteful.      
*                                                                            
* INPUTS                                                                     
*                                                                            
*    name                      The name of the host to add.                  
*    ip_addr                   The IP address of the host to add.            
*    ttl                       The Time To Live for this entry.              
*                                                                            
* OUTPUTS                                                                    
*                                                                            
*    DNS_HOST*                 A host pointer, or NULL if the host can       
*                               not be added.                                
*                                                                            
******************************************************************************/
DNS_HOST *DNS_Add_Host(CHAR *name, CHAR *ip_addr, UNSIGNED ttl)
{
    INT             size;
    DNS_HOST        *dns_host;
    UNSIGNED        time;

    /* Get the size of the name. */
    size = strlen(name) + 1;

    /* Retrieve the current time. */
    time = NU_Retrieve_Clock();

    /* Before allocating memory for a new entry, check to see if the TTL of an
       old entry has expired.  If so re-use that entry. */
    for ( dns_host = DNS_Hosts.dns_head;
          dns_host;
          dns_host = dns_host->dns_next )
    {
        /* First check to see if this entry has a ttl.  A ttl of 0 is used to

⌨️ 快捷键说明

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