📄 dns_client_util6.c
字号:
/* * DNS Resolver * IPv6 Resolver Utility Routines * * Author: Pavel A. Bolokhov <Pavel.Bolokhov@oktet.ru> * * External API: * dns_fmt_ip6_answer() * dns_fmt_cname6_answer() * dns_fmt_cache6_answer() * dns_fmt_ptr6_answer() */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include "messages.h"#include "dns_client.h"#include "dns_client_query.h"#include "dns_client_util6.h"#include "dns_client_resource.h"/* dns_fmt_ip6_answer -- * Puts the answer with address into message. * * PARAMETERS * query - query state structure * dnsmsg - dns message with results * * RETURNS: * 0 - for success, or * -1 - for an error condition. */intdns_fmt_ip6_answer(IN QueryState *query, IN DnsMsg *dnsmsg){ struct hostent *hent; DnsRRec *RR; int nanswers, i; MSG_D_DNS_GET_NODEBYNAME(dmsg, query->reply); DNSC_DEBUG("entry\n"); if ((hent = dns_alloc_struct_hostent()) == NULL) { dmsg->error = ENOMEM; DNSC_DEBUG("exit - dns_alloc_struct_hostent failed\n"); return -1; } if (strlen(query->cname) > 0) { if (dns_alloc_aliases(hent, 1) == NULL) { dmsg->error = ENOMEM; return -1; } if ((hent->h_aliases[0] = malloc(strlen(query->cname) + 1)) == NULL) { dns_freehostent(hent); dmsg->error = ENOMEM; return -1; } strcpy(hent->h_aliases[0], query->cname); } nanswers = find_num_match(query->domain, dnsmsg->m_answers, QT_AAAA) + find_num_match(query->domain, dnsmsg->m_answers, QT_A6); if (nanswers == 0) { DNSC_TRACE("unexpected format error no addresses for %s\n", query->domain);#ifdef DNS_DEBUG print_dns_message(dnsmsg);#endif dns_freehostent(hent); dmsg->error = ETRYAGAIN; return -1; } if (dns_alloc_hostname(hent, query->domain) == NULL) { dmsg->error = ENOMEM; DNSC_DEBUG("exit - dns_alloc_hostname failed\n"); return -1; } hent->h_addr_list = dns_alloc_addrlist(hent, nanswers, AF_INET6); if (hent->h_addr_list == NULL) { dmsg->error = ENOMEM; DNSC_DEBUG("exit - dns_alloc_addrlist failed\n"); return -1; } hent->h_addrtype = AF_INET6; hent->h_length = sizeof(struct in6_addr); RR = find_match_rrecord(query->domain, dnsmsg->m_answers, QT_AAAA); for (i = 0; i < nanswers && RR != NULL; i++) { memcpy(hent->h_addr_list[i], RR->r_data, sizeof(struct in6_addr)); RR = find_match_rrecord(query->domain, RR->r_next, QT_AAAA); } RR = find_match_rrecord(query->domain, dnsmsg->m_answers, QT_A6); for (; i < nanswers && RR != NULL; i++) { memcpy(hent->h_addr_list[i], RR->r_data, sizeof(struct in6_addr)); RR = find_match_rrecord(query->domain, RR->r_next, QT_A6); } /* * If we've not filled all the addresses, release the reserved * by 'dns_alloc_addrlist()' space */ if (i < nanswers) { int k; for (k = i; k < nanswers; k++) { free(hent->h_addr_list[k]); hent->h_addr_list[k] = NULL; } } dmsg->hent = hent; dmsg->error = ESUCCESS; DNSC_DEBUG("exit - success\n"); return 0;} /* dns_fmt_ip6_answer *//* dns_fmt_cname6_answer -- * This one is a little more complicated than the IP and PTR formatters. * Here it could be the case that the query already had known it was * looking for a CNAME which is indicated by a query type of ac_type or * the query received a DNS response and it told us then which is * indicated by a query type of aaaa_type; we handle both cases. * Then we need to locate the AAAA records for the CNAME. Note that it * is unlikely that there would be AAAA records for the CNAME in both * the answer records and additional records both we handle that situation. * We get up to the limit indicated by the user. * * PARAMETERS: * query - query state structure * dnsmsg - dns message with results * * RETURNS: * 0 - for success, and * -1 - indicates an error condition. */intdns_fmt_cname6_answer(IN QueryState *query, IN DnsMsg *dnsmsg){ struct hostent *hent; DnsRRec *RR; int cnt; int num_answ; MSG_D_DNS_GET_NODEBYNAME(dmsg, query->reply); DNSC_DEBUG("entry\n"); if ((hent = dns_alloc_struct_hostent()) == NULL) { dmsg->error = ENOMEM; DNSC_DEBUG("exit - dns_alloc_struct_hostent failed\n"); return -1; } hent->h_addrtype = AF_INET6; hent->h_length = sizeof(struct in6_addr); switch(query->qtype) { case a6_type: case aaaa_type: if ((RR = find_match_rrecord(query->domain, dnsmsg->m_answers, QT_CNAME)) == NULL) { DNSC_TRACE("unexpect format error, no CNAME record for %s\n", query->domain); #ifdef DNS_DEBUG print_dns_message(dnsmsg); #endif dmsg->error = ETRYAGAIN; return -1; } if (dns_alloc_aliases(hent, 1) == NULL) { dmsg->error = ENOMEM; return -1; } if ((hent->h_aliases[0] = malloc(strlen(query->domain) + 1)) == NULL) { dns_freehostent(hent); dmsg->error = ENOMEM; return -1; } strcpy(hent->h_aliases[0], query->domain); if (dns_alloc_hostname(hent, RR->r_data) == NULL) { dmsg->error = ENOMEM; return -1; } break; case ac_type: if (dns_alloc_hostname(hent, query->domain) == NULL) { dmsg->error = ENOMEM; return -1; } if (dns_alloc_aliases(hent, 1) == NULL) { dmsg->error = ENOMEM; return -1; } if ((hent->h_aliases[0] = malloc(strlen(query->cname) + 1)) == NULL) { dns_freehostent(hent); dmsg->error = ENOMEM; return -1; } strcpy(hent->h_aliases[0], query->cname); break; default: DNSC_TRACE("unrecognized query type: %d\n", query->qtype); dmsg->error = ETRYAGAIN; return -1; } cnt = 0; num_answ = find_num_match(hent->h_name, dnsmsg->m_answers, QT_AAAA) + find_num_match(hent->h_name, dnsmsg->m_answers, QT_A6) + find_num_match(hent->h_name, dnsmsg->m_additionals, QT_AAAA) + find_num_match(hent->h_name, dnsmsg->m_additionals, QT_A6); /* Allocate memory for addresses */ if (dns_alloc_addrlist(hent, num_answ, AF_INET6) == NULL) { dmsg->error = ENOMEM; return -1; } RR = find_match_rrecord(hent->h_name, dnsmsg->m_answers, QT_AAAA); while ( RR != NULL && cnt < num_answ ) { memcpy(hent->h_addr_list[cnt++], RR->r_data, sizeof(struct in6_addr)); RR = find_match_rrecord(hent->h_name, RR->r_next, QT_AAAA); } RR = find_match_rrecord(hent->h_name, dnsmsg->m_answers, QT_A6); while ( RR != NULL && cnt < num_answ ) { memcpy(hent->h_addr_list[cnt++], RR->r_data, sizeof(struct in6_addr)); RR = find_match_rrecord(hent->h_name, RR->r_next, QT_A6); } RR = find_match_rrecord(hent->h_name, dnsmsg->m_additionals, QT_AAAA); while ( RR != NULL && cnt < num_answ ) { memcpy(hent->h_addr_list[cnt++], RR->r_data, sizeof(struct in6_addr)); RR = find_match_rrecord(hent->h_name, RR->r_next, QT_AAAA); } RR = find_match_rrecord(hent->h_name, dnsmsg->m_additionals, QT_A6); while ( RR != NULL && cnt < num_answ ) { memcpy(hent->h_addr_list[cnt++], RR->r_data, sizeof(struct in6_addr)); RR = find_match_rrecord(hent->h_name, RR->r_next, QT_A6); } /* * If we've not filled all the addresses, release the reserved * by 'dns_alloc_addrlist()' space */ if (cnt < num_answ) { int k; for (k = cnt; k < num_answ; k++) { free(hent->h_addr_list[k]); hent->h_addr_list[k] = NULL; } } dmsg->hent = hent; dmsg->error = ESUCCESS; DNSC_DEBUG("exit - success\n"); return 0;} /* dns_fmt_cname6_answer *//* dns_fmt_cache6_answer -- * This routine is called when the cache returned a result and we don't * know if it is just the addresses or a CNAME. The results are expected * to have the the AAAA records for the CNAME if that is there. * * PARAMETERS: * query - query state structure * dnsmsg - dns message with results * * RETURNS: * 0 - for success, or * -1 - to incidate an error condition. */intdns_fmt_cache6_answer(IN QueryState *query, IN DnsMsg *dnsmsg){ DnsRRec *RR = dnsmsg->m_answers; char tmpName[NAMEMAX+1]; DNSC_DEBUG("entry\n"); /* * Note that all the names coming out of the cache are in all lower * case. So we have to convert the domain name in the query to lower * case so that the search for matching records in the formatting * routines will work. */ strcpy(tmpName, query->domain); lowercase_copy(query->domain, tmpName); if (RR->r_type == QT_CNAME) { query->qtype = aaaa_type; return dns_fmt_cname6_answer(query, dnsmsg); } DNSC_DEBUG("exit - call dns_fmt_ip6_answer\n"); return dns_fmt_ip6_answer(query, dnsmsg);} /* dns_fmt_cache6_answer *//* dns_fmt_ptr6_answer -- * This routine is called to format the response to a PTR query. * It should only be called for PTR queries since it makes an * assumption on the message type. * * PARAMETERS: * query - query state structure * dnsmsg - dns message with results * * RETURNS: * 0 - for success, or * -1 - to incidate an error condition. */intdns_fmt_ptr6_answer(IN QueryState *query, IN DnsMsg *dnsmsg){ DnsRRec *RR; struct hostent *hent; struct sockaddr_storage tmp; MSG_D_DNS_GET_HOSTBYADDR6(dmsg, query->reply); DNSC_DEBUG("entry\n"); if ((hent = dns_alloc_struct_hostent()) == NULL) { dmsg->error = ENOMEM; DNSC_DEBUG("exit - dns_alloc_struct_hostent failed\n"); return -1; } hent->h_addrtype = AF_INET6; hent->h_length = sizeof(struct in6_addr); RR = find_match_rrecord(query->domain, dnsmsg->m_answers, QT_PTR); if (RR == NULL) {#ifdef DNS_DEBUG print_dns_message(dnsmsg);#endif dmsg->error = ETRYAGAIN; dns_freehostent(hent); DNSC_DEBUG("exit - unexpected formating error, no pointer " "answer for %s\n", query->domain); return -1; } if (dns_alloc_hostname(hent, RR->r_data) == NULL) { dmsg->error = ENOMEM; DNSC_DEBUG("exit - dns_alloc_hostname failed\n"); return -1; } if (dns_alloc_addrlist(hent, 1, AF_INET6) == NULL) { dmsg->error = ENOMEM; DNSC_DEBUG("exit - dns_alloc_addrlist failed\n"); return -1; } /* * All our macros and functions assume we submit sockaddr_storage * structure, so we use this even though we know here we need * struct sockaddr_in6 only. */ convert_addr_arpa(query->domain, &tmp); memcpy(hent->h_addr_list[0], &((struct sockaddr_in6 *)&tmp)->sin6_addr, sizeof(struct in6_addr)); dmsg->hent = hent; dmsg->error = ESUCCESS; DNSC_DEBUG("exit - success\n"); return 0;} /* dns_fmt_ptr6_answer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -