📄 dns_client_packet.c
字号:
* 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 + -