📄 dns_client_reply.c
字号:
find_ns_record(QueryState *qstate, Dcmp *domain, DnsMsg *dmsg){ DnsRRec *RR; Dcmp ns; DNSC_DEBUG("entry\n"); RR = dmsg->m_answers; while ( RR != NULL && RR->r_type == QT_NS ) { ns.dname = RR->r_data; ns.dparts = count_domain_parts(ns.dname); if ( validate_domain(domain, &ns) == 0 ) { if ( find_replaceable_ns(qstate, domain, &ns) >= 0 ) return RR; } RR = RR->r_next; } RR = dmsg->m_authoritys; while ( RR != NULL && RR->r_type == QT_NS ) { ns.dname = RR->r_data; ns.dparts = count_domain_parts(ns.dname); if ( validate_domain(domain, &ns) == 0 ) { if ( find_replaceable_ns(qstate, domain, &ns) >= 0 ) return RR; } RR = RR->r_next; } return NULL;} /* end find_ns_record() */#ifdef DNS_HAVE_IP6STACK/* * ns6_reply -- * This routine called when an internal query results are returned. * * PARAMETERS * query - query state structure * * RETURNS * n/a */static voidns6_reply(IN QueryState *query){ struct hostent *hent; nslook_t *hp; int index; Dcmp domain; Dcmp ns; Qinfo_t qInfo; MSG_D_DNS_GET_NODEBYNAME(dmsg, query->nxquery); DNSC_DEBUG("entry\n"); hent = dmsg->hent; if (ESUCCESS == dmsg->error) { domain.dname = query->domain; domain.dparts = count_domain_parts(query->domain); ns.dname = (char *)hent->h_name; ns.dparts = count_domain_parts(ns.dname); if ((index = find_replaceable_ns(query, &domain, &ns)) >= 0) { if (hent->h_addr_list && hent->h_addr_list[0]) { data2sock(&query->ns_addrs[index].ns_addr, hent->h_addr_list[0]); strcpy(query->ns_addrs[index].ns_name, hent->h_name); query->ns_addrs[index].ns_try = 0; query->ns_addrs[index].ns_error = 0; query->ns_addrs[index].ns_recursion = 0; if ( index >= query->num_ns ) query->num_ns = index + 1; } } dns_hent_msg_free(query->nxquery); query->nxquery = NULL; dns_response_timeout(query); return; } dns_hent_msg_free(query->nxquery); query->nxquery = NULL; if ((hp = dns_hent_alloc()) == NULL) { dprintf("%C no free dns_hostent structures for internal NS query\n");#ifdef DNS_DEBUG print_resource_pool();#endif dns_response_timeout(query); return; } hp->hent.h_numaddrs = ENTADDRS; /* set for the max amount */ qInfo.qtype = addr_t; strcpy(hp->name, query->domain); qInfo.hostname = hp->name; qInfo.cache_flag = query->use_cache; qInfo.qcnt = query->nquerys; qInfo.amsg = &hp->amsg; qInfo.hptr = &hp->hent; if (start_new_query(&qInfo) < 0) { dprintf("%C; attempt to start internal NS query failed\n"); dns_hent_free(hp); dns_response_timeout(query); return; } query->nxquery = &hp->amsg; /* we use this to find this query later */ query->qstate = wf_nsaddr; query->dns_qreply = ns_reply; /* set the handler */ return;} /* end ns6_reply() */#endif/* * ns_reply() * * this routine called when an internal query results are returned. this routine * is set up for the waiting query when the internal query is kicked off. the * query was for the address of a name server suggested by another name server * in its response. if the query was successful we determine the name server in * our name server list that should be replaced by this new one. then, we replace * the name server. successful or not we free up the message and dns_hostent structure * once we're done with it. then we proceed as if a response had timed out. */voidns_reply(QueryState *query){ struct dns_hostent *hptr; int index; Dcmp domain; Dcmp ns; MSG_D_DNS_GET_ADDRBYNAME(dmsg, query->nxquery); DNSC_DEBUG("entry\n"); hptr = dmsg->hptr; if ( ESUCCESS == dmsg->error ) { domain.dname = query->domain; domain.dparts = count_domain_parts(query->domain); ns.dname = hptr->h_name; ns.dparts = count_domain_parts(ns.dname); if ((index = find_replaceable_ns(query, &domain, &ns)) >= 0) { long2sock(&query->ns_addrs[index].ns_addr, hptr->h_addr_list[0]); strcpy(query->ns_addrs[index].ns_name, hptr->h_name); query->ns_addrs[index].ns_try = 0; query->ns_addrs[index].ns_error = 0; query->ns_addrs[index].ns_recursion = 0; if ( index >= query->num_ns ) query->num_ns = index + 1; } } dns_hent_host_free(hptr); query->nxquery = NULL; dns_response_timeout(query);} /* end ns_reply() *//* cname6_reply -- * This routine is called when an internal query results are * returned for a CNAME query of a IPv6 request. * * PARAMETERS * query - query state structure * * RETURNS * N/A */static voidcname6_reply(QueryState *query){ struct hostent *result; struct hostent *hent; int i, numAddrs; MSG_D_DNS_GET_NODEBYNAME(rmsg, query->reply); MSG_D_DNS_GET_NODEBYNAME(nxmsg, query->nxquery); DNSC_DEBUG("entry\n"); result = nxmsg->hent; if (ESUCCESS == nxmsg->error) { do { ASSERT(rmsg->hent == NULL); if ((hent = dns_alloc_struct_hostent()) == NULL) break; hent->h_addrtype = AF_INET6; hent->h_length = sizeof(struct in6_addr); if (dns_alloc_hostname(hent, result->h_name) == NULL) break; /* copy aliases */ if (dns_alloc_aliases(hent, 1) == NULL) break; hent->h_aliases[0] = malloc(strlen(query->domain) + 1); if (hent->h_aliases[0] == NULL) { dns_freehostent(hent); break; } strcpy(hent->h_aliases[0], query->domain); /* * Now copy addresses. * First determine how many addresses there are */ numAddrs = 0; if (result->h_addr_list != NULL) { char **tmp; for (tmp = result->h_addr_list; *tmp; tmp++) numAddrs++; } if (dns_alloc_addrlist(hent, numAddrs, AF_INET6) == NULL) break; /* Copy all addresses */ for ( i = 0; i < numAddrs; i++ ) { memcpy(hent->h_addr_list[i], result->h_addr_list[i], sizeof(struct in6_addr)); } rmsg->hent = hent; rmsg->error = ESUCCESS; sendreply(query->reply); dns_hent_msg_free(query->nxquery); free_querystate(query); DNSC_DEBUG("exit - success\n"); return; } while (FALSE); /* We get here only if there were problems with malloc() */ rmsg->hent = NULL; rmsg->error = ENOMEM; } dns_hent_msg_free(query->nxquery); query->nxquery = NULL; dns_response_timeout(query); DNSC_DEBUG("exit - request failed\n");} /* cname6_reply *//* * cname_reply() * * this routine is called when an internal query results are returned for a CNAME * query. the routine is set up at the time the CNAME query is started. in this * case if the CNAME query was successful we just need to copy the information * to our dns_hostent structure for returning. we copy the domain name from the * starting query to the alias, since that's what the name server told us it was. * we copy as many IP addresses as we have or at least as many as was asked for. * we then just free up the resources and return the results to the caller. * * if the internal query was a failure, then there's something strange since * the other name server reply told us to use the CNAME. any other error indicates * a problem with either the name server or our domain imformation. we handle * this like we would a regular time out and hope the problem has cleared. if * not it'll be caught later. */voidcname_reply(QueryState *query){ struct dns_hostent *cn; struct dns_hostent *hptr; int i; MSG_D_DNS_GET_ADDRBYNAME(rmsg, query->reply); MSG_D_DNS_GET_ADDRBYNAME(nxmsg, query->nxquery); DNSC_DEBUG("entry\n"); cn = nxmsg->hptr; if ( ESUCCESS == nxmsg->error ) { hptr = rmsg->hptr; strcpy(hptr->h_name, cn->h_name); strcpy(hptr->h_alias, query->domain); hptr->h_numaddrs = MIN(hptr->h_numaddrs, cn->h_numaddrs); for ( i = 0; i < hptr->h_numaddrs; i++ ) hptr->h_addr_list[i] = cn->h_addr_list[i]; rmsg->error = ESUCCESS; sendreply(query->reply); free_querystate(query); dns_hent_host_free(cn); return; } dns_hent_host_free(cn); query->nxquery = NULL; dns_response_timeout(query);} /* end cname_reply() *//* * dns_response_XX_query() * * this routine handles responses for NAPTR/SRV queries. * Returns: None */voiddns_response_XX_query(QueryState *query){ DnsMsg *dnsmsg; DnsRRec *rr, *ns; int nrc; BOOL sendreply_flag = FALSE; DNSC_DEBUG("entry\n"); if ( verify_dns_response(query) < 0) { dprintf("%C DNS reply not valid for standard query\n");#ifdef DNS_DEBUG print_dns_message(&query->dnsreply); #endif dnsmsg_cleanup(&query->dnsreply); dns_response_timeout(query); return; } /* check that its not a negative return */ if ((nrc = dns_XX_negative_replycheck(query)) != ESUCCESS) { MSG_D_DNS_GET_RR(dmsg, query->reply); dmsg->error = nrc; sendreply(query->reply); dnsmsg_cleanup(&query->dnsreply); free_querystate(query);#ifdef DNS_DEBUG print_responding_server(query); print_dns_message(&query->dnsreply); #endif return; } /* If negative reply from server */ /* * the reply is okay and its not a negative reply, now see if we got the * answer we're looking for. if we got a NAPTR or SRV record then we did. so, format * the response, update the cache, send the reply, then clean up. */ dnsmsg = &query->dnsreply; if (query->qtype == naptr_type) { if (find_match_rrecord(query->domain, dnsmsg->m_answers, QT_NAPTR) != NULL) { sendreply_flag = TRUE; } } if (query->qtype == srv_type) { if (find_match_rrecord(query->domain, dnsmsg->m_answers, QT_SRV) != NULL) { sendreply_flag = TRUE; } } if (sendreply_flag == TRUE) { fmt_XX_answer(query, dnsmsg->m_answers); dns_update_XX_cache(dnsmsg); sendreply(query->reply); dnsmsg_cleanup(dnsmsg); free_querystate(query); return; } /* * if we didn't get the answer or weren't told our domain name was a CNAME * we see if there's a "delegation". that is did the server tell us to try * another server. if not we clean up and try the next server. we check * the answer section for the NS record, then if there are no answer records * and there are some NS records in the authority section, its a delegation, * see the referral response in section 2.2 of RFC 2308. */ rr = dnsmsg->m_answers; ns = dnsmsg->m_authoritys; if ( find_num_record(rr, QT_NS) > 0 || find_num_record(ns, QT_NS) > 0 ) return dns_ns_reply(query); dnsmsg_cleanup(&query->dnsreply); dns_response_timeout(query); DNSC_DEBUG("exit\n"); return;} /* end dns_response_XX_query() *//* * dns_XX_negative_replycheck() * * this routine checks whether the reply for a NAPTR/SRV query is * negative or not * * Returns: None */static intdns_XX_negative_replycheck(QueryState *query){ DnsMsg *dnsmsg; DNSC_DEBUG("entry\n"); /* name error replies will have the rcode section of the flags field * set to the name error. */ dnsmsg = &query->dnsreply; if ((dnsmsg->m_dnshdr.flags & DNS_RCODE) == DNS_NAMEERR) { DNSC_DEBUG("exit - failure - no name error\n"); return EHOSTNOTFOUND; /* name error reply */ } /* * no data replies have the rcode section set to no error. the reply * will have "no relevant answers in the answer section. the authority * section will contain an SOA record, or there will be no NS records * there", see section 2.2 of RFC 2308. * * we assume the DNS message has already been verified so if there is * no name error then there is no errors given in the flag field. first * see if there are any "relevant" answer records. relevant in this * case means no A records for our domain. then see if there is an * SOA record or there are no NS records in the authority section. */ if ( (query->qtype == naptr_type) && (find_num_match(query->domain, dnsmsg->m_answers, QT_NAPTR) == 0) ) { return ENODATA; } if ( (query->qtype == srv_type) && (find_num_match(query->domain, dnsmsg->m_answers, QT_SRV) == 0) ) { return ENODATA; } DNSC_DEBUG("exit - success\n"); return ESUCCESS;} /* end dns_XX_negative_replycheck() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -