Changeset 59167 in vbox
- Timestamp:
- Dec 17, 2015 2:42:48 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 104757
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/hostres.c
r59159 r59167 108 108 static int verify_header(PNATState pData, struct mbuf **pMBuf); 109 109 static struct mbuf *respond(PNATState pData, struct mbuf *m, struct response *res); 110 struct mbuf *resolve(PNATState pData, struct mbuf *m, struct response *res, size_t qname, uint16_t qtype); 110 struct mbuf *resolve(PNATState pData, struct mbuf *m, struct response *res, 111 uint16_t qtype, size_t qname); 112 struct mbuf *resolve_reverse(PNATState pData, struct mbuf *m, struct response *res, 113 uint16_t qtype, size_t qname, struct in_addr addr); 111 114 struct mbuf *refuse(PNATState pData, struct mbuf *m, unsigned int rcode); 112 115 static ssize_t append_a(struct response *res, const char *name, struct in_addr addr); 113 116 static ssize_t append_cname(struct response *res, const char *name, const char *cname); 117 static ssize_t append_ptr(struct response *res, const char *inaddrname, const char *name); 118 static ssize_t append_name_rr(struct response *res, const char *question, int type, const char *answer); 114 119 static ssize_t append_rrhdr(struct response *res, const char *name, uint16_t type, uint32_t ttl); 115 120 static ssize_t append_name(struct response *res, const char *name); … … 120 125 static ssize_t check_space(struct response *res, size_t size); 121 126 127 static int get_in_addr_arpa(struct in_addr *paddr, struct label *root); 128 static int labelstrcmp(struct label *l, const char *s); 122 129 static void strnlabels(char *namebuf, size_t nbuflen, const uint8_t *msg, size_t off); 123 130 … … 282 289 size_t qname; 283 290 uint16_t qtype, qclass; 291 struct in_addr in_addr_arpa; 284 292 struct label *l; 285 293 … … 400 408 if ( qtype != Type_A 401 409 && qtype != Type_CNAME 410 && qtype != Type_PTR 402 411 && qtype != Type_ANY) 403 412 { … … 406 415 } 407 416 408 return resolve(pData, m, res, qname, qtype); 417 /* 418 * Check for IN-ADDR.ARPA. Use the fact that res->labels at this 419 * point contains only the qname, so we have easy top-down access 420 * to its components. 421 */ 422 if (get_in_addr_arpa(&in_addr_arpa, res->labels)) 423 return resolve_reverse(pData, m, res, qtype, qname, in_addr_arpa); 424 else 425 return resolve(pData, m, res, qtype, qname); 409 426 } 410 427 … … 412 429 struct mbuf * 413 430 resolve(PNATState pData, struct mbuf *m, struct response *res, 414 size_t qname, uint16_t qtype)431 uint16_t qtype, size_t qname) 415 432 { 416 433 struct dnsmsg_header *pHdr; … … 429 446 strnlabels(name, sizeof(name), res->buf, qname); 430 447 LogDbg(("NAT: hostres: qname=\"%s\"\n", name)); 448 449 if (qtype != Type_A && qtype != Type_CNAME && qtype != Type_ANY) 450 { 451 goto out; /* NB: RCode_NoError without an answer, not RCode_NXDomain */ 452 } 453 431 454 432 455 h = gethostbyname(name); … … 551 574 552 575 576 struct mbuf * 577 resolve_reverse(PNATState pData, struct mbuf *m, struct response *res, 578 uint16_t qtype, size_t qname, struct in_addr in_addr_arpa) 579 { 580 struct dnsmsg_header *pHdr; 581 struct hostent *h; 582 size_t oend; 583 size_t nanswers; 584 ssize_t nbytes; 585 int i; 586 587 pHdr = (struct dnsmsg_header *)res->buf; 588 nanswers = 0; 589 oend = res->end; 590 591 LogDbg(("NAT: hostres: %RTnaipv4\n", in_addr_arpa.s_addr)); 592 593 if (qtype != Type_PTR && qtype != Type_ANY) 594 { 595 /* can't answer CNAME to PTR queries using gethostby* */ 596 goto out; /* NB: RCode_NoError without an answer, not RCode_NXDomain */ 597 } 598 599 /* XXX: TODO: apply HostResolverMappings */ 600 h = gethostbyaddr(&in_addr_arpa, sizeof(struct in_addr), AF_INET); 601 if (h == NULL) 602 { 603 /* LogErr: h_errno */ 604 return refuse(pData, m, RCode_NXDomain); 605 } 606 607 if (h->h_name != NULL) 608 { 609 char name[DNS_MAX_NAME_LEN+1]; 610 strnlabels(name, sizeof(name), res->buf, qname); 611 612 LogDbg(("NAT: hostres: %s PTR %s\n", name, h->h_name)); 613 nbytes = append_ptr(res, name, h->h_name); 614 if (nbytes > 0) 615 { 616 ++nanswers; 617 } 618 else 619 { 620 LogErr(("NAT: hostres: failed to add %s PTR %s\n", 621 name, h->h_name)); 622 if (nbytes < 0) 623 return refuse(pData, m, RCode_ServFail); 624 else 625 { 626 pHdr->tc = 1; 627 goto out; 628 } 629 } 630 } 631 632 out: 633 if (nanswers > 0) 634 { 635 int ok = m_append(pData, m, res->end - oend, (caddr_t)&res->buf[oend]); 636 if (!ok) 637 { 638 /* XXX: this may fail part way: restore old lenght, clear TC? */ 639 return refuse(pData, m, RCode_ServFail); 640 } 641 pHdr->ancount = RT_H2N_U16(nanswers); 642 } 643 memcpy(mtod(m, char *), res->buf, sizeof(struct dnsmsg_header)); 644 return m; 645 } 646 647 553 648 554 649 #define APPEND_PROLOGUE() \ … … 601 696 append_cname(struct response *res, const char *name, const char *cname) 602 697 { 698 return append_name_rr(res, name, Type_CNAME, cname); 699 } 700 701 702 /* 703 * PTR RR - rfc1035#section-3.3.12 704 */ 705 static ssize_t 706 append_ptr(struct response *res, const char *inaddrname, const char *name) 707 { 708 return append_name_rr(res, inaddrname, Type_PTR, name); 709 } 710 711 712 static ssize_t 713 append_name_rr(struct response *res, const char *question, 714 int type, const char *answer) 715 { 603 716 size_t rdlpos; 604 717 uint16_t rdlength; … … 606 719 APPEND_PROLOGUE(); 607 720 608 CHECKED( append_rrhdr(res, name, Type_CNAME, 3600) );721 CHECKED( append_rrhdr(res, question, type, 3600) ); 609 722 610 723 rdlpos = res->end; 611 724 CHECKED( append_u16(res, 0) ); /* RDLENGTH placeholder */ 612 725 613 CHECKED( append_name(res, cname) );726 CHECKED( append_name(res, answer) ); 614 727 615 728 rdlength = RT_H2N_U16(nbytes); … … 851 964 852 965 return size; 966 } 967 968 969 static int 970 get_in_addr_arpa(struct in_addr *paddr, struct label *root) 971 { 972 RTNETADDRIPV4 addr; 973 struct label *l; 974 int i; 975 976 l = root; 977 if (l == NULL || labelstrcmp(l, "arpa") != 0) 978 return 0; 979 980 l = l->children; 981 if (l == NULL || labelstrcmp(l, "in-addr") != 0) 982 return 0; 983 984 for (i = 0; i < 4; ++i) 985 { 986 char buf[4]; 987 size_t llen; 988 int rc; 989 uint8_t octet; 990 991 l = l->children; 992 if (l == NULL) 993 return 0; 994 995 llen = l->buf[l->off]; 996 Assert((llen & DNS_LABEL_PTR) == 0); 997 998 /* valid octet values are at most 3 digits */ 999 if (llen > 3) 1000 return 0; 1001 1002 /* copy to avoid dealing with trailing bytes */ 1003 memcpy(buf, &l->buf[l->off + 1], llen); 1004 buf[llen] = '\0'; 1005 1006 rc = RTStrToUInt8Full(buf, 10, &octet); 1007 if (rc != VINF_SUCCESS) 1008 return 0; 1009 1010 addr.au8[i] = octet; 1011 } 1012 1013 if (l->children != NULL) 1014 return 0; /* too many components */ 1015 1016 if (paddr != NULL) 1017 paddr->s_addr = addr.u; 1018 1019 return 1; 1020 } 1021 1022 1023 /* 1024 * Compare label with string. 1025 */ 1026 static int 1027 labelstrcmp(struct label *l, const char *s) 1028 { 1029 size_t llen; 1030 1031 llen = l->buf[l->off]; 1032 Assert((llen & DNS_LABEL_PTR) == 0); 1033 1034 return RTStrNICmp((char *)&l->buf[l->off + 1], s, llen); 853 1035 } 854 1036
Note:
See TracChangeset
for help on using the changeset viewer.