Changeset 753 for pjproject/trunk/pjlib-util/src/pjlib-util/dns.c
- Timestamp:
- Oct 8, 2006 12:39:34 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/dns.c
r745 r753 26 26 27 27 28 PJ_DEF(const char *) pj_dns_get_type_name(int type) 29 { 30 switch (type) { 31 case PJ_DNS_TYPE_A: return "A"; 32 case PJ_DNS_TYPE_SRV: return "SRV"; 33 case PJ_DNS_TYPE_NS: return "NS"; 34 case PJ_DNS_TYPE_CNAME: return "CNAME"; 35 case PJ_DNS_TYPE_PTR: return "PTR"; 36 case PJ_DNS_TYPE_MX: return "MX"; 37 case PJ_DNS_TYPE_TXT: return "TXT"; 38 case PJ_DNS_TYPE_NAPTR: return "NAPTR"; 39 } 40 return "(Unknown)"; 41 } 42 43 28 44 /** 29 45 * Initialize a DNS query transaction. … … 32 48 unsigned *size, 33 49 pj_uint16_t id, 34 pj_dns_typeqtype,50 int qtype, 35 51 const pj_str_t *name) 36 52 { … … 225 241 226 242 /* Skip query records. */ 227 static pj_status_t skip_query(const char *pkt, const char *start, 228 const char *max, int *skip_len) 229 { 230 int name_len = 0; 243 static pj_status_t parse_query(pj_dns_parsed_query *q, pj_pool_t *pool, 244 const char *pkt, const char *start, 245 const char *max, int *parsed_len) 246 { 247 const char *p = start; 248 int name_len, name_part_len; 231 249 pj_status_t status; 232 250 233 status = get_name_len(0, pkt, start, max, skip_len, &name_len); 251 /* Get the length of the name */ 252 status = get_name_len(0, pkt, start, max, &name_part_len, &name_len); 234 253 if (status != PJ_SUCCESS) 235 254 return status; 236 255 237 (*skip_len) += 4; 256 /* Allocate memory for the name */ 257 q->name.ptr = pj_pool_alloc(pool, name_len+4); 258 q->name.slen = 0; 259 260 /* Get the name */ 261 status = get_name(0, pkt, start, max, &q->name); 262 if (status != PJ_SUCCESS) 263 return status; 264 265 p = (start + name_part_len); 266 267 /* Get the type */ 268 pj_memcpy(&q->type, p, 2); 269 q->type = pj_ntohs(q->type); 270 p += 2; 271 272 /* Get the class */ 273 pj_memcpy(&q->dnsclass, p, 2); 274 q->dnsclass = pj_ntohs(q->dnsclass); 275 p += 2; 276 277 *parsed_len = (int)(p - start); 278 238 279 return PJ_SUCCESS; 239 280 } … … 276 317 277 318 /* Get the class */ 278 pj_memcpy(&rr-> class_, p, 2);279 rr-> class_ = pj_ntohs(rr->class_);319 pj_memcpy(&rr->dnsclass, p, 2); 320 rr->dnsclass = pj_ntohs(rr->dnsclass); 280 321 p += 2; 281 322 282 323 /* Class MUST be IN */ 283 if (rr-> class_!= 1)324 if (rr->dnsclass != 1) 284 325 return PJLIB_UTIL_EDNSINCLASS; 285 326 … … 297 338 if (p + rr->rdlength > max) 298 339 return PJLIB_UTIL_EDNSINSIZE; 299 300 /* Copy the raw data */301 rr->data = pj_pool_alloc(pool, rr->rdlength);302 pj_memcpy(rr->data, p, rr->rdlength);303 340 304 341 /* Parse some well known records */ … … 365 402 366 403 } else { 404 /* Copy the raw data */ 405 rr->data = pj_pool_alloc(pool, rr->rdlength); 406 pj_memcpy(rr->data, p, rr->rdlength); 407 367 408 p += rr->rdlength; 368 409 } … … 374 415 375 416 /* 376 * Parse raw DNS response packet into DNS responsestructure.417 * Parse raw DNS packet into DNS packet structure. 377 418 */ 378 PJ_DEF(pj_status_t) pj_dns_parse_ response( pj_pool_t *pool,379 380 381 pj_dns_parsed_response**p_res)382 { 383 pj_dns_parsed_ response*res;419 PJ_DEF(pj_status_t) pj_dns_parse_packet( pj_pool_t *pool, 420 const void *packet, 421 unsigned size, 422 pj_dns_parsed_packet **p_res) 423 { 424 pj_dns_parsed_packet *res; 384 425 char *start, *end; 385 426 pj_status_t status; … … 393 434 return PJLIB_UTIL_EDNSINSIZE; 394 435 395 /* Create the response */396 res = pj_pool_zalloc(pool, sizeof(pj_dns_parsed_ response));436 /* Create the structure */ 437 res = pj_pool_zalloc(pool, sizeof(pj_dns_parsed_packet)); 397 438 398 439 /* Copy the DNS header, and convert endianness to host byte order */ … … 409 450 end = ((char*)packet) + size; 410 451 411 /* If we have query records (some DNS servers do send them), skip 412 * the records. 452 /* Parse query records (if any). 413 453 */ 414 for (i=0; i<res->hdr.qdcount; ++i) { 415 int skip_len; 416 417 status = skip_query(packet, start, end, &skip_len); 418 if (status != PJ_SUCCESS) 419 return status; 420 421 start += skip_len; 454 if (res->hdr.qdcount) { 455 res->q = pj_pool_zalloc(pool, res->hdr.qdcount * 456 sizeof(pj_dns_parsed_query)); 457 for (i=0; i<res->hdr.qdcount; ++i) { 458 int parsed_len; 459 460 status = parse_query(&res->q[i], pool, packet, start, end, 461 &parsed_len); 462 if (status != PJ_SUCCESS) 463 return status; 464 465 start += parsed_len; 466 } 422 467 } 423 468 … … 478 523 return PJ_SUCCESS; 479 524 } 525 526 527 /* Perform name compression scheme. 528 * If a name is already in the nametable, when no need to duplicate 529 * the string with the pool, but rather just use the pointer there. 530 */ 531 static void apply_name_table( unsigned *count, 532 pj_str_t nametable[], 533 const pj_str_t *src, 534 pj_pool_t *pool, 535 pj_str_t *dst) 536 { 537 unsigned i; 538 539 /* Scan strings in nametable */ 540 for (i=0; i<*count; ++i) { 541 if (pj_stricmp(&nametable[i], src) == 0) 542 break; 543 } 544 545 /* If name is found in nametable, use the pointer in the nametable */ 546 if (i != *count) { 547 dst->ptr = nametable[i].ptr; 548 dst->slen = nametable[i].slen; 549 return; 550 } 551 552 /* Otherwise duplicate the string, and insert new name in nametable */ 553 pj_strdup(pool, dst, src); 554 555 if (*count < PJ_DNS_MAX_NAMES_IN_NAMETABLE) { 556 nametable[*count].ptr = dst->ptr; 557 nametable[*count].slen = dst->slen; 558 559 ++(*count); 560 } 561 } 562 563 static void copy_query(pj_pool_t *pool, pj_dns_parsed_query *dst, 564 const pj_dns_parsed_query *src, 565 unsigned *nametable_count, 566 pj_str_t nametable[]) 567 { 568 pj_memcpy(dst, src, sizeof(*src)); 569 apply_name_table(nametable_count, nametable, &src->name, pool, &dst->name); 570 } 571 572 573 static void copy_rr(pj_pool_t *pool, pj_dns_parsed_rr *dst, 574 const pj_dns_parsed_rr *src, 575 unsigned *nametable_count, 576 pj_str_t nametable[]) 577 { 578 pj_memcpy(dst, src, sizeof(*src)); 579 apply_name_table(nametable_count, nametable, &src->name, pool, &dst->name); 580 581 if (src->data) { 582 dst->data = pj_pool_alloc(pool, src->rdlength); 583 pj_memcpy(dst->data, src->data, src->rdlength); 584 } 585 586 if (src->type == PJ_DNS_TYPE_SRV) { 587 apply_name_table(nametable_count, nametable, &src->rdata.srv.target, 588 pool, &dst->rdata.srv.target); 589 } else if (src->type == PJ_DNS_TYPE_A) { 590 pj_strdup(pool, &dst->rdata.a.ip_addr, &src->rdata.a.ip_addr); 591 } else if (src->type == PJ_DNS_TYPE_CNAME) { 592 pj_strdup(pool, &dst->rdata.cname.name, &src->rdata.cname.name); 593 } else if (src->type == PJ_DNS_TYPE_NS) { 594 pj_strdup(pool, &dst->rdata.ns.name, &src->rdata.ns.name); 595 } else if (src->type == PJ_DNS_TYPE_PTR) { 596 pj_strdup(pool, &dst->rdata.ptr.name, &src->rdata.ptr.name); 597 } 598 } 599 600 /* 601 * Duplicate DNS packet. 602 */ 603 PJ_DEF(void) pj_dns_packet_dup(pj_pool_t *pool, 604 const pj_dns_parsed_packet*p, 605 pj_dns_parsed_packet **p_dst) 606 { 607 pj_dns_parsed_packet *dst; 608 unsigned nametable_count = 0; 609 #if PJ_DNS_MAX_NAMES_IN_NAMETABLE 610 pj_str_t nametable[PJ_DNS_MAX_NAMES_IN_NAMETABLE]; 611 #else 612 pj_str_t *nametable = NULL; 613 #endif 614 unsigned i; 615 616 PJ_ASSERT_ON_FAIL(pool && p && p_dst, return); 617 618 /* Create packet and copy header */ 619 *p_dst = dst = pj_pool_zalloc(pool, sizeof(pj_dns_parsed_packet)); 620 pj_memcpy(&dst->hdr, &p->hdr, sizeof(p->hdr)); 621 622 /* Initialize section counts in the target packet to zero. 623 * If memory allocation fails during copying process, the target packet 624 * should have a correct section counts. 625 */ 626 dst->hdr.qdcount = 0; 627 dst->hdr.anscount = 0; 628 dst->hdr.nscount = 0; 629 dst->hdr.arcount = 0; 630 631 632 /* Copy query section */ 633 if (p->hdr.qdcount) { 634 dst->q = pj_pool_alloc(pool, p->hdr.qdcount * 635 sizeof(pj_dns_parsed_query)); 636 for (i=0; i<p->hdr.qdcount; ++i) { 637 copy_query(pool, &dst->q[i], &p->q[i], 638 &nametable_count, nametable); 639 ++dst->hdr.qdcount; 640 } 641 } 642 643 /* Copy answer section */ 644 if (p->hdr.anscount) { 645 dst->ans = pj_pool_alloc(pool, p->hdr.anscount * 646 sizeof(pj_dns_parsed_rr)); 647 for (i=0; i<p->hdr.anscount; ++i) { 648 copy_rr(pool, &dst->ans[i], &p->ans[i], 649 &nametable_count, nametable); 650 ++dst->hdr.anscount; 651 } 652 } 653 654 /* Copy NS section */ 655 if (p->hdr.nscount) { 656 dst->ns = pj_pool_alloc(pool, p->hdr.nscount * 657 sizeof(pj_dns_parsed_rr)); 658 for (i=0; i<p->hdr.nscount; ++i) { 659 copy_rr(pool, &dst->ns[i], &p->ns[i], 660 &nametable_count, nametable); 661 ++dst->hdr.nscount; 662 } 663 } 664 665 /* Copy additional info section */ 666 if (p->hdr.arcount) { 667 dst->arr = pj_pool_alloc(pool, p->hdr.arcount * 668 sizeof(pj_dns_parsed_rr)); 669 for (i=0; i<p->hdr.arcount; ++i) { 670 copy_rr(pool, &dst->arr[i], &p->arr[i], 671 &nametable_count, nametable); 672 ++dst->hdr.arcount; 673 } 674 } 675 } 676
Note: See TracChangeset
for help on using the changeset viewer.