/* * Fill the hostent from the given DNS packet. */ static int hostent_from_packet(struct hostent *h, int action, char *pkt, size_t pktlen) { struct packed p; struct header hdr; struct query q; struct rr rr; int r; packed_init(&p, pkt, pktlen); unpack_header(&p, &hdr); for(; hdr.qdcount; hdr.qdcount--) unpack_query(&p, &q); for(; hdr.ancount; hdr.ancount--) { unpack_rr(&p, &rr); if (rr.rr_class != C_IN) continue; switch (rr.rr_type) { case T_CNAME: if (action == ASR_GETHOSTBYNAME) r = hostent_add_alias(h, rr.rr_dname, 1); else r = hostent_set_cname(h, rr.rr_dname, 1); break; case T_PTR: if (action != ASR_GETHOSTBYADDR) continue; r = hostent_set_cname(h, rr.rr.ptr.ptrname, 1); /* XXX See if we need MULTI_PTRS_ARE_ALIASES */ break; case T_A: if (h->h_addrtype != AF_INET) break; r = hostent_set_cname(h, rr.rr_dname, 1); r = hostent_add_addr(h, &rr.rr.in_a.addr, 4); break; case T_AAAA: if (h->h_addrtype != AF_INET6) break; r = hostent_set_cname(h, rr.rr_dname, 1); r = hostent_add_addr(h, &rr.rr.in_aaaa.addr6, 16); break; } } return (0); }
/* * Fill the hostent from the given DNS packet. */ static struct hostent * hostent_from_packet(int reqtype, int family, char *pkt, size_t pktlen) { struct hostent *h; struct packed p; struct header hdr; struct query q; struct rr rr; if ((h = hostent_alloc(family)) == NULL) return (NULL); packed_init(&p, pkt, pktlen); unpack_header(&p, &hdr); for(; hdr.qdcount; hdr.qdcount--) unpack_query(&p, &q); for(; hdr.ancount; hdr.ancount--) { unpack_rr(&p, &rr); if (rr.rr_class != C_IN) continue; switch (rr.rr_type) { case T_CNAME: if (reqtype == ASR_GETHOSTBYNAME) { if (hostent_add_alias(h, rr.rr_dname, 1) == -1) goto fail; } else { if (hostent_set_cname(h, rr.rr_dname, 1) == -1) goto fail; } break; case T_PTR: if (reqtype != ASR_GETHOSTBYADDR) break; if (hostent_set_cname(h, rr.rr.ptr.ptrname, 1) == -1) goto fail; /* XXX See if we need MULTI_PTRS_ARE_ALIASES */ break; case T_A: if (reqtype != ASR_GETHOSTBYNAME) break; if (family != AF_INET) break; if (hostent_set_cname(h, rr.rr_dname, 1) == -1) goto fail; if (hostent_add_addr(h, &rr.rr.in_a.addr, 4) == -1) goto fail; break; case T_AAAA: if (reqtype != ASR_GETHOSTBYNAME) break; if (family != AF_INET6) break; if (hostent_set_cname(h, rr.rr_dname, 1) == -1) goto fail; if (hostent_add_addr(h, &rr.rr.in_aaaa.addr6, 16) == -1) goto fail; break; } } return (h); fail: free(h); return (NULL); }