Changeset 1356
- Timestamp:
- Jun 11, 2007 4:47:51 PM (16 years ago)
- Location:
- pjproject/trunk/pjlib-util
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/include/pjlib-util/errno.h
r1037 r1356 175 175 */ 176 176 #define PJLIB_UTIL_EDNSNOANSWERREC (PJLIB_UTIL_ERRNO_START+47) /* 320047 */ 177 /** 178 * @hideinitializer 179 * Invalid DNS answer. This error is raised for example when the DNS 180 * answer does not have a query section, or the type of RR in the answer 181 * doesn't match the query. 182 */ 183 #define PJLIB_UTIL_EDNSINANSWER (PJLIB_UTIL_ERRNO_START+48) /* 320048 */ 177 184 178 185 -
pjproject/trunk/pjlib-util/include/pjlib-util/resolver.h
r1346 r1356 197 197 unsigned bad_ns_ttl; /**< See #PJ_DNS_RESOLVER_BAD_NS_TTL */ 198 198 } pj_dns_settings; 199 200 201 /** 202 * This structure represents DNS A record, as the result of parsing 203 * DNS response packet using #pj_dns_parse_a_response(). 204 */ 205 typedef struct pj_dns_a_record 206 { 207 /** The target name being queried. */ 208 pj_str_t name; 209 210 /** If target name corresponds to a CNAME entry, the alias contains 211 * the value of the CNAME entry, otherwise it will be empty. 212 */ 213 pj_str_t alias; 214 215 /** Number of IP addresses. */ 216 unsigned addr_count; 217 218 /** IP addresses of the host found in the response */ 219 pj_in_addr addr[PJ_DNS_MAX_IP_IN_A_REC]; 220 221 /** Internal buffer for hostname and alias. */ 222 char buf_[128]; 223 224 } pj_dns_a_record; 225 199 226 200 227 /** … … 366 393 pj_bool_t notify); 367 394 395 /** 396 * A utility function to parse a DNS response containing A records into 397 * DNS A record. 398 * 399 * @param pkt The DNS response packet. 400 * @param rec The structure to be initialized with the parsed 401 * DNS A record from the packet. 402 * 403 * @return PJ_SUCCESS if response can be parsed successfully. 404 */ 405 PJ_DECL(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt, 406 pj_dns_a_record *rec); 407 368 408 369 409 /** -
pjproject/trunk/pjlib-util/src/pjlib-util/errno.c
r1242 r1356 59 59 PJ_BUILD_ERR( PJLIB_UTIL_EDNSNOWORKINGNS, "No working DNS nameserver"), 60 60 PJ_BUILD_ERR( PJLIB_UTIL_EDNSNOANSWERREC, "No answer record in the DNS response"), 61 PJ_BUILD_ERR( PJLIB_UTIL_EDNSINANSWER, "Invalid DNS answer"), 61 62 62 63 PJ_BUILD_ERR( PJLIB_UTIL_EDNS_FORMERR, "DNS \"Format error\""), -
pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c
r1348 r1356 425 425 426 426 PJ_ASSERT_RETURN(resolver && count && servers, PJ_EINVAL); 427 PJ_ASSERT_RETURN(count < PJ_DNS_RESOLVER_MAX_NS, PJ_EINVAL); 427 428 428 429 pj_mutex_lock(resolver->mutex); … … 801 802 } 802 803 804 805 /* 806 * DNS response containing A packet. 807 */ 808 PJ_DEF(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt, 809 pj_dns_a_record *rec) 810 { 811 pj_str_t hostname, alias, *res_name; 812 unsigned bufstart = 0; 813 unsigned bufleft = sizeof(rec->buf_); 814 unsigned i, ansidx; 815 816 PJ_ASSERT_RETURN(pkt && rec, PJ_EINVAL); 817 818 /* Init the record */ 819 pj_bzero(rec, sizeof(pj_dns_a_record)); 820 821 /* Return error if there's error in the packet. */ 822 if (PJ_DNS_GET_RCODE(pkt->hdr.flags)) 823 return PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_GET_RCODE(pkt->hdr.flags)); 824 825 /* Return error if there's no query section */ 826 if (pkt->hdr.qdcount == 0) 827 return PJLIB_UTIL_EDNSINANSWER; 828 829 /* Return error if there's no answer */ 830 if (pkt->hdr.anscount == 0) 831 return PJLIB_UTIL_EDNSNOANSWERREC; 832 833 /* Get the hostname from the query. */ 834 hostname = pkt->q[0].name; 835 836 /* Copy hostname to the record */ 837 if (hostname.slen > (int)bufleft) { 838 return PJ_ENAMETOOLONG; 839 } 840 841 pj_memcpy(&rec->buf_[bufstart], hostname.ptr, hostname.slen); 842 rec->name.ptr = &rec->buf_[bufstart]; 843 rec->name.slen = hostname.slen; 844 845 bufstart += hostname.slen; 846 bufleft -= hostname.slen; 847 848 /* Find the first RR which name matches the hostname */ 849 for (ansidx=0; ansidx < pkt->hdr.anscount; ++ansidx) { 850 if (pj_stricmp(&pkt->ans[ansidx].name, &hostname)==0) 851 break; 852 } 853 854 if (ansidx == pkt->hdr.anscount) 855 return PJLIB_UTIL_EDNSNOANSWERREC; 856 857 /* If hostname is a CNAME, get the alias. */ 858 if (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME) { 859 alias = pkt->ans[ansidx].rdata.cname.name; 860 res_name = &alias; 861 } else if (pkt->ans[ansidx].type == PJ_DNS_TYPE_A) { 862 alias.ptr = NULL; 863 alias.slen = 0; 864 res_name = &hostname; 865 } else { 866 return PJLIB_UTIL_EDNSINANSWER; 867 } 868 869 /* Copy alias to the record, if present. */ 870 if (alias.slen) { 871 if (alias.slen > (int)bufleft) 872 return PJ_ENAMETOOLONG; 873 874 pj_memcpy(&rec->buf_[bufstart], alias.ptr, alias.slen); 875 rec->alias.ptr = &rec->buf_[bufstart]; 876 rec->alias.slen = alias.slen; 877 878 bufstart += alias.slen; 879 bufleft -= alias.slen; 880 } 881 882 /* Now scan the answer for all type A RRs where the name matches 883 * hostname or alias. 884 */ 885 for (i=0; i<pkt->hdr.anscount; ++i) { 886 if (pkt->ans[i].type == PJ_DNS_TYPE_A && 887 pj_stricmp(&pkt->ans[i].name, res_name)==0 && 888 rec->addr_count < PJ_DNS_MAX_IP_IN_A_REC) 889 { 890 rec->addr[rec->addr_count].s_addr = 891 pkt->ans[i].rdata.a.ip_addr.s_addr; 892 ++rec->addr_count; 893 } 894 } 895 896 if (rec->addr_count == 0) 897 return PJLIB_UTIL_EDNSNOANSWERREC; 898 899 return PJ_SUCCESS; 900 } 803 901 804 902 … … 1031 1129 1032 1130 /* Duplicate the packet. 1033 * We don't need to keep the query, NS, and AR sections from the packet, 1034 * so exclude from duplication. 1131 * We don't need to keep the NS and AR sections from the packet, 1132 * so exclude from duplication. We do need to keep the Query 1133 * section since DNS A parser needs the query section to know 1134 * the name being requested. 1035 1135 */ 1036 1136 res_pool = pj_pool_create_on_buf("respool", cache->buf, sizeof(cache->buf)); … … 1038 1138 cache->pkt = NULL; 1039 1139 pj_dns_packet_dup(res_pool, pkt, 1040 PJ_DNS_NO_ QD | PJ_DNS_NO_NS | PJ_DNS_NO_AR,1140 PJ_DNS_NO_NS | PJ_DNS_NO_AR, 1041 1141 &cache->pkt); 1042 1142 }
Note: See TracChangeset
for help on using the changeset viewer.