1 /* $NetBSD: resolve.c,v 1.4 2014/04/24 14:49:43 pettai Exp $ */ 2 3 /* 4 * Copyright (c) 1995 - 2006 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 37 #include <config.h> 38 39 #include <krb5/roken.h> 40 #ifdef HAVE_ARPA_NAMESER_H 41 #include <arpa/nameser.h> 42 #endif 43 #ifdef HAVE_RESOLV_H 44 #include <resolv.h> 45 #endif 46 #ifdef HAVE_DNS_H 47 #include <dns.h> 48 #endif 49 #include <krb5/resolve.h> 50 51 #include <assert.h> 52 53 #ifdef _AIX /* AIX have broken res_nsearch() in 5.1 (5.0 also ?) */ 54 #undef HAVE_RES_NSEARCH 55 #endif 56 57 #define DECL(X) {#X, rk_ns_t_##X} 58 59 static struct stot{ 60 const char *name; 61 int type; 62 }stot[] = { 63 DECL(a), 64 DECL(aaaa), 65 DECL(ns), 66 DECL(cname), 67 DECL(soa), 68 DECL(ptr), 69 DECL(mx), 70 DECL(txt), 71 DECL(afsdb), 72 DECL(sig), 73 DECL(key), 74 DECL(srv), 75 DECL(naptr), 76 DECL(sshfp), 77 DECL(ds), 78 {NULL, 0} 79 }; 80 81 int _resolve_debug = 0; 82 83 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 84 rk_dns_string_to_type(const char *name) 85 { 86 struct stot *p = stot; 87 for(p = stot; p->name; p++) 88 if(strcasecmp(name, p->name) == 0) 89 return p->type; 90 return -1; 91 } 92 93 ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL 94 rk_dns_type_to_string(int type) 95 { 96 struct stot *p = stot; 97 for(p = stot; p->name; p++) 98 if(type == p->type) 99 return p->name; 100 return NULL; 101 } 102 103 #if ((defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)) || defined(HAVE_WINDNS) 104 105 static void 106 dns_free_rr(struct rk_resource_record *rr) 107 { 108 if(rr->domain) 109 free(rr->domain); 110 if(rr->u.data) 111 free(rr->u.data); 112 free(rr); 113 } 114 115 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 116 rk_dns_free_data(struct rk_dns_reply *r) 117 { 118 struct rk_resource_record *rr; 119 if(r->q.domain) 120 free(r->q.domain); 121 for(rr = r->head; rr;){ 122 struct rk_resource_record *tmp = rr; 123 rr = rr->next; 124 dns_free_rr(tmp); 125 } 126 free (r); 127 } 128 129 #ifndef HAVE_WINDNS 130 131 static int 132 parse_record(const unsigned char *data, const unsigned char *end_data, 133 const unsigned char **pp, struct rk_resource_record **ret_rr) 134 { 135 struct rk_resource_record *rr; 136 int type, class, ttl; 137 unsigned size; 138 int status; 139 char host[MAXDNAME]; 140 const unsigned char *p = *pp; 141 142 *ret_rr = NULL; 143 144 status = dn_expand(data, end_data, p, host, sizeof(host)); 145 if(status < 0) 146 return -1; 147 if (p + status + 10 > end_data) 148 return -1; 149 150 p += status; 151 type = (p[0] << 8) | p[1]; 152 p += 2; 153 class = (p[0] << 8) | p[1]; 154 p += 2; 155 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 156 p += 4; 157 size = (p[0] << 8) | p[1]; 158 p += 2; 159 160 if (p + size > end_data) 161 return -1; 162 163 rr = calloc(1, sizeof(*rr)); 164 if(rr == NULL) 165 return -1; 166 rr->domain = strdup(host); 167 if(rr->domain == NULL) { 168 dns_free_rr(rr); 169 return -1; 170 } 171 rr->type = type; 172 rr->class = class; 173 rr->ttl = ttl; 174 rr->size = size; 175 switch(type){ 176 case rk_ns_t_ns: 177 case rk_ns_t_cname: 178 case rk_ns_t_ptr: 179 status = dn_expand(data, end_data, p, host, sizeof(host)); 180 if(status < 0) { 181 dns_free_rr(rr); 182 return -1; 183 } 184 rr->u.txt = strdup(host); 185 if(rr->u.txt == NULL) { 186 dns_free_rr(rr); 187 return -1; 188 } 189 break; 190 case rk_ns_t_mx: 191 case rk_ns_t_afsdb:{ 192 size_t hostlen; 193 194 status = dn_expand(data, end_data, p + 2, host, sizeof(host)); 195 if(status < 0){ 196 dns_free_rr(rr); 197 return -1; 198 } 199 if ((size_t)status + 2 > size) { 200 dns_free_rr(rr); 201 return -1; 202 } 203 204 hostlen = strlen(host); 205 rr->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) + 206 hostlen); 207 if(rr->u.mx == NULL) { 208 dns_free_rr(rr); 209 return -1; 210 } 211 rr->u.mx->preference = (p[0] << 8) | p[1]; 212 strlcpy(rr->u.mx->domain, host, hostlen + 1); 213 break; 214 } 215 case rk_ns_t_srv:{ 216 size_t hostlen; 217 status = dn_expand(data, end_data, p + 6, host, sizeof(host)); 218 if(status < 0){ 219 dns_free_rr(rr); 220 return -1; 221 } 222 if ((size_t)status + 6 > size) { 223 dns_free_rr(rr); 224 return -1; 225 } 226 227 hostlen = strlen(host); 228 rr->u.srv = 229 (struct srv_record*)malloc(sizeof(struct srv_record) + 230 hostlen); 231 if(rr->u.srv == NULL) { 232 dns_free_rr(rr); 233 return -1; 234 } 235 rr->u.srv->priority = (p[0] << 8) | p[1]; 236 rr->u.srv->weight = (p[2] << 8) | p[3]; 237 rr->u.srv->port = (p[4] << 8) | p[5]; 238 strlcpy(rr->u.srv->target, host, hostlen + 1); 239 break; 240 } 241 case rk_ns_t_txt:{ 242 if(size == 0 || size < (unsigned)(*p + 1)) { 243 dns_free_rr(rr); 244 return -1; 245 } 246 rr->u.txt = (char*)malloc(*p + 1); 247 if(rr->u.txt == NULL) { 248 dns_free_rr(rr); 249 return -1; 250 } 251 strncpy(rr->u.txt, (const char*)(p + 1), *p); 252 rr->u.txt[*p] = '\0'; 253 break; 254 } 255 case rk_ns_t_key : { 256 size_t key_len; 257 258 if (size < 4) { 259 dns_free_rr(rr); 260 return -1; 261 } 262 263 key_len = size - 4; 264 rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1); 265 if (rr->u.key == NULL) { 266 dns_free_rr(rr); 267 return -1; 268 } 269 270 rr->u.key->flags = (p[0] << 8) | p[1]; 271 rr->u.key->protocol = p[2]; 272 rr->u.key->algorithm = p[3]; 273 rr->u.key->key_len = key_len; 274 memcpy (rr->u.key->key_data, p + 4, key_len); 275 break; 276 } 277 case rk_ns_t_sig : { 278 size_t sig_len, hostlen; 279 280 if(size <= 18) { 281 dns_free_rr(rr); 282 return -1; 283 } 284 status = dn_expand (data, end_data, p + 18, host, sizeof(host)); 285 if (status < 0) { 286 dns_free_rr(rr); 287 return -1; 288 } 289 if ((size_t)status + 18 > size) { 290 dns_free_rr(rr); 291 return -1; 292 } 293 294 /* the signer name is placed after the sig_data, to make it 295 easy to free this structure; the size calculation below 296 includes the zero-termination if the structure itself. 297 don't you just love C? 298 */ 299 sig_len = size - 18 - status; 300 hostlen = strlen(host); 301 rr->u.sig = malloc(sizeof(*rr->u.sig) 302 + hostlen + sig_len); 303 if (rr->u.sig == NULL) { 304 dns_free_rr(rr); 305 return -1; 306 } 307 rr->u.sig->type = (p[0] << 8) | p[1]; 308 rr->u.sig->algorithm = p[2]; 309 rr->u.sig->labels = p[3]; 310 rr->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16) 311 | (p[6] << 8) | p[7]; 312 rr->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16) 313 | (p[10] << 8) | p[11]; 314 rr->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16) 315 | (p[14] << 8) | p[15]; 316 rr->u.sig->key_tag = (p[16] << 8) | p[17]; 317 rr->u.sig->sig_len = sig_len; 318 memcpy (rr->u.sig->sig_data, p + 18 + status, sig_len); 319 rr->u.sig->signer = &rr->u.sig->sig_data[sig_len]; 320 strlcpy(rr->u.sig->signer, host, hostlen + 1); 321 break; 322 } 323 324 case rk_ns_t_cert : { 325 size_t cert_len; 326 327 if (size < 5) { 328 dns_free_rr(rr); 329 return -1; 330 } 331 332 cert_len = size - 5; 333 rr->u.cert = malloc (sizeof(*rr->u.cert) + cert_len - 1); 334 if (rr->u.cert == NULL) { 335 dns_free_rr(rr); 336 return -1; 337 } 338 339 rr->u.cert->type = (p[0] << 8) | p[1]; 340 rr->u.cert->tag = (p[2] << 8) | p[3]; 341 rr->u.cert->algorithm = p[4]; 342 rr->u.cert->cert_len = cert_len; 343 memcpy (rr->u.cert->cert_data, p + 5, cert_len); 344 break; 345 } 346 case rk_ns_t_sshfp : { 347 size_t sshfp_len; 348 349 if (size < 2) { 350 dns_free_rr(rr); 351 return -1; 352 } 353 354 sshfp_len = size - 2; 355 356 rr->u.sshfp = malloc (sizeof(*rr->u.sshfp) + sshfp_len - 1); 357 if (rr->u.sshfp == NULL) { 358 dns_free_rr(rr); 359 return -1; 360 } 361 362 rr->u.sshfp->algorithm = p[0]; 363 rr->u.sshfp->type = p[1]; 364 rr->u.sshfp->sshfp_len = sshfp_len; 365 memcpy (rr->u.sshfp->sshfp_data, p + 2, sshfp_len); 366 break; 367 } 368 case rk_ns_t_ds: { 369 size_t digest_len; 370 371 if (size < 4) { 372 dns_free_rr(rr); 373 return -1; 374 } 375 376 digest_len = size - 4; 377 378 rr->u.ds = malloc (sizeof(*rr->u.ds) + digest_len - 1); 379 if (rr->u.ds == NULL) { 380 dns_free_rr(rr); 381 return -1; 382 } 383 384 rr->u.ds->key_tag = (p[0] << 8) | p[1]; 385 rr->u.ds->algorithm = p[2]; 386 rr->u.ds->digest_type = p[3]; 387 rr->u.ds->digest_len = digest_len; 388 memcpy (rr->u.ds->digest_data, p + 4, digest_len); 389 break; 390 } 391 default: 392 rr->u.data = (unsigned char*)malloc(size); 393 if(size != 0 && rr->u.data == NULL) { 394 dns_free_rr(rr); 395 return -1; 396 } 397 if (size) 398 memcpy(rr->u.data, p, size); 399 } 400 *pp = p + size; 401 *ret_rr = rr; 402 403 return 0; 404 } 405 406 #ifndef TEST_RESOLVE 407 static 408 #endif 409 struct rk_dns_reply* 410 parse_reply(const unsigned char *data, size_t len) 411 { 412 const unsigned char *p; 413 int status; 414 size_t i; 415 char host[MAXDNAME]; 416 const unsigned char *end_data = data + len; 417 struct rk_dns_reply *r; 418 struct rk_resource_record **rr; 419 420 r = calloc(1, sizeof(*r)); 421 if (r == NULL) 422 return NULL; 423 424 p = data; 425 426 r->h.id = (p[0] << 8) | p[1]; 427 r->h.flags = 0; 428 if (p[2] & 0x01) 429 r->h.flags |= rk_DNS_HEADER_RESPONSE_FLAG; 430 r->h.opcode = (p[2] >> 1) & 0xf; 431 if (p[2] & 0x20) 432 r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER; 433 if (p[2] & 0x40) 434 r->h.flags |= rk_DNS_HEADER_TRUNCATED_MESSAGE; 435 if (p[2] & 0x80) 436 r->h.flags |= rk_DNS_HEADER_RECURSION_DESIRED; 437 if (p[3] & 0x01) 438 r->h.flags |= rk_DNS_HEADER_RECURSION_AVAILABLE; 439 if (p[3] & 0x04) 440 r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER; 441 if (p[3] & 0x08) 442 r->h.flags |= rk_DNS_HEADER_CHECKING_DISABLED; 443 r->h.response_code = (p[3] >> 4) & 0xf; 444 r->h.qdcount = (p[4] << 8) | p[5]; 445 r->h.ancount = (p[6] << 8) | p[7]; 446 r->h.nscount = (p[8] << 8) | p[9]; 447 r->h.arcount = (p[10] << 8) | p[11]; 448 449 p += 12; 450 451 if(r->h.qdcount != 1) { 452 free(r); 453 return NULL; 454 } 455 status = dn_expand(data, end_data, p, host, sizeof(host)); 456 if(status < 0){ 457 rk_dns_free_data(r); 458 return NULL; 459 } 460 r->q.domain = strdup(host); 461 if(r->q.domain == NULL) { 462 rk_dns_free_data(r); 463 return NULL; 464 } 465 if (p + status + 4 > end_data) { 466 rk_dns_free_data(r); 467 return NULL; 468 } 469 p += status; 470 r->q.type = (p[0] << 8 | p[1]); 471 p += 2; 472 r->q.class = (p[0] << 8 | p[1]); 473 p += 2; 474 475 rr = &r->head; 476 for(i = 0; i < r->h.ancount; i++) { 477 if(parse_record(data, end_data, &p, rr) != 0) { 478 rk_dns_free_data(r); 479 return NULL; 480 } 481 rr = &(*rr)->next; 482 } 483 for(i = 0; i < r->h.nscount; i++) { 484 if(parse_record(data, end_data, &p, rr) != 0) { 485 rk_dns_free_data(r); 486 return NULL; 487 } 488 rr = &(*rr)->next; 489 } 490 for(i = 0; i < r->h.arcount; i++) { 491 if(parse_record(data, end_data, &p, rr) != 0) { 492 rk_dns_free_data(r); 493 return NULL; 494 } 495 rr = &(*rr)->next; 496 } 497 *rr = NULL; 498 return r; 499 } 500 501 #ifdef HAVE_RES_NSEARCH 502 #ifdef HAVE_RES_NDESTROY 503 #define rk_res_free(x) res_ndestroy(x) 504 #else 505 #define rk_res_free(x) res_nclose(x) 506 #endif 507 #endif 508 509 #if defined(HAVE_DNS_SEARCH) 510 #define resolve_search(h,n,c,t,r,l) \ 511 ((int)dns_search(h,n,c,t,r,l,(struct sockaddr *)&from,&fromsize)) 512 #define resolve_free_handle(h) dns_free(h) 513 #elif defined(HAVE_RES_NSEARCH) 514 #define resolve_search(h,n,c,t,r,l) res_nsearch(h,n,c,t,r,l) 515 #define resolve_free_handle(h) rk_res_free(h); 516 #else 517 #define resolve_search(h,n,c,t,r,l) res_search(n,c,t,r,l) 518 #define handle 0 519 #define resolve_free_handle(h) 520 #endif 521 522 523 static struct rk_dns_reply * 524 dns_lookup_int(const char *domain, int rr_class, int rr_type) 525 { 526 struct rk_dns_reply *r; 527 void *reply = NULL; 528 int size, len; 529 #if defined(HAVE_DNS_SEARCH) 530 struct sockaddr_storage from; 531 uint32_t fromsize = sizeof(from); 532 dns_handle_t handle; 533 534 handle = dns_open(NULL); 535 if (handle == NULL) 536 return NULL; 537 #elif defined(HAVE_RES_NSEARCH) 538 struct __res_state state; 539 struct __res_state *handle = &state; 540 541 memset(&state, 0, sizeof(state)); 542 if(res_ninit(handle)) 543 return NULL; /* is this the best we can do? */ 544 #endif 545 546 len = 1500; 547 while(1) { 548 if (reply) { 549 free(reply); 550 reply = NULL; 551 } 552 if (_resolve_debug) { 553 #if defined(HAVE_DNS_SEARCH) 554 dns_set_debug(handle, 1); 555 #elif defined(HAVE_RES_NSEARCH) 556 state.options |= RES_DEBUG; 557 #endif 558 fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain, 559 rr_class, rk_dns_type_to_string(rr_type), len); 560 } 561 reply = malloc(len); 562 if (reply == NULL) { 563 resolve_free_handle(handle); 564 return NULL; 565 } 566 567 size = resolve_search(handle, domain, rr_class, rr_type, reply, len); 568 569 if (_resolve_debug) { 570 fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n", 571 domain, rr_class, rk_dns_type_to_string(rr_type), size); 572 } 573 if (size > len) { 574 /* resolver thinks it know better, go for it */ 575 len = size; 576 } else if (size > 0) { 577 /* got a good reply */ 578 break; 579 } else if (size <= 0 && len < rk_DNS_MAX_PACKET_SIZE) { 580 len *= 2; 581 if (len > rk_DNS_MAX_PACKET_SIZE) 582 len = rk_DNS_MAX_PACKET_SIZE; 583 } else { 584 /* the end, leave */ 585 resolve_free_handle(handle); 586 free(reply); 587 return NULL; 588 } 589 } 590 591 len = min(len, size); 592 r = parse_reply(reply, len); 593 free(reply); 594 595 resolve_free_handle(handle); 596 597 return r; 598 } 599 600 ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL 601 rk_dns_lookup(const char *domain, const char *type_name) 602 { 603 int type; 604 605 type = rk_dns_string_to_type(type_name); 606 if(type == -1) { 607 if(_resolve_debug) 608 fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n", 609 type_name); 610 return NULL; 611 } 612 return dns_lookup_int(domain, rk_ns_c_in, type); 613 } 614 615 #endif /* !HAVE_WINDNS */ 616 617 static int 618 compare_srv(const void *a, const void *b) 619 { 620 const struct rk_resource_record *const* aa = a, *const* bb = b; 621 622 if((*aa)->u.srv->priority == (*bb)->u.srv->priority) 623 return ((*aa)->u.srv->weight - (*bb)->u.srv->weight); 624 return ((*aa)->u.srv->priority - (*bb)->u.srv->priority); 625 } 626 627 /* try to rearrange the srv-records by the algorithm in RFC2782 */ 628 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 629 rk_dns_srv_order(struct rk_dns_reply *r) 630 { 631 struct rk_resource_record **srvs, **ss, **headp; 632 struct rk_resource_record *rr; 633 int num_srv = 0; 634 635 rk_random_init(); 636 637 for(rr = r->head; rr; rr = rr->next) 638 if(rr->type == rk_ns_t_srv) 639 num_srv++; 640 641 if(num_srv == 0) 642 return; 643 644 srvs = malloc(num_srv * sizeof(*srvs)); 645 if(srvs == NULL) 646 return; /* XXX not much to do here */ 647 648 /* unlink all srv-records from the linked list and put them in 649 a vector */ 650 for(ss = srvs, headp = &r->head; *headp; ) 651 if((*headp)->type == rk_ns_t_srv) { 652 *ss = *headp; 653 *headp = (*headp)->next; 654 (*ss)->next = NULL; 655 ss++; 656 } else 657 headp = &(*headp)->next; 658 659 /* sort them by priority and weight */ 660 qsort(srvs, num_srv, sizeof(*srvs), compare_srv); 661 662 headp = &r->head; 663 664 for(ss = srvs; ss < srvs + num_srv; ) { 665 int sum, rnd, count; 666 struct rk_resource_record **ee, **tt; 667 /* find the last record with the same priority and count the 668 sum of all weights */ 669 for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) { 670 assert(*tt != NULL); 671 if((*tt)->u.srv->priority != (*ss)->u.srv->priority) 672 break; 673 sum += (*tt)->u.srv->weight; 674 } 675 ee = tt; 676 /* ss is now the first record of this priority and ee is the 677 first of the next */ 678 while(ss < ee) { 679 rnd = rk_random() % (sum + 1); 680 for(count = 0, tt = ss; ; tt++) { 681 if(*tt == NULL) 682 continue; 683 count += (*tt)->u.srv->weight; 684 if(count >= rnd) 685 break; 686 } 687 688 assert(tt < ee); 689 690 /* insert the selected record at the tail (of the head) of 691 the list */ 692 (*tt)->next = *headp; 693 *headp = *tt; 694 headp = &(*tt)->next; 695 sum -= (*tt)->u.srv->weight; 696 *tt = NULL; 697 while(ss < ee && *ss == NULL) 698 ss++; 699 } 700 } 701 702 free(srvs); 703 return; 704 } 705 706 #ifdef HAVE_WINDNS 707 708 #include <WinDNS.h> 709 710 static struct rk_resource_record * 711 parse_dns_record(PDNS_RECORD pRec) 712 { 713 struct rk_resource_record * rr; 714 715 if (pRec == NULL) 716 return NULL; 717 718 rr = calloc(1, sizeof(*rr)); 719 720 rr->domain = strdup(pRec->pName); 721 rr->type = pRec->wType; 722 rr->class = 0; 723 rr->ttl = pRec->dwTtl; 724 rr->size = 0; 725 726 switch (rr->type) { 727 case rk_ns_t_ns: 728 case rk_ns_t_cname: 729 case rk_ns_t_ptr: 730 rr->u.txt = strdup(pRec->Data.NS.pNameHost); 731 if(rr->u.txt == NULL) { 732 dns_free_rr(rr); 733 return NULL; 734 } 735 break; 736 737 case rk_ns_t_mx: 738 case rk_ns_t_afsdb:{ 739 size_t hostlen = strnlen(pRec->Data.MX.pNameExchange, DNS_MAX_NAME_LENGTH); 740 741 rr->u.mx = (struct mx_record *)malloc(sizeof(struct mx_record) + 742 hostlen); 743 if (rr->u.mx == NULL) { 744 dns_free_rr(rr); 745 return NULL; 746 } 747 748 strcpy_s(rr->u.mx->domain, hostlen + 1, pRec->Data.MX.pNameExchange); 749 rr->u.mx->preference = pRec->Data.MX.wPreference; 750 break; 751 } 752 753 case rk_ns_t_srv:{ 754 size_t hostlen = strnlen(pRec->Data.SRV.pNameTarget, DNS_MAX_NAME_LENGTH); 755 756 rr->u.srv = 757 (struct srv_record*)malloc(sizeof(struct srv_record) + 758 hostlen); 759 if(rr->u.srv == NULL) { 760 dns_free_rr(rr); 761 return NULL; 762 } 763 764 rr->u.srv->priority = pRec->Data.SRV.wPriority; 765 rr->u.srv->weight = pRec->Data.SRV.wWeight; 766 rr->u.srv->port = pRec->Data.SRV.wPort; 767 strcpy_s(rr->u.srv->target, hostlen + 1, pRec->Data.SRV.pNameTarget); 768 769 break; 770 } 771 772 case rk_ns_t_txt:{ 773 size_t len; 774 775 if (pRec->Data.TXT.dwStringCount == 0) { 776 rr->u.txt = strdup(""); 777 break; 778 } 779 780 len = strnlen(pRec->Data.TXT.pStringArray[0], DNS_MAX_TEXT_STRING_LENGTH); 781 782 rr->u.txt = (char *)malloc(len + 1); 783 strcpy_s(rr->u.txt, len + 1, pRec->Data.TXT.pStringArray[0]); 784 785 break; 786 } 787 788 case rk_ns_t_key : { 789 size_t key_len; 790 791 if (pRec->wDataLength < 4) { 792 dns_free_rr(rr); 793 return NULL; 794 } 795 796 key_len = pRec->wDataLength - 4; 797 rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1); 798 if (rr->u.key == NULL) { 799 dns_free_rr(rr); 800 return NULL; 801 } 802 803 rr->u.key->flags = pRec->Data.KEY.wFlags; 804 rr->u.key->protocol = pRec->Data.KEY.chProtocol; 805 rr->u.key->algorithm = pRec->Data.KEY.chAlgorithm; 806 rr->u.key->key_len = key_len; 807 memcpy_s (rr->u.key->key_data, key_len, 808 pRec->Data.KEY.Key, key_len); 809 break; 810 } 811 812 case rk_ns_t_sig : { 813 size_t sig_len, hostlen; 814 815 if(pRec->wDataLength <= 18) { 816 dns_free_rr(rr); 817 return NULL; 818 } 819 820 sig_len = pRec->wDataLength; 821 822 hostlen = strnlen(pRec->Data.SIG.pNameSigner, DNS_MAX_NAME_LENGTH); 823 824 rr->u.sig = malloc(sizeof(*rr->u.sig) 825 + hostlen + sig_len); 826 if (rr->u.sig == NULL) { 827 dns_free_rr(rr); 828 return NULL; 829 } 830 rr->u.sig->type = pRec->Data.SIG.wTypeCovered; 831 rr->u.sig->algorithm = pRec->Data.SIG.chAlgorithm; 832 rr->u.sig->labels = pRec->Data.SIG.chLabelCount; 833 rr->u.sig->orig_ttl = pRec->Data.SIG.dwOriginalTtl; 834 rr->u.sig->sig_expiration = pRec->Data.SIG.dwExpiration; 835 rr->u.sig->sig_inception = pRec->Data.SIG.dwTimeSigned; 836 rr->u.sig->key_tag = pRec->Data.SIG.wKeyTag; 837 rr->u.sig->sig_len = sig_len; 838 memcpy_s (rr->u.sig->sig_data, sig_len, 839 pRec->Data.SIG.Signature, sig_len); 840 rr->u.sig->signer = &rr->u.sig->sig_data[sig_len]; 841 strcpy_s(rr->u.sig->signer, hostlen + 1, pRec->Data.SIG.pNameSigner); 842 break; 843 } 844 845 #ifdef DNS_TYPE_DS 846 case rk_ns_t_ds: { 847 rr->u.ds = malloc (sizeof(*rr->u.ds) + pRec->Data.DS.wDigestLength - 1); 848 if (rr->u.ds == NULL) { 849 dns_free_rr(rr); 850 return NULL; 851 } 852 853 rr->u.ds->key_tag = pRec->Data.DS.wKeyTag; 854 rr->u.ds->algorithm = pRec->Data.DS.chAlgorithm; 855 rr->u.ds->digest_type = pRec->Data.DS.chDigestType; 856 rr->u.ds->digest_len = pRec->Data.DS.wDigestLength; 857 memcpy_s (rr->u.ds->digest_data, pRec->Data.DS.wDigestLength, 858 pRec->Data.DS.Digest, pRec->Data.DS.wDigestLength); 859 break; 860 } 861 #endif 862 863 default: 864 dns_free_rr(rr); 865 return NULL; 866 } 867 868 rr->next = parse_dns_record(pRec->pNext); 869 return rr; 870 } 871 872 ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL 873 rk_dns_lookup(const char *domain, const char *type_name) 874 { 875 DNS_STATUS status; 876 int type; 877 PDNS_RECORD pRec = NULL; 878 struct rk_dns_reply * r = NULL; 879 880 __try { 881 882 type = rk_dns_string_to_type(type_name); 883 if(type == -1) { 884 if(_resolve_debug) 885 fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n", 886 type_name); 887 return NULL; 888 } 889 890 status = DnsQuery_UTF8(domain, type, DNS_QUERY_STANDARD, NULL, 891 &pRec, NULL); 892 if (status != ERROR_SUCCESS) 893 return NULL; 894 895 r = calloc(1, sizeof(*r)); 896 r->q.domain = strdup(domain); 897 r->q.type = type; 898 r->q.class = 0; 899 900 r->head = parse_dns_record(pRec); 901 902 if (r->head == NULL) { 903 rk_dns_free_data(r); 904 return NULL; 905 } else { 906 return r; 907 } 908 909 } __finally { 910 911 if (pRec) 912 DnsRecordListFree(pRec, DnsFreeRecordList); 913 914 } 915 } 916 #endif /* HAVE_WINDNS */ 917 918 #else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */ 919 920 ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL 921 rk_dns_lookup(const char *domain, const char *type_name) 922 { 923 return NULL; 924 } 925 926 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 927 rk_dns_free_data(struct rk_dns_reply *r) 928 { 929 } 930 931 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 932 rk_dns_srv_order(struct rk_dns_reply *r) 933 { 934 } 935 936 #endif 937