13070Spst/*- 23070Spst * Copyright (c) 1985, 1988, 1993 33070Spst * The Regents of the University of California. All rights reserved. 43070Spst * 53070Spst * Redistribution and use in source and binary forms, with or without 63070Spst * modification, are permitted provided that the following conditions 73070Spst * are met: 83070Spst * 1. Redistributions of source code must retain the above copyright 93070Spst * notice, this list of conditions and the following disclaimer. 103070Spst * 2. Redistributions in binary form must reproduce the above copyright 113070Spst * notice, this list of conditions and the following disclaimer in the 123070Spst * documentation and/or other materials provided with the distribution. 133070Spst * 4. Neither the name of the University nor the names of its contributors 143070Spst * may be used to endorse or promote products derived from this software 153070Spst * without specific prior written permission. 163070Spst * 173070Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 183070Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 193070Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 203070Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 213070Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 223070Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 233070Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 243070Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 253070Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 263070Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 273070Spst * SUCH DAMAGE. 283070Spst * - 293070Spst * Portions Copyright (c) 1993 by Digital Equipment Corporation. 308870Srgrimes * 313070Spst * Permission to use, copy, modify, and distribute this software for any 323070Spst * purpose with or without fee is hereby granted, provided that the above 333070Spst * copyright notice and this permission notice appear in all copies, and that 343070Spst * the name of Digital Equipment Corporation not be used in advertising or 353070Spst * publicity pertaining to distribution of the document or software without 363070Spst * specific, written prior permission. 378870Srgrimes * 383070Spst * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 393070Spst * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 403070Spst * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 413070Spst * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 423070Spst * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 433070Spst * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 443070Spst * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 453070Spst * SOFTWARE. 463070Spst * - 473070Spst * --Copyright-- 483070Spst */ 4913408Speter/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro 5013408Speter * Dep. Matematica Universidade de Coimbra, Portugal, Europe 5113408Speter * 5213408Speter * Permission to use, copy, modify, and distribute this software for any 5313408Speter * purpose with or without fee is hereby granted, provided that the above 5413408Speter * copyright notice and this permission notice appear in all copies. 5513408Speter */ 563070Spst 573070Spst#if defined(LIBC_SCCS) && !defined(lint) 583070Spststatic char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 593070Spst#endif /* LIBC_SCCS and not lint */ 6092986Sobrien#include <sys/cdefs.h> 6192986Sobrien__FBSDID("$FreeBSD$"); 623070Spst 633070Spst#include <sys/param.h> 643070Spst#include <sys/socket.h> 653070Spst#include <netinet/in.h> 663070Spst#include <arpa/inet.h> 673070Spst#include <arpa/nameser.h> 6813408Speter 69125555Sdds#include <errno.h> 7013408Speter#include <stdio.h> 71104415Sume#include <stdlib.h> 723070Spst#include <netdb.h> 733070Spst#include <resolv.h> 743070Spst#include <ctype.h> 753070Spst#include <string.h> 7613408Speter#include <unistd.h> 773070Spst#include <syslog.h> 7865532Snectar#include <stdarg.h> 7965532Snectar#include <nsswitch.h> 803070Spst 81145626Sume#include "netdb_private.h" 8213408Speter#include "res_config.h" 833070Spst 8413408Speter#define BYADDR 0 8513408Speter#define BYNAME 1 863070Spst 87104415Sume#define MAXPACKET (64*1024) 883070Spst 893070Spsttypedef union { 9013408Speter HEADER hdr; 9113408Speter u_char buf[MAXPACKET]; 923070Spst} querybuf; 933070Spst 943070Spsttypedef union { 9513408Speter long al; 9613408Speter char ac; 973070Spst} align; 983070Spst 99125555Sdds/* 100125555Sdds * Reverse the order of first four dotted entries of in. 101125555Sdds * Out must contain space for at least strlen(in) characters. 102125555Sdds * The result does not include any leading 0s of in. 103125555Sdds */ 104125562Srustatic void 105125555Sddsipreverse(char *in, char *out) 106125555Sdds{ 107125555Sdds char *pos[4]; 108125555Sdds int len[4]; 109125555Sdds char *p, *start; 110125555Sdds int i = 0; 111125555Sdds int leading = 1; 112125555Sdds 113125555Sdds /* Fill-in element positions and lengths: pos[], len[]. */ 114125555Sdds start = p = in; 115125555Sdds for (;;) { 116125555Sdds if (*p == '.' || *p == '\0') { 117125555Sdds /* Leading 0? */ 118125555Sdds if (leading && p - start == 1 && *start == '0') 119125555Sdds len[i] = 0; 120125555Sdds else { 121125555Sdds len[i] = p - start; 122125555Sdds leading = 0; 123125555Sdds } 124125555Sdds pos[i] = start; 125125555Sdds start = p + 1; 126125555Sdds i++; 127125555Sdds } 128125555Sdds if (i == 4) 129125555Sdds break; 130125555Sdds if (*p == 0) { 131125555Sdds for (; i < 4; i++) { 132125555Sdds pos[i] = p; 133125555Sdds len[i] = 0; 134125555Sdds } 135125555Sdds break; 136125555Sdds } 137125555Sdds p++; 138125555Sdds } 139125555Sdds 140125555Sdds /* Copy the entries in reverse order */ 141125555Sdds p = out; 142125555Sdds leading = 1; 143125555Sdds for (i = 3; i >= 0; i--) { 144125555Sdds memcpy(p, pos[i], len[i]); 145125555Sdds if (len[i]) 146125555Sdds leading = 0; 147125555Sdds p += len[i]; 148125555Sdds /* Need a . separator? */ 149125555Sdds if (!leading && i > 0 && len[i - 1]) 150125555Sdds *p++ = '.'; 151125555Sdds } 152125555Sdds *p = '\0'; 153125555Sdds} 154125555Sdds 155145626Sumestatic int 156145626Sumegetnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne, 157156960Sume struct netent_data *ned, res_state statp) 1583070Spst{ 1593070Spst 16092889Sobrien HEADER *hp; 16192889Sobrien u_char *cp; 16292889Sobrien int n; 16313408Speter u_char *eom; 164125562Sru int type, class, ancount, qdcount, haveanswer; 165125555Sdds char aux[MAXHOSTNAMELEN]; 166145626Sume char ans[MAXHOSTNAMELEN]; 167125555Sdds char *in, *bp, *ep, **ap; 1683070Spst 1693070Spst /* 1703070Spst * find first satisfactory answer 1713070Spst * 1723070Spst * answer --> +------------+ ( MESSAGE ) 1733070Spst * | Header | 1743070Spst * +------------+ 1753070Spst * | Question | the question for the name server 1763070Spst * +------------+ 1773070Spst * | Answer | RRs answering the question 1783070Spst * +------------+ 1793070Spst * | Authority | RRs pointing toward an authority 1803070Spst * | Additional | RRs holding additional information 1813070Spst * +------------+ 1823070Spst */ 1833070Spst eom = answer->buf + anslen; 1843070Spst hp = &answer->hdr; 1853070Spst ancount = ntohs(hp->ancount); /* #/records in the answer section */ 1863070Spst qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ 187145626Sume bp = ned->netbuf; 188145626Sume ep = ned->netbuf + sizeof(ned->netbuf); 1893070Spst cp = answer->buf + HFIXEDSZ; 1903070Spst if (!qdcount) { 1913070Spst if (hp->aa) 192156960Sume RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 1933070Spst else 194156960Sume RES_SET_H_ERRNO(statp, TRY_AGAIN); 195157779Sume return (-1); 1963070Spst } 19713408Speter while (qdcount-- > 0) 1983070Spst cp += __dn_skipname(cp, eom) + QFIXEDSZ; 199145626Sume ap = ned->net_aliases; 2003070Spst *ap = NULL; 201145626Sume ne->n_aliases = ned->net_aliases; 2023070Spst haveanswer = 0; 2033070Spst while (--ancount >= 0 && cp < eom) { 20498865Simp n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 20517903Speter if ((n < 0) || !res_dnok(bp)) 2063070Spst break; 2073070Spst cp += n; 2083070Spst ans[0] = '\0'; 20932299Simp (void)strncpy(&ans[0], bp, sizeof(ans) - 1); 21032299Simp ans[sizeof(ans) - 1] = '\0'; 2113070Spst GETSHORT(type, cp); 2123070Spst GETSHORT(class, cp); 2133070Spst cp += INT32SZ; /* TTL */ 2143070Spst GETSHORT(n, cp); 2153070Spst if (class == C_IN && type == T_PTR) { 21698865Simp n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 21717903Speter if ((n < 0) || !res_hnok(bp)) { 2183070Spst cp += n; 219157779Sume return (-1); 2203070Spst } 221157779Sume cp += n; 2223070Spst *ap++ = bp; 22398860Simp n = strlen(bp) + 1; 22498860Simp bp += n; 225145626Sume ne->n_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 2263070Spst haveanswer++; 2273070Spst } 2283070Spst } 2293070Spst if (haveanswer) { 2303070Spst *ap = NULL; 2313070Spst switch (net_i) { 23213408Speter case BYADDR: 233145626Sume ne->n_name = *ne->n_aliases; 234145626Sume ne->n_net = 0L; 2353070Spst break; 23613408Speter case BYNAME: 237145626Sume in = *ne->n_aliases; 238145626Sume n = strlen(ans) + 1; 239145626Sume if (ep - bp < n) { 240156960Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 241145626Sume errno = ENOBUFS; 242157779Sume return (-1); 243145626Sume } 244145626Sume strlcpy(bp, ans, ep - bp); 245145626Sume ne->n_name = bp; 246125555Sdds if (strlen(in) + 1 > sizeof(aux)) { 247156960Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 248125555Sdds errno = ENOBUFS; 249157779Sume return (-1); 250125555Sdds } 251125555Sdds ipreverse(in, aux); 252145626Sume ne->n_net = inet_network(aux); 25313408Speter break; 2543070Spst } 255145626Sume ne->n_aliases++; 256157779Sume return (0); 2573070Spst } 258156960Sume RES_SET_H_ERRNO(statp, TRY_AGAIN); 259157779Sume return (-1); 2603070Spst} 2613070Spst 26265532Snectarint 26365532Snectar_dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) 2643070Spst{ 265146244Sume uint32_t net; 26665532Snectar int net_type; 267157779Sume char *buffer; 268157779Sume size_t buflen; 269157779Sume int *errnop, *h_errnop; 270157779Sume struct netent *nptr, ne; 271145626Sume struct netent_data *ned; 27213408Speter unsigned int netbr[4]; 273145626Sume int nn, anslen, error; 274104415Sume querybuf *buf; 27513408Speter char qbuf[MAXDNAME]; 276146244Sume uint32_t net2; 277156960Sume res_state statp; 2783070Spst 279146244Sume net = va_arg(ap, uint32_t); 28065532Snectar net_type = va_arg(ap, int); 281157779Sume nptr = va_arg(ap, struct netent *); 282157779Sume buffer = va_arg(ap, char *); 283157779Sume buflen = va_arg(ap, size_t); 284157779Sume errnop = va_arg(ap, int *); 285157779Sume h_errnop = va_arg(ap, int *); 28665532Snectar 287156960Sume statp = __res_state(); 288156960Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 289156960Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 290157779Sume *h_errnop = statp->res_h_errno; 291157779Sume return (NS_UNAVAIL); 292156960Sume } 293156960Sume 294157779Sume if ((ned = __netent_data_init()) == NULL) { 295157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 296157779Sume *h_errnop = statp->res_h_errno; 297157779Sume return (NS_UNAVAIL); 298157779Sume } 299157779Sume 300157779Sume *((struct netent **)rval) = NULL; 301157779Sume 302157779Sume if (net_type != AF_INET) { 303157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 304157779Sume *h_errnop = statp->res_h_errno; 305157779Sume return (NS_UNAVAIL); 306157779Sume } 307157779Sume 30813408Speter for (nn = 4, net2 = net; net2; net2 >>= 8) 3093070Spst netbr[--nn] = net2 & 0xff; 3103070Spst switch (nn) { 31113408Speter case 3: /* Class A */ 31213408Speter sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); 31313408Speter break; 31413408Speter case 2: /* Class B */ 31513408Speter sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); 31613408Speter break; 31713408Speter case 1: /* Class C */ 31813408Speter sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], 31913408Speter netbr[1]); 32013408Speter break; 32113408Speter case 0: /* Class D - E */ 32213408Speter sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], 32313408Speter netbr[1], netbr[0]); 32413408Speter break; 3253070Spst } 326104415Sume if ((buf = malloc(sizeof(*buf))) == NULL) { 327156960Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 328157779Sume *h_errnop = statp->res_h_errno; 329157779Sume return (NS_NOTFOUND); 330104415Sume } 331156960Sume anslen = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf, 332156960Sume sizeof(*buf)); 3333070Spst if (anslen < 0) { 334104415Sume free(buf); 33513408Speter#ifdef DEBUG 336156960Sume if (statp->options & RES_DEBUG) 337156960Sume printf("res_nsearch failed\n"); 33813408Speter#endif 339157779Sume *h_errnop = statp->res_h_errno; 340157779Sume return (NS_UNAVAIL); 341104415Sume } else if (anslen > sizeof(*buf)) { 342104415Sume free(buf); 343103350Snectar#ifdef DEBUG 344156960Sume if (statp->options & RES_DEBUG) 345156960Sume printf("res_nsearch static buffer too small\n"); 346103350Snectar#endif 347157779Sume *h_errnop = statp->res_h_errno; 348157779Sume return (NS_UNAVAIL); 3493070Spst } 350157779Sume error = getnetanswer(buf, anslen, BYADDR, &ne, ned, statp); 351104415Sume free(buf); 352145626Sume if (error == 0) { 3533070Spst /* Strip trailing zeros */ 354146244Sume while ((net & 0xff) == 0 && net != 0) 355146244Sume net >>= 8; 356157779Sume ne.n_net = net; 357157779Sume if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { 358211276Sume *errnop = errno; 359211276Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 360157779Sume *h_errnop = statp->res_h_errno; 361211276Sume return (NS_RETURN); 362157779Sume } 363157779Sume *((struct netent **)rval) = nptr; 364157779Sume return (NS_SUCCESS); 3653070Spst } 366157779Sume *h_errnop = statp->res_h_errno; 367157779Sume return (NS_NOTFOUND); 3683070Spst} 3693070Spst 37065532Snectarint 37165532Snectar_dns_getnetbyname(void *rval, void *cb_data, va_list ap) 3723070Spst{ 37365532Snectar const char *net; 374157779Sume char *buffer; 375157779Sume size_t buflen; 376157779Sume int *errnop, *h_errnop; 377157779Sume struct netent *nptr, ne; 378145626Sume struct netent_data *ned; 379145626Sume int anslen, error; 380104415Sume querybuf *buf; 38113408Speter char qbuf[MAXDNAME]; 382156960Sume res_state statp; 3838870Srgrimes 38465532Snectar net = va_arg(ap, const char *); 385157779Sume nptr = va_arg(ap, struct netent *); 386157779Sume buffer = va_arg(ap, char *); 387157779Sume buflen = va_arg(ap, size_t); 388157779Sume errnop = va_arg(ap, int *); 389157779Sume h_errnop = va_arg(ap, int *); 39065532Snectar 391156960Sume statp = __res_state(); 392156960Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 393156960Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 394157779Sume *h_errnop = statp->res_h_errno; 395157779Sume return (NS_UNAVAIL); 39613408Speter } 397157779Sume if ((ned = __netent_data_init()) == NULL) { 398157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 399157779Sume *h_errnop = statp->res_h_errno; 400157779Sume return (NS_UNAVAIL); 401157779Sume } 402104415Sume if ((buf = malloc(sizeof(*buf))) == NULL) { 403156960Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 404157779Sume *h_errnop = statp->res_h_errno; 405157779Sume return (NS_NOTFOUND); 406104415Sume } 407157779Sume 408157779Sume *((struct netent **)rval) = NULL; 409157779Sume 41032299Simp strncpy(qbuf, net, sizeof(qbuf) - 1); 41132299Simp qbuf[sizeof(qbuf) - 1] = '\0'; 412156960Sume anslen = res_nsearch(statp, qbuf, C_IN, T_PTR, (u_char *)buf, 413156960Sume sizeof(*buf)); 4143070Spst if (anslen < 0) { 415104415Sume free(buf); 41613408Speter#ifdef DEBUG 417156960Sume if (statp->options & RES_DEBUG) 418156960Sume printf("res_nsearch failed\n"); 41913408Speter#endif 420157779Sume return (NS_UNAVAIL); 421104415Sume } else if (anslen > sizeof(*buf)) { 422104415Sume free(buf); 423103350Snectar#ifdef DEBUG 424156960Sume if (statp->options & RES_DEBUG) 425103630Snectar printf("res_search static buffer too small\n"); 426103350Snectar#endif 427157779Sume return (NS_UNAVAIL); 4283070Spst } 429157779Sume error = getnetanswer(buf, anslen, BYNAME, &ne, ned, statp); 430104415Sume free(buf); 431157779Sume if (error != 0) { 432157779Sume *h_errnop = statp->res_h_errno; 433157779Sume return (NS_NOTFOUND); 434157779Sume } 435157779Sume if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { 436211276Sume *errnop = errno; 437211276Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 438157779Sume *h_errnop = statp->res_h_errno; 439211276Sume return (NS_RETURN); 440157779Sume } 441157779Sume *((struct netent **)rval) = nptr; 442157779Sume return (NS_SUCCESS); 4433070Spst} 4443070Spst 4453070Spstvoid 446157779Sume_setnetdnsent(int stayopen) 4473070Spst{ 448156960Sume res_state statp; 449156960Sume 450156960Sume statp = __res_state(); 451156960Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) 452156960Sume return; 4533070Spst if (stayopen) 454156960Sume statp->options |= RES_STAYOPEN | RES_USEVC; 4553070Spst} 4563070Spst 4573070Spstvoid 4583070Spst_endnetdnsent() 4593070Spst{ 460156960Sume res_state statp; 461156960Sume 462156960Sume statp = __res_state(); 463156960Sume statp->options &= ~(RES_STAYOPEN | RES_USEVC); 464156960Sume res_nclose(statp); 4653070Spst} 466