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

📄 dns_client_skt.c

📁 DNS 的实现代码
💻 C
字号:
/* ############################################################################ (c) Copyright Virata Limited 2002## Virata Limited Confidential and Proprietary## The following software source code ("Software") is strictly confidential and# is proprietary to Virata Limited ("Virata").  It may only be read, used,# copied, adapted, modified or otherwise dealt with by you if you have# entered into a confidentiality agreement with Virata and then subject to the# terms of that confidentiality agreement and any other applicable agreement# between you and Virata.  If you are in any doubt as to whether you are# entitled to access, read, use, copy, adapt, modify or otherwise deal with# the Software or whether you are entitled to disclose the Software to any# other person you should contact Virata.  If you have not entered into a# confidentiality agreement with Virata granting access to this Software you# should forthwith return all media, copies and printed listings containing# the Software to Virata.## Virata reserves the right to take legal action against you should you breach# the above provisions.## If you are unsure, or to report violations, please contact# support@virata.com# ##########################################################################*//* * File:  dns_client_skt.c * * Description: This file contains routines dealing with the UDP messages *              that the DNS client sends and receives.  The idea is to *              hide some of interaction with sockets from the rest of the *              code. Note that we do not set our source UDP port number. *              There is no set port number that must be used by the DNS *              client, and the NS must respond to whatever port we use, *              (see RFC 2181 section 4.2). */#include <sys/time.h>#include <netinet/in.h>#include "dns_client.h"#include "dns_client_query.h"#include "dns_client_resource.h"#include "dns_client_statics.h"#undef DEBUG_LEVEL#define DEBUG_LEVEL     (0x01)  /* Only trace messages */#define SIN(ptr)            ((struct sockaddr_in *)(ptr))#define SIN_PORT(p_sin)     (SIN(p_sin)->sin_port)#define SIN_ADDR(p_sin)     (&(SIN(p_sin)->sin_addr))#define SIN6(ptr)           ((struct sockaddr_in6 *)(ptr))#define SIN6_PORT(p_sin6)   (SIN6(p_sin6)->sin6_port)#define SIN6_ADDR(p_sin6)   (&(SIN6(p_sin6)->sin6_addr))#define SA(ptr)             ((struct sockaddr *)(ptr))#define SA_FAMILY(p_sa)     (SA(p_sa)->sa_family)#define SA_PORT(p_sa)       (((p_sa)->sa_family == AF_INET) ?     \                                 SIN_PORT(p_sa) : SIN6_PORT(p_sa))#define SET_PORT(p_sa, value)    if ((SA_FAMILY(p_sa) == AF_INET)) \                                     SIN_PORT(p_sa) = value; \                                 else \                                     SIN6_PORT(p_sa) = value                                             #define SA_ADDR(p_sa)       ((SA(p_sa)->sa_family == AF_INET) ?     \                                 (void *)SIN_ADDR(p_sa) :           \                                 (void *)SIN6_ADDR(p_sa))#define DNS_CLIENT_MAX_TIME     ((u_long)(-1))char *dns_client_inetaddr(const struct sockaddr *addr);    /* Socket for DNS client networking */static int                     dns_client_skt = -1;/* Timeout in milliseconds for next atmos_select() call */static u_long                  dns_client_posted_query_timeout = 0;/* Buffer to receive data from socket */U8                      dns_client_recvbuf[BUFLEN];/* Address of the sender */static struct sockaddr_storage dns_client_msg_from;/* Length of the used part of sockaddr_storage */static socklen_t               dns_client_msg_fromlen;/* dns_client_udp_send -- *     Sends UDP message.  The message should already have DNS message *     only.  DNS client socket is opened if it's necessary. * * PARAMETERS: *     buffer  - buffer with message to send *     nbytes  - number of bytes in the buffer to send *     to      - pointer to the target address *     tolen   - length of the target address *     timeout - timeout for the query in milliseconds * * RETURNS: *     >0  - for success - number of bytes was sent *     -1 -  to indicates an error condition */intdns_client_udp_send(U8 *buffer, int nbytes,                    const struct sockaddr *p_sa_to, socklen_t tolen,                    u_long timeout){    int nsent;#if defined(DNS_HAVE_IP6STACK)    struct sockaddr_in6 to_sin6;#endif        DNSC_DEBUG("entry\n");    /* Validate number of bytes to send */    if (nbytes <= 0 || nbytes > (int)BUFLEN)    {        DNSC_DEBUG("exit - number bytes to send %d invalid\n", nbytes);        return -1;    }        /* Open socket if it is necessary */    if (dns_client_skt == -1)    {        DNSC_DEBUG("Try to open DGRAM socket\n");#if defined(DNS_HAVE_IP6STACK)        dns_client_skt = socket(PF_INET6, SOCK_DGRAM, 0);#else        dns_client_skt = socket(PF_INET, SOCK_DGRAM, 0);#endif                if (dns_client_skt == -1)        {            DNSC_MSG("failed to open DNS client socket\n");            return -1;        }        DNSC_DEBUG("socket %d opened\n", dns_client_skt);    }    #if defined(DNS_HAVE_IP6STACK)    if (p_sa_to->sa_family == AF_INET)    {        /*          * In order to send query to IPv4 server via IPv6 socket         * make IPv6 IPv4-mapped address         */        MAKE_SIN6_V4MAPPED_BY_INADDR(SIN_ADDR(p_sa_to), &to_sin6);        /* Substitute destination address pointer */        p_sa_to = (struct sockaddr *)&to_sin6;        tolen = sizeof(to_sin6);    }#endif        /* Set up DNS Name Server port */    SET_PORT(p_sa_to, htons(NSPORT));        DNSC_DEBUG("Send to socket %d buffer 0x%08x len %u\n",               dns_client_skt, buffer, nbytes);    DNSC_DEBUG("Dst: family %s len %u addr %s\n",               (p_sa_to->sa_family == AF_INET) ? "INET" : "INET6",               tolen, dns_client_inetaddr(p_sa_to));    /* Transmit message to another socket */    nsent = sendto(dns_client_skt, buffer, nbytes, 0 /* no flags */,                   p_sa_to, tolen);    DNSC_DEBUG("sendto() function returned %d\n", nsent);    if (nsent == -1)    {        /* Change return code in order to don't fail request immediately */        nsent = 0;        /*          * Set timeout for the posted query to minimal possible value         * in order to time out request ASAP         */        dns_client_posted_query_timeout = 1;        /* Error to sendto */        DNSC_DEBUG("sendto() failed\n");    }    else     {        if (nsent != nbytes)        {            DNSC_TRACE("Incomplete DNS message was sent "                       "(%d bytes instead of %d)\n", nsent, nbytes);        }        /* Set timeout for the posted query (minimum) */        if ((dns_client_posted_query_timeout == 0) ||            (dns_client_posted_query_timeout > timeout))        {            dns_client_posted_query_timeout = timeout;        }        DNSC_DEBUG("Set dns_client_posted_query_timeout = %d\n",                   timeout);    }    DNSC_DEBUG("exit - %d\n", nsent);    return nsent;} /* dns_client_udp_send *//* dns_client_udp_receive -- *     Waits for data or ATMOS messages. Receives data and processes *     them. Another ATMOS messages are handled by socket handler *     registered during initialization. * * PARAMETERS: *     N/A *  * RETURNS: *     N/A */voiddns_client_udp_receive(){    int            result;    struct timeval current_time;    struct timeval select_timeout;    u_int          queries_min_timeout = 0;    u_int          current_timeout;    fd_set         readfds;        /* Has DNS client socket been opened? */    if (dns_client_skt == -1)    {        /* DNS client socket hasn't been opened */        return;    }        DNSC_DEBUG("entry\n");    /* Clean up set of file descriptors to read from */    FD_ZERO(&readfds);    DNSC_DEBUG("dns_client_posted_query_timeout = %d\n",               dns_client_posted_query_timeout);    DNSC_DEBUG("queries_min_timeout = %d\n", queries_min_timeout);    DNSC_DEBUG("=> current_timeout = %d\n",                (dns_client_posted_query_timeout == 0) ?                   queries_min_timeout :                   (queries_min_timeout == 0) ?                       dns_client_posted_query_timeout :                       MIN(dns_client_posted_query_timeout,                           queries_min_timeout));        /* Do while active queries exist */    while ((current_timeout = (dns_client_posted_query_timeout == 0) ?                                  queries_min_timeout :                                  (queries_min_timeout == 0) ?                                      dns_client_posted_query_timeout :                                      MIN(dns_client_posted_query_timeout,                                          queries_min_timeout))                            > 0)    {        /* Set posted query timeout to zero but it may be changed */        dns_client_posted_query_timeout = 0;                /* Set up DNS client socket bit */        FD_SET(dns_client_skt, &readfds);        /* Prepare timeout */        select_timeout.tv_sec = 0;        select_timeout.tv_usec = current_timeout * 1000;            /*          * Wait for ready data in opened socket and process another         * messages using socket handler which was registered during         * initialization         */        DNSC_DEBUG("call atmos_select ...\n");        result = atmos_select(dns_client_skt + 1, &readfds,                              NULL /* no writefds */,                               NULL /* no exceptfds */,                              &select_timeout,                              NULL /* no place for ATMOS message */ );        DNSC_DEBUG("... atmos_select return code %d\n", result);        if (result == -1)        {            /* Fatal error returned by atmos_select */            DNSC_TRACE("atmos_select() failed\n");            /* Fail here if it's debugged */            ASSERT(FALSE);            break;        }        else if (result == 0)        {            /* The timeout expires before anything interesting happens */            DNSC_TRACE("Timeout\n");        }        else if ((result == 1) &&                  FD_ISSET(dns_client_skt, &readfds))        {            /* Set correct length of the structure for source address */            dns_client_msg_fromlen = sizeof(dns_client_msg_from);            /* Receive data from socket */            result = recvfrom(dns_client_skt, dns_client_recvbuf,                              BUFLEN, 0 /* no flags */,                              (struct sockaddr *)&dns_client_msg_from,                              &dns_client_msg_fromlen);            if (result == -1)            {                /* Fatal error returned by recvfrom */                DNSC_TRACE("recvfrom failed\n");                /* Fail here if it's debugged */                ASSERT(FALSE);                                             break;            }            else            {                DNSC_TRACE("UDP message received\n");                DNSC_DEBUG("Received from socket %d buffer 0x%08x len %u\n",                           dns_client_skt, dns_client_recvbuf, result);                DNSC_DEBUG("Src: family %s len %u addr %s\n",                           (SA_FAMILY(&dns_client_msg_from) == AF_INET) ?                               "INET" : "INET6",                           dns_client_msg_fromlen,                           dns_client_inetaddr(SA(&dns_client_msg_from)));                /* Process message */                DNSC_DEBUG("call dns_udp_message ...\n");                dns_udp_message(dns_client_recvbuf, result);                DNSC_DEBUG("... dns_udp_message finished\n");                /* dns_client_posted_query_timeout might be changed */            }        }        else        {            /* Unpredictable behaviour */            DNSC_TRACE("atmos_select returned too many active "                       "descriptors or active not requested\n");            /* Fail here if it's debugged */            ASSERT(FALSE);            break;        }                /* Get current time value */        if (gettimeofday(&current_time, NULL) != 0)        {            /* Fatal error returned by atmos_select */            DNSC_TRACE("gettimeofday() failed\n");            /* Fail here if it's debugged */            ASSERT(FALSE);            break;        }                /* Some time was elapsed */        DNSC_DEBUG("call dns_client_query_timeout ...\n");        queries_min_timeout = dns_client_query_timeout(                                  &current_time,                                  dns_response_timeout);        DNSC_DEBUG("... dns_client_query_timeout returned %d\n",                   queries_min_timeout);        /* dns_client_posted_query_timeout might be changed too */            DNSC_DEBUG("dns_client_posted_query_timeout = %d\n",                   dns_client_posted_query_timeout);    } /* end while */        /* If loop was breaked by error - terminate all queries */    if (current_timeout > 0)    {        current_time.tv_sec = DNS_CLIENT_MAX_TIME;        /* Discord all queries */        dns_client_query_timeout(&current_time,                                 dns_response_timeout);    }    /* Close socket */        close(dns_client_skt);    DNSC_DEBUG("socket %d was closed\n", dns_client_skt);    DNSC_TRACE("No active queries\n");    /* Mark socket ad closed */    dns_client_skt = -1;        DNSC_DEBUG("exit\n");} /* dns_client_udp_receive */#ifdef DNS_DEBUG/* dns_udp_get_sourceaddr -- *     Returns pointer to the source address of the UDP message. *     This is useful for knowing which server responded with an  *     answer. Since this routine is used from debug only, we do *     no error checking. * * PARAMETERS: *     N/A * * RETURNS: *     pointer to to the source address of the UDP message */struct sockaddr_storage *dns_client_udp_get_sourceaddr(){    return &dns_client_msg_from;} /* dns_client_udp_get_sourceaddr *//* dns_client_inetaddr -- *     Converts IP (IPv4 or IPv6) address in internal representation  *     to human-readable form (for logging). * * PARAMETERS: *     addr - IP address * * RETURNS: *     pointer to address in human-readable form */char *dns_client_inetaddr(const struct sockaddr *addr){    static char addr_buf[INET6_ADDRSTRLEN];        if ((addr == NULL) ||        (inet_ntop(addr->sa_family, SA_ADDR(addr),                   addr_buf, INET6_ADDRSTRLEN) == NULL))    {        addr_buf[0] = '\0';    }            return addr_buf;}#endif

⌨️ 快捷键说明

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