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

📄 dns_client_support.c

📁 DNS 的实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ############################################################################ (c) Copyright Virata Limited 2001 ## 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_support.c * * description:  most of the routines in this file support handling messages *               received by the DNS client. *//*  * List of New Routines: *     dns_node_query_reply() *     dns_addr6_query_reply() *     dns_start_next_search_common() *     dns_start_next_search6() *     display_node_reply() */#include <errno.h>#include <netinet/in.h>#include <netdb.h>#include "messages.h"#include "dns_resolv.h"#include "dns_client.h"#include "dns_client_query.h"#include "dns_client_resource.h"#include "dns_client_cache.h"#include "dns_client_util6.h"#include "netlib.h"#include "dns_client_statics.h"static void  display_host_reply(ATMOS_MESSAGE *);static void  display_node_reply(ATMOS_MESSAGE *);static void  terminate_query(QueryState *);#ifdef DNS_DEBUGvoid display_dnsmsghdr(U8 *pkt);#endif/* * dns_node_query_reply -- *     This routine is called when we receive a host query reply.   *     This could be from one of our "internal" queries or, it could be the  *     results of an nslookup query. We first see if the message matches  *     an nslookup.  If so we just hand it off. *     Otherwise it must be an internal query.  If it doesn't match any  *     current query we just free up the resources.  If it does match we  *     call the reply routine for that query. * * PARAMETERS *     rmsg - DNS_GET_NODEBYNAME message * * RETURNS *     n/a */voiddns_node_query_reply(IN ATMOS_MESSAGE *rmsg){    QueryState *query;    DNSC_DEBUG("entry\n");    if (dns_nslkup_locate(rmsg) == TRUE)     {        display_node_reply(rmsg);        DNSC_DEBUG("exit - positive dns_nslkup_locate\n");	return;    }    if ((query = search_wait_list_reply(rmsg)) == NULL)     {        dprintf("%C no query state in list for DNS query reply (not an error)\n");	dns_hent_msg_free(rmsg);        DNSC_DEBUG("exit - no query state in list for DNS query reply\n");	return;    }    if (query->dns_qreply != NULL)         query->dns_qreply(query);    else     {        dprintf("%C no internal query reply handle\n");	dns_hent_msg_free(rmsg);    }    DNSC_DEBUG("exit\n");    }   /* end dns_node_query_reply() *//* * dns_addr6_query_reply -- *     This routine is called when we receive a reply from a nslookup query  *     for a host name.  Note in this case we know it is from nslookup  *     since all of the internal queries are for addresses.  The address that  *     is printed out is the one the user entered on the command line. * * PARAMETERS *     rmsg - DNS_GET_HOSTBYADDR6 message * * RETURNS *     n/a */voiddns_addr6_query_reply(ATMOS_MESSAGE *rmsg){    struct hostent  *hent;    MSG_D_DNS_GET_HOSTBYADDR6(dmsg, rmsg);    DNSC_DEBUG("entry\n");    if ( ESUCCESS == dmsg->error ) {        char  ipaddr[INET6_ADDRSTRLEN];	hent = dmsg->hent;        if (hent->h_addr_list)        {            inet_ntop(AF_INET6, hent->h_addr_list[0],                       ipaddr, sizeof(ipaddr));        }        else        {            strcpy(ipaddr,"<unknown>");        }	printf("Name:     %s\n", hent->h_name);	printf("Address:  %s\n", ipaddr);    }    else         print_dns_error(dmsg->error);    dns_nslkup_msg_free(rmsg);    DNSC_DEBUG("exit\n");}   /* end dns_addr_query_reply() *//* * dns_host_query_reply() * * this routine is called when we receive a host query reply.  this could be from * one of our "internal" queries or, it could be the results of an nslookup query. * we first see if the message matches an nslookup.  if so we just hand it off. * otherwise it must be an internal query.  if it doesn't match any current query * we just free up the resources.  if it does match we call the reply routine for * that query. */voiddns_host_query_reply(ATMOS_MESSAGE *rmsg){    QueryState *query;    DNSC_DEBUG("entry\n");    if ( dns_nslkup_locate(rmsg) == TRUE ) {        display_host_reply(rmsg);        DNSC_DEBUG("exit - positive dns_nslkup_locate\n");	return;    }    if ((query = search_wait_list_reply(rmsg)) == NULL) {        dprintf("%C no query state in list for DNS query reply (not an error)\n");	dns_hent_msg_free(rmsg);        DNSC_DEBUG("exit - no query state in list for DNS query reply\n");	return;    }    if ( query->dns_qreply != NULL )         query->dns_qreply(query);    else {        dprintf("%C no internal query reply handle\n");	dns_hent_msg_free(rmsg);    }    DNSC_DEBUG("exit\n");    }   /* end dns_host_query_reply() *//* * dns_addr_query_reply() * * this routine is called when we receive a reply from a nslookup query for a * host name.  note in this case we know it is from nslookup since all of the  * internal queries are for addresses.  the address that is printed out is the * one the user entered on the command line. */voiddns_addr_query_reply(ATMOS_MESSAGE *rmsg){    struct dns_hostent  *hptr;    MSG_D_DNS_GET_HOSTBYADDR(dmsg, rmsg);    DNSC_DEBUG("entry\n");    if ( ESUCCESS == dmsg->error ) {        char  ipaddr[INET6_ADDRSTRLEN];	hptr = dmsg->hptr;        inet_ntop(AF_INET, hptr->h_addr_list + 0,                   ipaddr, sizeof(ipaddr));	printf("Name:     %s\n", hptr->h_name);	printf("Address:  %s\n", ipaddr);    }    else         print_dns_error(dmsg->error);    dns_nslkup_msg_free(rmsg);    DNSC_DEBUG("exit\n");}   /* end dns_addr_query_reply() *//* * dns_udp_message() * * this routine handles the case when we get a UDP message.  we expect the * message is a reply to one of our query requests.  we get the message and  * use the message id to determine which query it matches to.  if no query is * found we assume that query has already been handled and just exit.  if one * is found we hand the message to it for handling.  Note that if the parse  * attempt fails we treat the case the same as if the message had timed out. */voiddns_udp_message(U8 *dnsmsg, int nbytes){    int         msgid;    QueryState  *query;    DNSC_DEBUG("entry\n");    /* next get the DNS message id.  then use it to see if there's a QueryState     * that's waiting for the message.  if not we're done.  if so go ahead and     * parse the message.     */    msgid = ntohs(((DnsHdr *)dnsmsg)->id);    if ((query = search_wait_list_id((U16 )msgid)) == NULL) {#if defined(DNS_DEBUG) && defined(DNS_VERBOSE)        dprintf("%C no query for DNS message id %d (this is not an error)\n", msgid);#endif        DNSC_DEBUG("exit - no query for DNS message id %d\n", msgid);	return;    }#if defined(DNS_DEBUG)    /* Copy address of server */    memcpy(&query->svripaddr, dns_client_udp_get_sourceaddr(),           sizeof(query->svripaddr));#endif    #if defined(DNS_DEBUG) && defined(DNS_VERBOSE)    dprintf("%C dns_udp_message: got a query:\n");    dns_print_query(query);#endif    if ( parse_dns_message(dnsmsg, nbytes, &query->dnsreply) < 0 ) {	dprintf("%C error attempting to parse the DNS response\n");        /* since the message did match a QueryState assume it was intended as 	 * a reply.  handle it as if we had timed out waiting for a message.	 */	dns_response_timeout(query);        DNSC_DEBUG("exit - parse_dns_message failed\n");	return;    }    DNSC_DEBUG("call dns_response method 0x%08x\n", query->dns_response);        query->dns_response(query);    /* dns_response will clean up the parsed message */    DNSC_DEBUG("exit - dns_response method finished\n");}   /* end dns_udp_message() */        /* * dns_response_timeout() * * got a time out.  this could be for a "main" query or a "support" query.  a support * query is one that was started to deal with something from another query.  an  * example is when a name server response suggests another nameserver to try but * we don't have the new name server address.  to get it we start another query, this * new query is a support query.  (NOTE: in other places I call the support query * an internal query) * * first we check to verify we haven't already exceeded any limits before trying * to do anything else.  if we have we terminate the query.  next we determine the * next name server to try.  if we've tried all the name servers in our list the * max number of times the query is considered done.  we then check to see if we * need to try another element of the search list.  this would be the case when the * user wanted the IP address of a relative host name. */voiddns_response_timeout(QueryState *query){    int       i;    DNSC_DEBUG("entry\n");    /*     * first, verify that we haven't exceeded any limits we have on the number     * of DNS requests we've made for this query or the number of query depths,     * which is where we have to post a different DNS query to support this one.     */    if ( query->ntrys > MAXDNSTRYS || query->nquerys > MAXQUERYDEPTH ) {        dprintf("%C DNS query max exceeded\n");	dprintf("max trys allowed %d, attempted %d\n", MAXDNSTRYS, query->ntrys);	dprintf("max queries allowed %d attempted %d\n", MAXQUERYDEPTH, query->nquerys);	terminate_query(query);     DNSC_DEBUG("finished - query terminated - too many\n");	return;    }    /*      * okay, now see if there's another name server to try.  it would seem simplier     * to just keep the index of the next name server to try but that won't work     * because we can get a DNS response that suggests different name servers to     * try.  it can be more than one and what we do with the list is to replace     * name servers in our list that shouldn't be as good as the suggested ones.     * so the list can be mixed with servers that have been tried already and some     * that haven't been tried at all.  so first we loop through to find one that     * hasn't been used at all, and if there aren't any we just get one that hasn't     * been tried too many times.  also, since RES_RETRY typically is 2, so we won't      * likely be using the same name server twice in a row.     */    for ( i = 0; i < query->num_ns; i++ ) {        if ( 0 == query->ns_addrs[i].ns_try ) {	    if ( post_query(query, i) < 0 ) {#ifdef DNS_DEBUG                char  strip[INET6_ADDRSTRLEN];				ip_string(&query->ns_addrs[i].ns_addr, strip, sizeof(strip));	        dprintf("%C error sending DNS request to %s\n", strip);#endif                terminate_query(query);   /* there's an error sending message quit */            DNSC_DEBUG("finished - query terminated - post #0 error\n");		return;	    }	    else {#ifdef DNS_DEBUG                char  str[INET6_ADDRSTRLEN];                ip_string(&query->ns_addrs[i].ns_addr, str, sizeof(str));	        dprintf("%C trying name server %s\n", str);		dprintf("for query %s\n\n", query->domain);#endif             DNSC_DEBUG("finished - try the first time\n");                return;	    }	}    }    for ( i = 0; i < query->num_ns; i++ ) {        if ( query->ns_addrs[i].ns_try < RES_RETRY  ) {	    if ( post_query(query, i) < 0 ) {#ifdef DNS_DEBUG                char  str2[INET6_ADDRSTRLEN];		ip_string(&query->ns_addrs[i].ns_addr, str2, sizeof(str2));	        dprintf("%C error sending DNS request to %s\n", str2);#endif		terminate_query(query);  /* end the query if UDP error */            DNSC_DEBUG("finished - query terminated - post #%d error\n",                       query->ns_addrs[i].ns_try);		return;	    }	    else {#ifdef DNS_DEBUG                char  str3[INET6_ADDRSTRLEN];                ip_string(&query->ns_addrs[i].ns_addr, str3, sizeof(str3));	        dprintf("%C trying name server %s\n", str3);		dprintf("this is the %d try for this server\n", query->ns_addrs[i].ns_try);		dprintf("for query %s\n\n", query->domain);#endif             DNSC_DEBUG("finished - try once more\n");                return;	    }	}    }    /*      * if we get here, we've run out of name servers to try.  we see if we need     * to try another search list element.  note if we terminate the query we do     * it with a try again error, see RFC 1035, since we didn't get any other     * error type from a name server or we wouldn't have gotten here.     */    if ( query->next_srch < 0 )        /* no need to try search list */    {        terminate_query(query);        /* let the caller know we didn't find anything */        DNSC_DEBUG("finished - query terminated - no next search\n");    }    else    {        dns_start_next_search_common(query);  /* try the next search list */        DNSC_DEBUG("finished - start next search\n");    }}   /* end dns_response_timeout() *//* * dns_start_next_search_common -- *     This routine starts either 'dns_start_next_search()' or  *     'dns_start_next_search6()' depending on the family. We guess the *     family to be AF_INET6 for aaaa_type and a6_type queries. * * PARAMETERS *     query - query state structure * * RETURNS *     n/a */voiddns_start_next_search_common(QueryState *query){    DNSC_DEBUG("entry\n");    if (query->qtype == a6_type || query->qtype == aaaa_type)        dns_start_next_search6(query);    else        dns_start_next_search(query);    DNSC_DEBUG("exit\n");}/* dns_start_next_search6 -- *     This routine sets up for the next attempt using a constructed name  *     from search list. *  * PARAMETERS *     query - query state structure *  * RETURNS *     n/a */voiddns_start_next_search6(QueryState *query){    int   i;    MSG_D_DNS_GET_NODEBYNAME(dmsg, query->reply);     DNSC_DEBUG("entry\n");

⌨️ 快捷键说明

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