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

📄 dns_client_packet.c

📁 DNS 的实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ############################################################################ (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_packet.c * * description:  this file contains routines used in the parsing and construction *               of the DNS packet. * */#include <stdio.h>#include <string.h>#include "dns_client.h"#include "dns_client_resource.h"static int  parse_dns_question(U8 *dnsmsg, U8 *data, DnsQuestion *dq, int bremain);static int  parse_dns_record(U8 *dnsmsg, U8 *data, DnsRRec *drr, int bremain);static int  parse_soa_data(SOArec *srec, U8 *dnsmsg, U8 *data);static int  get_dname(U8 *dnsmsg, U8 *data, U8 *dname);static int  get_label(U8 *data, U8 *label);static int  install_dns_question(U8 *cptr, DnsQuestion *dquest);static int  install_dns_rrecord(U8 *cptr, DnsRRec *drrec);static int  create_dname(char *domain, char *buffer);#ifdef DNS_DEBUGvoid  print_resource_record(DnsRRec *);void  print_question(DnsQuestion *);void  dns_string(DnsRRec *);void  dns_ipaddr(DnsRRec *);void  dns_default(DnsRRec *);void  dns_soa(DnsRRec *);#endif/* * create_dns_message() * * this routine takes a pointer to a completed DnsMsg structure and a  * pointer to a buffer to place the completed DNS message.  note we're  * assuming the buffer points to enough space.  note that this is  * important, we do not attempt to do the DNS message compression scheme. * so if you've got a lot of resource records you could overflow even * though you may not if the compression was used and we're not checking. * * return:  number of bytes for the message or *         -1 to indicate an error condition. */intcreate_dns_message(U8 *dnsbuffer, DnsMsg *dmsg){    int          nused, i, nbytes = 0;    DnsQuestion  *dq = NULL;    DnsRRec      *rrec = NULL;    U16          *sptr = (U16 *)dnsbuffer;    U8           *cptr = NULL;    /*     * assign the values for the DNS header, this part is word aligned     * but the rest of the message is not.     */    *sptr = htons(dmsg->m_dnshdr.id);   sptr++;    *sptr = htons(dmsg->m_dnshdr.flags);   sptr++;    *sptr = htons(dmsg->m_dnshdr.nquest);   sptr++;    *sptr = htons(dmsg->m_dnshdr.nansrr);   sptr++;    *sptr = htons(dmsg->m_dnshdr.nauthrr);   sptr++;    *sptr = htons(dmsg->m_dnshdr.naddrr);   sptr++;    cptr = (U8 *)sptr;    nbytes = sizeof(DnsHdr);    /* install the questions */    i = 0;    dq = dmsg->m_questions;    while ( dq != NULL && i++ < dmsg->m_dnshdr.nquest ) {        if ((nused = install_dns_question(cptr, dq)) < 0) {	    dprintf("%C error installing question\n");	    return -1;	}	cptr += nused;	nbytes += nused;	dq = dq->q_next;    }    /* install the answers */    i = 0;    rrec = dmsg->m_answers;    while ( rrec != NULL && i++ < dmsg->m_dnshdr.nansrr ) {        if ((nused = install_dns_rrecord(cptr, rrec)) < 0) {	    dprintf("%C error installing answers\n");	    return -1;	}	cptr += nused;	nbytes += nused;	rrec = rrec->r_next;    }    /* install the authority records */    i = 0;    rrec = dmsg->m_authoritys;    while ( rrec != NULL && i++ < dmsg->m_dnshdr.nauthrr ) {        if ((nused = install_dns_rrecord(cptr, rrec)) < 0) {	    dprintf("%C error installing authoritys\n");	    return -1;	}	cptr += nused;	nbytes += nused;	rrec = rrec->r_next;    }    /* install additional records */    i = 0;    rrec = dmsg->m_additionals;    while ( rrec != NULL && i++ < dmsg->m_dnshdr.naddrr ) {        if ((nused = install_dns_rrecord(cptr, rrec)) < 0) {	    dprintf("%C error installing additionals\n");	    return -1;	}	cptr += nused;	nbytes += nused;	rrec = rrec->r_next;    }    return nbytes;}   /* end create_dns_message() *//* * parse_dns_message() * * this routine will parse the DNS message.  keep in mind that currently * we only handle a few resource record types.  we take the DNS message * and retrieve the header information, including the flags.  we parse * out the questions and all the resource records. * * dnsmsg  - is the DNS message * dsize   - is the number of bytes in the DNS message * dmsg    - is the parsed message, we allocate the needed space for the *           lists. * * return:  number of bytes used during the parsing, or *         -1 to indicate an error condition */intparse_dns_message(U8 *dnsmsg, int dsize, DnsMsg *dmsg){    DnsQuestion  *dq = NULL;    DnsRRec      *rrec = NULL;    int          i, nread, tread, bcnt = dsize;    U8           *cptr;    U16          *sptr;    UNUSED(dsize);    /*      * first get the header stuff.  note we can assume the header part     * is aligned so the casts are okay.  can't make this assumption     * elsewhere though.     */    if ( dsize < (int )sizeof(DnsHdr) ) {        dprintf("%C DNS message size less than DNS header\n");        dprintf("header size %d, packet size %d\n", sizeof(DnsHdr), dsize);	return -1;    }    memset(dmsg, 0, sizeof(DnsMsg));    sptr = (U16 *)dnsmsg;    dmsg->m_dnshdr.id = ntohs(*sptr);  sptr++;    dmsg->m_dnshdr.flags = ntohs(*sptr);  sptr++;    dmsg->m_dnshdr.nquest = ntohs(*sptr);  sptr++;    dmsg->m_dnshdr.nansrr = ntohs(*sptr);  sptr++;    dmsg->m_dnshdr.nauthrr = ntohs(*sptr);  sptr++;    dmsg->m_dnshdr.naddrr = ntohs(*sptr);  sptr++;    cptr = (U8 *)sptr;    bcnt -= sizeof(DnsHdr);    tread = sizeof(DnsHdr);    /* allocate and parse the DNS questions and the resource records */    if ( dmsg->m_dnshdr.nquest > 0 ) {	if ((dmsg->m_questions = dns_get_question()) == NULL) {            dprintf("%C allocation failure for DnsQuestions\n");#ifdef DNS_DEBUG	    print_resource_pool();#endif            return -1;	}	dq = dmsg->m_questions;	if ((nread = parse_dns_question(dnsmsg, cptr, dq, bcnt)) < 0) {	    dprintf("%C error parsing DNS question\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	cptr += nread;	bcnt -= nread;	tread += nread;	if ( tread > dsize ) {	    dprintf("%C parse error on DNS packet not enough space left\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	for ( i = 1; i < dmsg->m_dnshdr.nquest; i++ ) {	    if ((dq->q_next = dns_get_question()) == NULL) {	        dprintf("%C allocation failure for DnsQuestion\n");#ifdef DNS_DEBUG		print_resource_pool();#endif		dnsmsg_cleanup(dmsg);		return -1;	    }	    if ((nread = parse_dns_question(dnsmsg, cptr, dq->q_next, bcnt)) < 0) {		dprintf("%C error parsing DNS question\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    cptr += nread;	    bcnt -= nread;	    tread += nread;	    if ( tread > dsize ) {		dprintf("%C parse error on DNS packet out of space parsing questions\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    dq = dq->q_next;	}    }    /* answer RRs */    if ( dmsg->m_dnshdr.nansrr > 0 ) {        if ((dmsg->m_answers = dns_get_RR()) == NULL) {	    dprintf("%C error allocating new answer resource record\n");#ifdef DNS_DEBUG	    print_resource_pool();#endif	    dnsmsg_cleanup(dmsg);	    return -1;	}	rrec = dmsg->m_answers;	if ((nread = parse_dns_record(dnsmsg, cptr, rrec, bcnt)) < 0) {	    dprintf("%C error parsing answer record\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	cptr += nread;	bcnt -= nread;	tread += nread;	if ( tread > dsize ) {	    dprintf("%C parse error on DNS packet, not enough space for RR\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	for ( i = 1; i < dmsg->m_dnshdr.nansrr; i++ ) {	    if ((rrec->r_next = dns_get_RR()) == NULL) {		dprintf("%C could not allocate space for next answer RR\n");#ifdef DNS_DEBUG		print_resource_pool();#endif		dnsmsg_cleanup(dmsg);		return -1;	    }	    if ((nread = parse_dns_record(dnsmsg, cptr, rrec->r_next, bcnt)) < 0) {	        dprintf("%C error parsing answer record\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    cptr += nread;	    bcnt -= nread;	    tread += nread;	    if ( tread > dsize ) {		dprintf("%C parse error on DNS packet, not enough space for answer RR\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    rrec = rrec->r_next;	}    }    /* authority or NS records */    if ( dmsg->m_dnshdr.nauthrr > 0 ) {	if ((dmsg->m_authoritys = dns_get_RR()) == NULL) {	    dprintf("%C error allocating NS record\n");#ifdef DNS_DEBUG	    print_resource_pool();#endif	    dnsmsg_cleanup(dmsg);	    return -1;	}	rrec = dmsg->m_authoritys;	if ((nread = parse_dns_record(dnsmsg, cptr, rrec, bcnt)) < 0) {	    dprintf("%C error parsing NS record\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	cptr += nread;	bcnt -= nread;	tread += nread;	if ( tread > dsize ) {	    dprintf("%C parse error on DNS packet, not enough space for NS RR\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	for ( i = 1; i < dmsg->m_dnshdr.nauthrr; i++ ) {	    if ((rrec->r_next = dns_get_RR()) == NULL) {		dprintf("%C error allocating next NS record\n");#ifdef DNS_DEBUG		print_resource_pool();#endif		dnsmsg_cleanup(dmsg);		return -1;	    }	    if ((nread = parse_dns_record(dnsmsg, cptr, rrec->r_next, bcnt)) < 0) {		dprintf("%C error parsing NS record\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    cptr += nread;	    bcnt -= nread;	    tread += nread;	    if ( tread > dsize ) {		dprintf("%C parse error on DNS packet, not enough space fo next NS RR\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    rrec = rrec->r_next;	}    }    /* get any additional records */    if ( dmsg->m_dnshdr.naddrr > 0 ) {	if ((dmsg->m_additionals = dns_get_RR()) == NULL) {	    dprintf("%C error allocating additional record\n");#ifdef DNS_DEBUG	    print_resource_pool();#endif	    dnsmsg_cleanup(dmsg);	    return -1;	}	rrec = dmsg->m_additionals;	if ((nread = parse_dns_record(dnsmsg, cptr, rrec, bcnt)) < 0) {	    dprintf("%C error parsing additional record\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	cptr += nread;	bcnt -= nread;	tread += nread;	if ( tread > dsize ) {	    dprintf("%C parse error on DNS packet, no space for additional RR\n");	    dnsmsg_cleanup(dmsg);	    return -1;	}	for ( i = 1; i < dmsg->m_dnshdr.naddrr; i++ ) {	    if ((rrec->r_next = dns_get_RR()) == NULL) {		dprintf("%C error allocating next additional record\n");#ifdef DNS_DEBUG		print_resource_pool();#endif		dnsmsg_cleanup(dmsg);		return -1;	    }	    if ((nread = parse_dns_record(dnsmsg, cptr, rrec->r_next, bcnt)) < 0) {		dprintf("%C error parsing next additional record\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    cptr += nread;	    bcnt -= nread;	    tread += nread;	    if ( tread > dsize ) {		dprintf("%C parse error on DNS packet, no space for next additional RR\n");		dnsmsg_cleanup(dmsg);		return -1;	    }	    rrec = rrec->r_next;	}    }    return tread;}   /* end parse_dns_message() *//* * install_dns_question() * * this routine will take a pointer to the current location in the  * DNS message and a pointer to the DnsQuestion structure to fill in. * * return:  number of bytes used, or *         -1 will indicate an error. */static intinstall_dns_question(U8 *cptr, DnsQuestion *dquest){    int   nbytes;    U8    nbuf[NAMEMAX+1];    U16   sval;             /* short value, used for 2 byte conversion */    /* copy the domain name in.  the name comes in as a string, need to      * convert it to proper format.     */        if ((nbytes = create_dname(dquest->q_name, nbuf)) < 0) {        dprintf("%C: domain name %s not within DNS limits\n", dquest->q_name);	return -1;    }    memcpy(cptr, nbuf, nbytes);    cptr += nbytes;    /*     * now copy in the type and class values.  note that we can't     * assume stuff is word aligned so we do a memcpy here      */    sval = htons(dquest->q_type);    memcpy(cptr, &sval, sizeof(sval));    cptr += sizeof(sval);    nbytes += sizeof(sval);    sval = htons(dquest->q_class);    memcpy(cptr, &sval, sizeof(sval));    nbytes += sizeof(sval);    return nbytes;}   /* end install_dns_question() *//* * parse_dns_question() * * this routine will parse a question from the DNS message.  it will * parse out the domain name and the query type and class.  the  * information is returned in the DnsQuestion structure. * * return:  number of bytes used to parse the question, or *         -1 to indicate an error. */static intparse_dns_question(U8 *dnsmsg, U8 *data, DnsQuestion *dq, int bremain){    int  nread, bcnt = bremain;  /* byte count, the remaining bytes in the packet */    U16  sval;                   /* 2 byte value used for conversion */    /* the first thing in the question is the domain name */    memset(dq->q_name, 0, NAMEMAX+1);    if ((nread = get_dname(dnsmsg, data, dq->q_name)) < 0) {        dprintf("error retrieving domain name\n");	return -1;    }    data += nread;    bcnt -= nread;    if ( bcnt < (int )(2 * sizeof(sval)) ) {        dprintf("%C DNS question parsing error\n");	return -1;    }    /* next are two two byte values, the query type and query class */    memcpy(&sval, data, sizeof(sval));    dq->q_type = ntohs(sval);    data += sizeof(sval);    memcpy(&sval, data, sizeof(sval));    dq->q_class = ntohs(sval);

⌨️ 快捷键说明

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