📄 dns_client_util.c
字号:
} /* end fmt_ip_answer() *//* * fmt_cname_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 a_type; we handle * both cases. then we need to locate the A records for the CNAME. note that it * is unlikely that there would be A 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. * * return: 0 for success, and * -1 indicates an error condition. */intfmt_cname_answer(QueryState *query, DnsMsg *dnsmsg){ struct dns_hostent *hptr; DnsRRec *RR; int cnt; MSG_D_DNS_GET_ADDRBYNAME(dmsg, query->reply); DNSC_DEBUG("entry\n"); hptr = dmsg->hptr; switch(query->qtype) { case a_type: if ((RR = find_match_rrecord(query->domain, dnsmsg->m_answers, QT_CNAME)) == NULL) { dprintf("%C: unexpect format error, no CNAME record for %s\n", query->domain);#ifdef DNS_DEBUG print_dns_message(dnsmsg);#endif dmsg->error = ETRYAGAIN; return -1; } strcpy(hptr->h_alias, query->domain); strcpy(hptr->h_name, RR->r_data); break; case ac_type: strcpy(hptr->h_name, query->domain); strcpy(hptr->h_alias, query->cname); break; default: dprintf("%C: unrecognized query type: %d\n", query->qtype); dmsg->error = ETRYAGAIN; return -1; } cnt = 0; if ( find_num_match(hptr->h_name, dnsmsg->m_answers, QT_A) > 0 ) { RR = find_match_rrecord(hptr->h_name, dnsmsg->m_answers, QT_A); while ( RR != NULL && cnt < hptr->h_numaddrs ) { hptr->h_addr_list[cnt++] = *(U32 *)RR->r_data; RR = find_match_rrecord(hptr->h_name, RR->r_next, QT_A); } } if ( find_num_match(hptr->h_name, dnsmsg->m_additionals, QT_A) > 0 ) { RR = find_match_rrecord(hptr->h_name, dnsmsg->m_additionals, QT_A); while ( RR != NULL && cnt < hptr->h_numaddrs ) { hptr->h_addr_list[cnt++] = *(U32 *)RR->r_data; RR = find_match_rrecord(hptr->h_name, RR->r_next, QT_A); } } hptr->h_numaddrs = cnt; dmsg->error = ESUCCESS; return 0;} /* end fmt_cname_answer() *//* * fmt_cache_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 * A records for the CNAME if that is there. also note that the cache puts the * A records for the CNAME in the additional section. this routine looks at the * first record of the answer section and if its a CNAME sets the query type so * that fmt_cname_answer() will handle things correctly. otherwise fmt_ip_answer() * is used. * * return: 0 for success, or * -1 to incidate an error condition. */intfmt_cache_answer(QueryState *query, DnsMsg *dnsmsg){ DnsRRec *RR = dnsmsg->m_answers; char tmpname[NAMEMAX+1]; /* * 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 = a_type; return fmt_cname_answer(query, dnsmsg); } return fmt_ip_answer(query, dnsmsg);} /* end fmt_cache_answer() *//* * print_dns_error() * * this routine will print a message describing the error indicated by the * value given by error. */voidprint_dns_error(int error){ switch(error) { case EHOSTNOTFOUND: printf("Specified host is unknown.\n"); break; case ENOADDRESS: printf("Name is valid but does not have an IP address.\n"); break; case ENORECOVERY: printf("Non-recoverable name server error occurred.\n"); break; case ETRYAGAIN: printf("Temporary error occurred - try again later.\n"); break; case ENOMEM: printf("Error attempting to allocate memory.\n"); break; case ENONSADDRESS: printf("No name server addresses provided, configuration error.\n"); break; case ENOSEARCHLIST: printf("No search list provided (when using relative host name).\n"); break; }} /* end print_dns_error() *//* * dns_validate_hostname() * * this routine is used to verify a hostname entered by a user is at least * reasonable. that is, we check that the name doesn't start with a '.', * (it can end in a dot). it has no white space, (no spaces or tabs). we * also check that the characters are alpha numeric. we check that the name * isn't over the max name length and we check that individual labels are * not over their max either. (see RFC 1034 section 3.5) * * return: 0 for okay, and * -1 to indicate an error. */intdns_validate_hostname(const char *name){ char dname[NAMEMAX+1]; char *dup, *tok; int len; if ( name == NULL ) /* make sure there is a name */ return -1; len = strlen(name); if ( len > NAMEMAX || len == 0 ) return -1; /* first character not allowed to be a dot and must be a character * ending character must be alphanumeric. */ if ( !isalpha(*name) ) return -1; if ( name[strlen(name) - 1] != '.' && !isalnum(name[strlen(name) - 1]) ) return -1; strcpy(dname, name); dup = dname; /* check that no white space and that all characters are dots or * at least alpha numeric. internal characters can be a hyphen. */ while ( *dup != '\0' ) { if ( !isalnum(*dup) && *dup != '.' && *dup != '-' ) return -1; dup++; } /* * alright, everything is okay. if there are individual labels, * for exampe www.hostname.com the we need to verify they are not * over the max label size. */ dup = dname; while ((tok = strchr(dup, '.')) != NULL) { *tok++ = '\0'; len = strlen(dup); if ( len > LABELMAX || len == 0 ) return -1; /* labels must start with a letter and end with an alphanumer value */ if ( !isalpha(*dup) || !isalnum(dup[len - 1]) ) return -1; dup = tok; } return 0;} /* end dns_validate_hostname() *//* * fmt_XX_answer() * * this routine formats the RRS in the user supplied buffer. * * return: None */voidfmt_XX_answer(QueryState *query, DnsRRec *answers){ DnsRRec *RR; U32 orig_len, copy_len; U8 *ptr; MSG_D_DNS_GET_RR(dmsg, query->reply); DNSC_DEBUG("entry\n"); ptr = dmsg->rrptr; RR = answers; orig_len = *(dmsg->len); copy_len = 0; while ( (RR != NULL) && ((copy_len+RR->r_datalen+sizeof(RR->r_datalen)) <= orig_len) ) { memcpy(ptr, (U8 *)(&(RR->r_datalen)), sizeof(U16)); ptr += sizeof(U16); memcpy(ptr, RR->r_data, RR->r_datalen); ptr += RR->r_datalen; copy_len += (RR->r_datalen+sizeof(RR->r_datalen)); RR = RR->r_next; } /* If RR == NULL we have copied all RRs to the user buffer */ if (RR == NULL) { /* Indicate the user about the actual length of data */ *(dmsg->len) = copy_len; dmsg->error = ESUCCESS; if (query->qtype == srv_type) { memcpy (dmsg->dnsMsg, dns_client_recvbuf, BUFLEN); } } else { /* user supplied buffer is less to copy all RRs */ dmsg->error = EMORE; /* shd be EMORE */ /* calculate the length of buffer needed to accomodate all RRs */ while (RR != NULL) { copy_len += (RR->r_datalen+sizeof(RR->r_datalen)); RR = RR->r_next; } /* Indicate the user about the actual length of buffer needed */ *(dmsg->len) = copy_len; } DNSC_DEBUG("exit\n"); return ;} /* end fmt_XX_answer() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -