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

📄 dns_client_packet.c

📁 DNS 的实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * data, points to the start of the label.  the first byte is a count, or * the number, of bytes for the label.  the parameter, label, is assumed to * point to enough space to hold the entire label.  the label will end with * a dot '.' and is a null terminated string on return.  the only error  * checking is to verify that the count is not larger than the max label * size. * * NOTE:  this routine does not check for the compression indication in the *        count byte, it is expected that has already been done. * * return:  number of bytes used from data.  this includes the count byte. *         -1 indicates an error. */static intget_label(U8 *data, U8 *label){    U8  cnt;    cnt = *data;    if ( cnt > LABELMAX )        return -1;    memcpy(label, ++data, cnt);    label += cnt;    *label++ = DOT;    *label = '\0';    return cnt + 1;}   /* end get_label() *//* * dnsmsg_cleanup() * * this routine will free the DNS questions and DNS resource records and their * data.  note the routine does not depend on the header being set, that is it * doesn't expect the number of records to be set, and just checks for NULL  * pointers. */voiddnsmsg_cleanup(DnsMsg *dnsmsg){    DnsQuestion  *dq, *tdq;    DNSC_DEBUG("entry\n");    if ( dnsmsg->m_questions != NULL ) {        dq = dnsmsg->m_questions;        while ( dq != NULL ) {            tdq = dq->q_next;            dns_free_question(dq);            dq = tdq;        }    }    dns_free_rrlist(dnsmsg->m_answers);        /* dns_free_rrlist() checks for NULL */    dns_free_rrlist(dnsmsg->m_authoritys);    dns_free_rrlist(dnsmsg->m_additionals);}   /* end dnsmsg_cleanup() *//* * dns_free_rrlist() * * this utility routine will go through the RR list.  it frees the data section * by assuming if the type is address (A) free it using dns_ip_free() otherwise use * dns_name_free(). */voiddns_free_rrlist(DnsRRec *list){    DnsRRec   *rr, *trr;    DNSC_DEBUG("entry\n");    rr = list;    while ( rr != NULL ) {        trr = rr->r_next;	if ( rr->r_data != NULL ) {	    if ( rr->r_type == QT_A || rr->r_type == QT_AAAA ||                  rr->r_type == QT_A6)        {            DNSC_DEBUG("free IP address\n");            dns_ip_free(rr->r_data);        }	    else if ( rr->r_type == QT_SOA )        {            DNSC_DEBUG("free SOA\n");	        dns_free_SOA((SOArec *)rr->r_data);        }	    else        {            DNSC_DEBUG("free name\n");            dns_name_free(rr->r_data);        }	}	dns_free_RR(rr);	rr = trr;    }}   /* end dns_free_rrlist() *//* * create_dname() * * this routine takes a null terminated string representing a domain name in  * the format "label.label.label." NOTE the trailing dot which MUST be there. * we convert the string into a formatted buffer which can be used in the DNS  * message, see get_dname() comments for what it would look like.  we do not * use the compression scheme, RFC 1035 section 4.1.4.  we do verify the length   * of the string and that the individual labels are within limits.  * * return: length of the formatted buffer, or *        -1 to indicate an error condition. */static intcreate_dname(char *domain, char *buffer){    char  *ptr, *pdup;    char  dup[NAMEMAX+1];    char  num;    int   i, used = 0;    if ( strlen(domain) > NAMEMAX ) {        dprintf("%C: domain name %s too long\n", domain);        return -1;    }    strcpy(dup, domain);    pdup = dup;    while ((ptr = strchr(pdup, DOT)) != NULL) {        *ptr++ = '\0';        if ((num = strlen(pdup)) > LABELMAX) {            dprintf("%C: domain name label %s too long\n", pdup);            return -1;        }        *buffer++ = num;        used += num + 1;        for ( i = 0; i < num; i++ )            *buffer++ = *pdup++;        pdup = ptr;    }    *buffer = 0;    return used + 1;}   /* end create_dname() */#ifdef DNS_DEBUG typedef  void (*func)(DnsRRec *);func  dns_tfunc[40] = {                           NULL,			 dns_ipaddr,         /* 1 */			 dns_string,			 dns_default,			 dns_default,			 dns_string,         /* 5 */			 dns_soa,			 dns_default,			 dns_default,			 dns_default,			 dns_default,        /* 10 */			 dns_default,			 dns_string,			 dns_default,			 dns_string,			 dns_string,         /* 15 */			 dns_default,			 dns_default,			 dns_default,			 dns_default,			 dns_default,        /* 20 */			 dns_default,			 dns_default,			 dns_default,			 dns_default,			 dns_default,        /* 25 */			 dns_default,			 dns_default,			 dns_ipaddr, 			 dns_default,			 dns_default,        /* 30 */			 dns_default,			 dns_default,			 dns_default,			 dns_default,			 dns_default,        /* 35 */			 dns_default,			 dns_default,			 dns_default,			 dns_default         /* 39 */		     };const char  *dns_type[40] = {                         "",           /* nothing */			 "A",          /* 1, a host address */			 "NS",         /* 2, an authoritative name server */			 "MD",         /* 3, obsolete */			 "MF",         /* 4, obsolete */			 "CNAME",      /* 5, the canonical name for an alias */			 "SOA",        /* 6, marks the start of a zone of authority */			 "MB",         /* 7, experimental */			 "MG",         /* 8, experimental */			 "MR",         /* 9, experimental */			 "NULL",       /* 10, experimental */			 "WKS",        /* 11, well known service description */			 "PTR",        /* 12, domain name pointer */			 "HINFO",      /* 13, host information */			 "MINFO",      /* 14, mailbox or mail list information */			 "MX",         /* 15, mail exchange */			 "TXT",        /* 16, text strings */                         "RP",         /* 17, for Responsible Person */                         "AFSDB",      /* 18, for AFS Data Base location */                         "X25",        /* 19, for X.25 PSDN address */                         "ISDN",       /* 20, for ISDN address */                         "RT",         /* 21, for Route Through */                         "NSAP",       /* 22, for NSAP address, NSAP style A record */                         "NSAP-PTR",   /* 23, NSAP PTR */                         "SIG",        /* 24, for security signature */                         "KEY",        /* 25, for security key */                         "PX",         /* 26, X.400 mail mapping information */                         "GPOS",       /* 27, Geographical Position */                         "AAAA",       /* 28, IP6 Address */                         "LOC",        /* 29, Location Information */                         "NXT",        /* 30, Next Domain */                         "EID",        /* 31, Endpoint Identifier */                         "NIMLOC",     /* 32, Nimrod Locator */                         "SRV",        /* 33, Server Selection */                         "ATMA",       /* 34, ATM Address */                         "NAPTR",      /* 35, Naming Authority Pointer */                         "KX",         /* 36, Key Exchanger */                         "CERT",       /* 37, CERT */                         "A6"          /* 38, A6 */                      };const char *dns_class[5] = {                         "",           /* nothing */			 "IN",         /* 1, Internet */			 "CS",         /* 2, obsolete */			 "CH",         /* 3, chaos class */			 "HS"          /* 4, Hesiod */		      };#define RR_FMT   "%s  %d  %s    %s   %s"/* * print_dns_header() * * this will take a pointer to a parsed dns header and print out the  * values without interpretation. */voidprint_dns_header(DnsHdr *dhdr){    dprintf("DNS header: \n");    dprintf("message id: %d\n", dhdr->id);    dprintf("flags in hex: 0x%X\n", dhdr->flags);    dprintf("number of questions: %d\n", dhdr->nquest);    dprintf("number of answer records: %d\n", dhdr->nansrr);    dprintf("number of NS records: %d\n", dhdr->nauthrr);    dprintf("number of additional records: %d\n", dhdr->naddrr);    dprintf("\n");}   /* end print_dns_header() *//* * print_dns_message() * * this routine will print out a DNS message represented by a DnsMsg  * structure. */voidprint_dns_message(DnsMsg *dmsg){    DnsQuestion  *dq;    DnsRRec      *rr;    U16          flag;    dprintf("DNS header:\n");    dprintf("message id: %d\n", dmsg->m_dnshdr.id);    dprintf("flags in hex: 0x%X\n", dmsg->m_dnshdr.flags);    dprintf("interpreting the flags:\n");    flag = dmsg->m_dnshdr.flags;    if ((flag & DNS_QR) == DNS_QR)        dprintf("message is a response\n");    else        dprintf("message is a query\n");    if ((flag & DNS_OPCODE) == DNS_STDQUERY)        dprintf("message is a standard query\n");    else if ((flag & DNS_OPCODE) == DNS_INVQUERY)        dprintf("message is an inverse query\n");    else if ((flag & DNS_OPCODE) == DNS_STATUS)        dprintf("message is server status requesst\n");    if ((flag & DNS_AUTHANS) == DNS_AUTHANS)        dprintf("message is an authoritive answer\n");    else        dprintf("message is not an authoritive answer\n");    if ((flag & DNS_TRUNC) == DNS_TRUNC)        dprintf("message is truncated\n");    else        dprintf("message not truncated\n");    if ((flag & DNS_RECURDD) == DNS_RECURDD)        dprintf("message asked for recursion\n");    else        dprintf("message did not ask for recursion\n");    if ((flag & DNS_RECURAV) == DNS_RECURAV)        dprintf("message indicates recursion available from server\n");    else        dprintf("message does not indicate recursion available\n");    if ((flag & DNS_RCODE) == DNS_NOERROR)        dprintf("no errors\n");    else if ((flag & DNS_RCODE) == DNS_NAMEERR)        dprintf("domain does not exist\n");    /* print questions */    dprintf("questions\n");    dq = dmsg->m_questions;    while ( dq != NULL ) {        print_question(dq);	dq = dq->q_next;    }    dprintf("answers\n");    rr = dmsg->m_answers;    while ( rr != NULL ) {        print_resource_record(rr);	rr = rr->r_next;    }    dprintf("authority records\n");    rr = dmsg->m_authoritys;    while ( rr != NULL ) {        print_resource_record(rr);	rr = rr->r_next;    }    dprintf("additional records\n");    rr = dmsg->m_additionals;    while ( rr != NULL ) {        print_resource_record(rr);	rr = rr->r_next;    }    dprintf("\n");}   /* end print_dns_message() */    /* * print_resource_record() * * this routine takes a pointer to a DnsRRec structure and prints out the * information to standard out, stdout.  the routine will interpret the  * rdata part of the RR if its a type the routine understands.  if not, * the routine will attempt to dump the data in hex. */voidprint_resource_record(DnsRRec *RR){    char *dname, *type, *class;        dname = RR->r_dname;    type = (char *)dns_type[RR->r_type];    class = (char *)dns_class[RR->r_class];    dprintf("%s  %d  %s    %s  ", dname, RR->r_ttl, type, class);    (dns_tfunc[RR->r_type])(RR);    dprintf("\n");}   /* end print_resource_record() *//* * print_question() */voidprint_question(DnsQuestion *dquestion){    char *dname, *type, *class;    dname = dquestion->q_name;    type = (char *)dns_type[dquestion->q_type];    class = (char *)dns_class[dquestion->q_class];    dprintf("%s   %s   %s\n", dname, type, class);}   /* end print_question() *//* * dns_string() */voiddns_string(DnsRRec *RR){    dprintf("%s", RR->r_data);}   /* end dns_string() *//* * dns_ipaddr() */voiddns_ipaddr(DnsRRec *RR){    char tmp[INET6_ADDRSTRLEN];    /* prints A or AAAA records */    switch (RR->r_datalen)    {        case IPSIZE:            inet_ntop(AF_INET, RR->r_data, tmp, sizeof(tmp));            dprintf("%s", tmp);            break;        case IP6SIZE:            inet_ntop(AF_INET6, RR->r_data, tmp, sizeof(tmp));            dprintf("%s", tmp);            break;        default:            dprintf("dns_ipaddr: weird data size: %d\n", RR->r_datalen);            break;    }}   /* end dns_ipaddr() *//* * dns_soa() * * this is ugly, but its only for debugging purposes.  the format is similiar to * what would be printed out with host(1) with the -v option. */voiddns_soa(DnsRRec *RR){    SOArec  *srec;    srec = (SOArec *)RR->r_data;    dprintf("%s %s(\n", srec->s_mname, srec->s_rname);    dprintf("\t\t\t%u  serial (version)\n", srec->s_serial);    dprintf("\t\t\t%u  refresh period\n", srec->s_refresh);    dprintf("\t\t\t%u  retry refresh this often\n", srec->s_retry);    dprintf("\t\t\t%u  expiration period\n", srec->s_expire);    dprintf("\t\t\t%u  minimum TTL)",  srec->s_minimum);}   /* end dns_soa() *//* * dns_default() * * here we don't know what the type may be. so, we just turn the thing into a * string of hex data.  each byte will be 2 characters and a space.  we currently * will only allocate up to 255 bytes for the data part of an RR.  so, 3 * 255 * = 765 and then we need the NULL. */voiddns_default(DnsRRec *RR){    int   i;    for ( i = 0; i < RR->r_datalen; i++ )         dprintf("%X ", RR->r_data[i]);}   /* end dns_default() */#endif  /* DNS_DEBUG */

⌨️ 快捷键说明

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