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

📄 dns_client_query.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# ##########################################################################*/#include "dns_resolv.h"#include "dns_client_query.h"#include "dns_client_cache.h"#include "dns_client_resource.h"#include "messages.h"#include "errno.h"#include <timelib.h>#include "dns_client_statics.h"#define DNSIDMAX  (int )0xFFFFFFFF#ifdef DNS_DEBUGextern int  dns_verbosity;extern void display_dnsmsghdr(U8 *);#endifextern U32  ipstring2long(const char *);static int  msgid = 1;/* * dns_gethostbyname() * * this routine will handle setting up for a standard query for an address.  the * routine will attempt to determine if we have a relative domain name and if so * will construct a complete domain name using the first element from the search * list.  it then sets the next search list index.  if a complete name it sets the * next search index to indicate its not necessary to worry about trying another * search list element should the query fail.  the cache is queried only if indicated * to do so by the user.  if the cache query fails or isn't attempted this routine * sets the query state up to post a message to the first name server.  dns_query() * handles that part of the job. */voiddns_gethostbyname(ATMOS_MESSAGE *msg, DnsDomain *dm){    QueryState  *qs;    int         cflag = FALSE;    U32         ip;    MSG_D_DNS_GET_ADDRBYNAME(dmsg, msg);    DNSC_DEBUG("entry\n");#if defined(DEBUG)    print_resource_pool();#endif    /*      * first verify that the hostname is not an IP address.  if it is we'll     * handle it differently.  if the hostname is an IP address we copy      * the hostname string (the IP address) into the host name element of     * the dns_hostent structure.  then, convert the string to an unsigned     * long value (U32), and assign it to the first element of the host      * address list.  then set the number of addresses to 1.  this is done     * so as to be similiar to the gethostbyname() UNIX library routine.     */    if ((ip = ipstring2long(dmsg->hostname)) != (U32 )-1) {        strcpy(dmsg->hptr->h_name, dmsg->hostname);        if ( dmsg->hptr->h_numaddrs > 0 ) {            dmsg->hptr->h_addr_list[0] = ip;            dmsg->hptr->h_numaddrs = 1;        }        dmsg->error = ESUCCESS;        sendreply(msg);        return;    }    /* if not an IP address, then verify that we were sent a valid host name.       * if not just return an error without doing anything.     */    if ( dns_validate_hostname(dmsg->hostname) < 0 ) {        dprintf("%C bad host name\n");	dmsg->error = EHOSTNOTFOUND;	sendreply(msg);        DNSC_DEBUG("exit - bad host name\n");	return;    }    /* get a new query state */    if ((qs = dns_get_querystate()) == NULL) {        dprintf("%C no free query states available\n");#ifdef DNS_DEBUG	print_resource_pool();#endif        dmsg->error = ENOMEM;	sendreply(msg);        DNSC_DEBUG("exit - no free query states available\n");	return;    }    /* initialize the query state structure */    qs->use_cache = dmsg->use_cache;    qs->nquerys = dmsg->qcnt;    qs->reply = msg;    copy_domain(&qs->dm, dm);    /*     * if the host name ends with a dot, we assume the user wants us to try it     * as a complete host name.  if not, then we first just add the dot to the      * name and try that then we'll add elements of the search list if that      * fails.     */    strcpy(qs->domain, dmsg->hostname);    if ( DOT == qs->domain[strlen(qs->domain)-1] ) {  /* we've got a complete host name */        dprintf("%C trying the null domain\n");	qs->next_srch = -1;    }    else {	strcat(qs->domain, SDOT);    /* add the '.' */	qs->next_srch = 0;           /* set index of the first search list to try */    }    /*      * okay now we have a host name to try. if the user wants to use the cache     * we construct a question and submit it to the cache.  the cache can return     * CNAME and A type resource records (RR).  it is possible to have the CNAME     * but not the address for it, if that's the case we have to start the query     * with the offical, that is the canonical (CNAME).  we can tell if we have      * both the CNAME and the address for it by the number of RRs.  if the user      * doesn't want to use the cache we skip this and just send off a query to     * the first name server.     */    if ( qs->use_cache ) {        DnsQuestion  question;  /* cache requests are in the form of a DNS question */	DnsMsg       dnsmsg;    /* responses are returned in a DNS message */	strcpy(question.q_name, qs->domain);	question.q_type = QT_A;	question.q_class = QC_IN;        memset(&dnsmsg, 0, sizeof(dnsmsg));	if ( query_cache(&question, &dnsmsg) == 0 ) {	    /* 	     * first check for a name error, the cache will set the flags to	     * indicate a name error if we know the host name doesn't exist.	     * no need to clean up the DnsMsg if name error, only the flag is 	     * set.	     */	    if ((dnsmsg.m_dnshdr.flags & DNS_RCODE) == DNS_NAMEERR) {	        if ( qs->next_srch > -1 ) {                    /*                     * well, we know that this domain name doesn't exist, and we                     * haven't tried all the domains in the search list, so, set up                     * as if for another query, we may have to query a name sever.                     *                     * first get a list of name server addresses.                     */                    if ((qs->num_ns = get_ns_list(qs->domain, qs->ns_addrs, dm)) == 0) {                        dprintf("%C No name servers to query\n");                        dmsg->error = ENONSADDRESS;                        free_querystate(qs);                        sendreply(msg);                        DNSC_DEBUG("exit - no name server to query\n");                        return;                    }                    /* now set up the rest of the query state */                    qs->dns_construct = dns_std_query;                    qs->dns_response = dns_response_std_query;                    qs->dns_qreply = NULL;                    qs->ntrys = 0;                    qs->qtype = ac_type;                    qs->qstate = wf_caddr;		    return dns_start_next_search(qs);		}		dmsg->error = EHOSTNOTFOUND;		free_querystate(qs);		sendreply(msg);            DNSC_DEBUG("exit - host not found\n");		return;	    }	    	    /* 	     * if the anwser RR is a CNAME and there are no additional records	     * then we have to construct the DNS query for the new name. otherwise	     * format the answer and send it back.  the cache places A records for	     * a CNAME in the additional section.	     */	    if ( QT_CNAME == dnsmsg.m_answers->r_type && 0 == dnsmsg.m_dnshdr.naddrr ) {	        strcpy(qs->cname, qs->domain);		strcpy(qs->domain, dnsmsg.m_answers->r_data);		dnsmsg_cleanup(&dnsmsg);		cflag = TRUE;	    }	    else { 		fmt_cache_answer(qs, &dnsmsg);		free_querystate(qs);		dnsmsg_cleanup(&dnsmsg);		sendreply(msg);            DNSC_DEBUG("exit - reply from cache\n");		return;	    } 	}    }    /*      * first get a list of default name servers to try, then construct the DNS     * request message, send the message and start listen to network.     */    if ((qs->num_ns = get_ns_list(qs->domain, qs->ns_addrs, dm)) == 0) {        dprintf("%C No name servers to query\n");	dmsg->error = ENONSADDRESS;	free_querystate(qs);	sendreply(msg);        DNSC_DEBUG("exit - no name server to query\n");	return;    }#ifdef DNS_DEBUG    if ( dns_verbosity > 1 ) {        int     j;	NS_t    *ns;	char    ipstr[INET6_ADDRSTRLEN];        	ns = qs->ns_addrs;	for ( j = 0; j < qs->num_ns; j++ ) {	    ip_string(&ns[j].ns_addr, ipstr, sizeof(ipstr));	    if ( ns[j].ns_name[0] != '\0' )	        dprintf("NS_list[%d]: %s, address %s\n", j, ns[j].ns_name, ipstr);	    else	        dprintf("NS_list[%d] address: %s\n", j, ipstr);	}    }#endif    qs->dns_construct = dns_std_query;    qs->dns_response = dns_response_std_query;    qs->dns_qreply = NULL;    qs->ntrys = 0;    if ( FALSE == cflag ) {	qs->qtype = a_type;	qs->qstate = wf_addr;    }    else {	qs->qtype = ac_type;	qs->qstate = wf_caddr;    }#if defined (DNS_DEBUG) && defined (DNS_VERBOSE)    dprintf("starting query for %s\n", qs->domain);#endif    if ( dns_query(qs) < 0 ) {	dmsg->error = ETRYAGAIN;	free_querystate(qs);	sendreply(msg);        DNSC_DEBUG("exit - dns_query failed\n");	return;    }    DNSC_DEBUG("exit\n");}   /* end dns_gethostbyname() *//* * dns_gethostbyaddr() * * this routine will set up a query state to handle a PTR request. this is the * case where we have an IP address and want the domain name associated with that * host.  if the user wants we first query the cache and if found there return the * cached information.  if not, or if not found in the cache, we set up for a query * to the DNS name servers.  */voiddns_gethostbyaddr(ATMOS_MESSAGE *msg, DnsDomain *dm){    QueryState    *query;    MSG_D_DNS_GET_HOSTBYADDR(dmsg, msg);    DNSC_DEBUG("entry\n");    if ((query = dns_get_querystate()) == NULL) {    /* get a new query state structure */        dprintf("%C no free query states available\n");#ifdef DNS_DEBUG	print_resource_pool();#endif        dmsg->error = ENOMEM;	sendreply(msg);	return;    }    /* initialize the query state structure */    query->use_cache = dmsg->use_cache;    query->nquerys = dmsg->qcnt;    query->reply = msg;    copy_domain(&query->dm, dm);    reverse_ip_addr(dmsg->ipaddr, query->domain);    /* if alright by the user we first see if the info is in the cache */    if ( query->use_cache ) {        DnsQuestion  question;   /* the cache wants a DNS question */	DnsMsg       dnsmsg;     /* our representation of the DNS message */	/* construct question, then try the cache */	strcpy(question.q_name, query->domain);	question.q_type = QT_PTR;	question.q_class = QC_IN;	/* the cache either has a RR for this IP address or it doesn't */        	memset(&dnsmsg, 0, sizeof(dnsmsg));	if ( query_cache(&question, &dnsmsg) == 0 ) {            /* see if the cache knows that this address doesn't exist.  we	     * cache name error replies.  no need to clean up the DnsMsg	     * if name error, only the flag is set.	     */	    if ((dnsmsg.m_dnshdr.flags & DNS_RCODE) == DNS_NAMEERR) 		dmsg->error = EHOSTNOTFOUND;	    else {		fmt_ptr_answer(query, &dnsmsg);		dnsmsg_cleanup(&dnsmsg);	    }	    sendreply(msg);	    free_querystate(query);	    return;	}    }    /*     * either the user didn't want to use the cache or it wasn't there.  first     * we need to get a list of default name servers to try.  this is done by     * looking to the cache for name servers that would be good to try or just     * using the default list.  not having a list is considered a fatal error.     */    if ((query->num_ns = get_ns_list(query->domain, query->ns_addrs, dm)) == 0) {        dprintf("%C No name servers to query\n");	dmsg->error = ENONSADDRESS;	free_querystate(query);	sendreply(msg);	return;    }#ifdef DNS_DEBUG        if ( dns_verbosity > 1 ) {        int     j;	NS_t    *ns;	char    ipstr[INET6_ADDRSTRLEN];        	ns = query->ns_addrs;	for ( j = 0; j < query->num_ns; j++ ) {	    ip_string(&ns[j].ns_addr, ipstr, sizeof(ipstr));	    if ( ns[j].ns_name[0] != '\0' )

⌨️ 快捷键说明

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