110015Speter/*- 212496Speter * SPDX-License-Identifier: BSD-3-Clause 310015Speter * 434832Speter * Copyright (c) 1985, 1988, 1993 510015Speter * The Regents of the University of California. All rights reserved. 656505Speter * 710015Speter * Redistribution and use in source and binary forms, with or without 810015Speter * modification, are permitted provided that the following conditions 910015Speter * are met: 1010015Speter * 1. Redistributions of source code must retain the above copyright 1110015Speter * notice, this list of conditions and the following disclaimer. 1210015Speter * 2. Redistributions in binary form must reproduce the above copyright 1310015Speter * notice, this list of conditions and the following disclaimer in the 1410015Speter * documentation and/or other materials provided with the distribution. 1510015Speter * 3. Neither the name of the University nor the names of its contributors 1610015Speter * may be used to endorse or promote products derived from this software 1710015Speter * without specific prior written permission. 1810015Speter * 1910015Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2010015Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2110015Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2210015Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2310015Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2410015Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2510015Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2610015Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2710015Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2810015Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2910015Speter * SUCH DAMAGE. 3010015Speter * - 3110015Speter * Portions Copyright (c) 1993 by Digital Equipment Corporation. 3210015Speter * 3310015Speter * Permission to use, copy, modify, and distribute this software for any 3410015Speter * purpose with or without fee is hereby granted, provided that the above 35119419Sobrien * copyright notice and this permission notice appear in all copies, and that 36119419Sobrien * the name of Digital Equipment Corporation not be used in advertising or 37119419Sobrien * publicity pertaining to distribution of the document or software without 3810015Speter * specific, written prior permission. 3934832Speter * 4034832Speter * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 4156505Speter * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 4210015Speter * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 4310015Speter * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 4431778Seivind * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 4532929Seivind * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46111899Sdas * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4731778Seivind * SOFTWARE. 4810015Speter * - 4910015Speter * --Copyright-- 5024207Sbde */ 5124207Sbde/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro 5224207Sbde * Dep. Matematica Universidade de Coimbra, Portugal, Europe 5310015Speter * 5410015Speter * Permission to use, copy, modify, and distribute this software for any 5524131Sbde * purpose with or without fee is hereby granted, provided that the above 5610015Speter * copyright notice and this permission notice appear in all copies. 5710015Speter */ 5815683Speter 5956498Speter#include <sys/param.h> 6056498Speter#include <sys/socket.h> 6156498Speter#include <netinet/in.h> 6256498Speter#include <arpa/inet.h> 6310015Speter#include <arpa/nameser.h> 6410015Speter 6512659Sbde#include <errno.h> 6612662Sdg#include <stdio.h> 6712659Sbde#include <stdlib.h> 6813353Speter#include <netdb.h> 6910015Speter#include <resolv.h> 7056498Speter#include <ctype.h> 7156505Speter#include <string.h> 7256498Speter#include <unistd.h> 7356498Speter#include <syslog.h> 7410015Speter#include <stdarg.h> 7510015Speter#include <nsswitch.h> 7634832Speter 7734832Speter#include "netdb_private.h" 7810015Speter#include "res_config.h" 7934832Speter 8034832Speter#define BYADDR 0 8133395Speter#define BYNAME 1 8234832Speter 8310015Speter#define MAXPACKET (64*1024) 8410015Speter 8517547Spetertypedef union { 8617547Speter HEADER hdr; 8717547Speter u_char buf[MAXPACKET]; 8812496Speter} querybuf; 8934832Speter 9034832Spetertypedef union { 9115639Speter long al; 9210015Speter char ac; 9310015Speter} align; 9410015Speter 9556498Speter/* 9656498Speter * Reverse the order of first four dotted entries of in. 9756498Speter * Out must contain space for at least strlen(in) characters. 9883366Sjulian * The result does not include any leading 0s of in. 9956498Speter */ 10056498Speterstatic void 10125047Sbdeipreverse(char *in, char *out) 10256498Speter{ 10356498Speter char *pos[4]; 10456498Speter int len[4]; 10510015Speter char *p, *start; 10656505Speter int i = 0; 10756505Speter int leading = 1; 10856505Speter 10956505Speter /* Fill-in element positions and lengths: pos[], len[]. */ 11056498Speter start = p = in; 11110015Speter for (;;) { 11256498Speter if (*p == '.' || *p == '\0') { 11356498Speter /* Leading 0? */ 11410708Speter if (leading && p - start == 1 && *start == '0') 11512675Sjulian len[i] = 0; 11612675Sjulian else { 11712675Sjulian len[i] = p - start; 11812675Sjulian leading = 0; 11912675Sjulian } 12047625Sphk pos[i] = start; 121126080Sphk start = p + 1; 122111815Sphk i++; 123111815Sphk } 124111815Sphk if (i == 4) 125111815Sphk break; 126111815Sphk if (*p == 0) { 127126080Sphk for (; i < 4; i++) { 12838485Sbde pos[i] = p; 12912675Sjulian len[i] = 0; 13010962Speter } 13110962Speter break; 13210962Speter } 13310015Speter p++; 13434832Speter } 135100743Speter 13634832Speter /* Copy the entries in reverse order */ 13756498Speter p = out; 13810044Speter leading = 1; 13956505Speter for (i = 3; i >= 0; i--) { 14056498Speter memcpy(p, pos[i], len[i]); 14112174Speter if (len[i]) 14210015Speter leading = 0; 14310015Speter p += len[i]; 14410015Speter /* Need a . separator? */ 14550442Speter if (!leading && i > 0 && len[i - 1]) 14650442Speter *p++ = '.'; 14750442Speter } 14850442Speter *p = '\0'; 14950442Speter} 15050442Speter 15150442Speterstatic int 15250442Spetergetnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne, 15350442Speter struct netent_data *ned, res_state statp) 15450442Speter{ 15550442Speter 15650442Speter HEADER *hp; 15750442Speter u_char *cp; 15850442Speter int n; 15950442Speter u_char *eom; 16010015Speter int type, class, ancount, qdcount, haveanswer; 16110015Speter char aux[MAXHOSTNAMELEN]; 16210015Speter char ans[MAXHOSTNAMELEN]; 16310015Speter char *in, *bp, *ep, **ap; 16410015Speter 16510015Speter /* 16610015Speter * find first satisfactory answer 16750442Speter * 16850442Speter * answer --> +------------+ ( MESSAGE ) 16950442Speter * | Header | 17050442Speter * +------------+ 17150442Speter * | Question | the question for the name server 17250442Speter * +------------+ 17350442Speter * | Answer | RRs answering the question 17450442Speter * +------------+ 17550442Speter * | Authority | RRs pointing toward an authority 17650442Speter * | Additional | RRs holding additional information 17750442Speter * +------------+ 17850442Speter */ 17950442Speter eom = answer->buf + anslen; 18050442Speter hp = &answer->hdr; 18150442Speter ancount = ntohs(hp->ancount); /* #/records in the answer section */ 18210015Speter qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ 18310015Speter bp = ned->netbuf; 18410015Speter ep = ned->netbuf + sizeof(ned->netbuf); 18510015Speter cp = answer->buf + HFIXEDSZ; 18615683Speter if (!qdcount) { 18756498Speter if (hp->aa) 18815639Speter RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 18916403Speter else 19017547Speter RES_SET_H_ERRNO(statp, TRY_AGAIN); 19150442Speter return (-1); 19210015Speter } 19356498Speter while (qdcount-- > 0) 19410015Speter cp += __dn_skipname(cp, eom) + QFIXEDSZ; 19510015Speter ap = ned->net_aliases; 19610015Speter *ap = NULL; 19710015Speter ne->n_aliases = ned->net_aliases; 19810015Speter haveanswer = 0; 19910015Speter while (--ancount >= 0 && cp < eom) { 20010015Speter n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 20110015Speter if ((n < 0) || !res_dnok(bp)) 20210015Speter break; 20334832Speter cp += n; 20410015Speter ans[0] = '\0'; 20510015Speter (void)strncpy(&ans[0], bp, sizeof(ans) - 1); 20633395Speter ans[sizeof(ans) - 1] = '\0'; 20733395Speter GETSHORT(type, cp); 20833395Speter GETSHORT(class, cp); 20910015Speter cp += INT32SZ; /* TTL */ 21010015Speter GETSHORT(n, cp); 21156498Speter if (class == C_IN && type == T_PTR) { 21256498Speter n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 21356498Speter if ((n < 0) || !res_hnok(bp)) { 21456498Speter cp += n; 21556498Speter return (-1); 21656498Speter } 21756498Speter cp += n; 21856498Speter *ap++ = bp; 21956498Speter n = strlen(bp) + 1; 22056498Speter bp += n; 22156498Speter ne->n_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 22256498Speter haveanswer++; 22356498Speter } 22456498Speter } 22556498Speter if (haveanswer) { 22656498Speter *ap = NULL; 22756498Speter switch (net_i) { 22856498Speter case BYADDR: 22956498Speter ne->n_name = *ne->n_aliases; 23056498Speter ne->n_net = 0L; 23156498Speter break; 23256498Speter case BYNAME: 23356498Speter in = *ne->n_aliases; 23456498Speter n = strlen(ans) + 1; 23534832Speter if (ep - bp < n) { 23610015Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 23710015Speter errno = ENOBUFS; 23856505Speter return (-1); 23956498Speter } 24010015Speter strlcpy(bp, ans, ep - bp); 24156498Speter ne->n_name = bp; 24256498Speter if (strlen(in) + 1 > sizeof(aux)) { 24310015Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 24410015Speter errno = ENOBUFS; 24510015Speter return (-1); 24610015Speter } 24710015Speter ipreverse(in, aux); 24810015Speter ne->n_net = inet_network(aux); 24910015Speter break; 25012174Speter } 25110015Speter ne->n_aliases++; 25256498Speter return (0); 25356498Speter } 25410015Speter RES_SET_H_ERRNO(statp, TRY_AGAIN); 25556505Speter return (-1); 25656505Speter} 25756505Speter 25856505Speterint 25956498Speter_dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) 26010015Speter{ 26156498Speter uint32_t net; 26256498Speter int net_type; 26356498Speter char *buffer; 26456498Speter size_t buflen; 26556498Speter int *errnop, *h_errnop; 26656498Speter struct netent *nptr, ne; 26756498Speter struct netent_data *ned; 26856498Speter unsigned int netbr[4]; 26956498Speter int nn, anslen, error; 27033395Speter querybuf *buf; 27133395Speter char qbuf[MAXDNAME]; 27233395Speter uint32_t net2; 27310015Speter res_state statp; 27410015Speter 27510015Speter net = va_arg(ap, uint32_t); 27610015Speter net_type = va_arg(ap, int); 27734832Speter nptr = va_arg(ap, struct netent *); 27834832Speter buffer = va_arg(ap, char *); 27934832Speter buflen = va_arg(ap, size_t); 28034832Speter errnop = va_arg(ap, int *); 28156498Speter h_errnop = va_arg(ap, int *); 28234832Speter 28334832Speter statp = __res_state(); 28434832Speter if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 28534832Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 28634832Speter *h_errnop = statp->res_h_errno; 28734832Speter return (NS_UNAVAIL); 28834832Speter } 28934832Speter 29034832Speter if ((ned = __netent_data_init()) == NULL) { 29134832Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 29234832Speter *h_errnop = statp->res_h_errno; 29334832Speter return (NS_UNAVAIL); 29434832Speter } 29534832Speter 29634832Speter *((struct netent **)rval) = NULL; 29734832Speter 29856498Speter if (net_type != AF_INET) { 29934832Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 30034832Speter *h_errnop = statp->res_h_errno; 30134832Speter return (NS_UNAVAIL); 30234832Speter } 30334832Speter 30436956Ssteve for (nn = 4, net2 = net; net2; net2 >>= 8) 30533395Speter netbr[--nn] = net2 & 0xff; 30656498Speter switch (nn) { 30734832Speter case 3: /* Class A */ 30834832Speter sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); 30934832Speter break; 31034832Speter case 2: /* Class B */ 31156498Speter sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); 31234832Speter break; 31334832Speter case 1: /* Class C */ 31434832Speter sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], 31533395Speter netbr[1]); 31656498Speter break; 31734832Speter case 0: /* Class D - E */ 31834832Speter sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], 31933395Speter netbr[1], netbr[0]); 32010015Speter break; 32134832Speter } 32234832Speter if ((buf = malloc(sizeof(*buf))) == NULL) { 32310015Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 32410015Speter *h_errnop = statp->res_h_errno; 32534832Speter return (NS_NOTFOUND); 32634832Speter } 32756498Speter anslen = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf, 32856498Speter sizeof(*buf)); 32910015Speter if (anslen < 0) { 33033395Speter free(buf); 33134832Speter#ifdef DEBUG 33233395Speter if (statp->options & RES_DEBUG) 33333395Speter printf("res_nsearch failed\n"); 33433395Speter#endif 33533395Speter *h_errnop = statp->res_h_errno; 33633395Speter return (NS_UNAVAIL); 33733395Speter } else if (anslen > sizeof(*buf)) { 33833395Speter free(buf); 33933395Speter#ifdef DEBUG 34033395Speter if (statp->options & RES_DEBUG) 34133395Speter printf("res_nsearch static buffer too small\n"); 34234832Speter#endif 34356498Speter *h_errnop = statp->res_h_errno; 34434832Speter return (NS_UNAVAIL); 34534832Speter } 34656498Speter error = getnetanswer(buf, anslen, BYADDR, &ne, ned, statp); 34734832Speter free(buf); 34834832Speter if (error == 0) { 34956498Speter /* Strip trailing zeros */ 35034832Speter while ((net & 0xff) == 0 && net != 0) 35134832Speter net >>= 8; 35256498Speter ne.n_net = net; 35334832Speter if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { 35434832Speter *errnop = errno; 35556498Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 35634832Speter *h_errnop = statp->res_h_errno; 35734832Speter return (NS_RETURN); 35834832Speter } 35933395Speter *((struct netent **)rval) = nptr; 36010015Speter return (NS_SUCCESS); 36110015Speter } 36210015Speter *h_errnop = statp->res_h_errno; 36310015Speter return (NS_NOTFOUND); 36410015Speter} 36510015Speter 36610015Speterint 36756498Speter_dns_getnetbyname(void *rval, void *cb_data, va_list ap) 36810015Speter{ 36910015Speter const char *net; 37056498Speter char *buffer; 37110015Speter size_t buflen; 37210015Speter int *errnop, *h_errnop; 37356498Speter struct netent *nptr, ne; 37410015Speter struct netent_data *ned; 37510015Speter int anslen, error; 37610015Speter querybuf *buf; 37710015Speter char qbuf[MAXDNAME]; 37810015Speter res_state statp; 37934832Speter 38034832Speter net = va_arg(ap, const char *); 38156498Speter nptr = va_arg(ap, struct netent *); 38210015Speter buffer = va_arg(ap, char *); 38310015Speter buflen = va_arg(ap, size_t); 38410015Speter errnop = va_arg(ap, int *); 38510015Speter h_errnop = va_arg(ap, int *); 38610015Speter 38710015Speter statp = __res_state(); 38810015Speter if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 38910015Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 39010015Speter *h_errnop = statp->res_h_errno; 39110015Speter return (NS_UNAVAIL); 39210015Speter } 39310015Speter if ((ned = __netent_data_init()) == NULL) { 39410015Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 39512174Speter *h_errnop = statp->res_h_errno; 39656498Speter return (NS_UNAVAIL); 39710015Speter } 39836956Ssteve if ((buf = malloc(sizeof(*buf))) == NULL) { 39934832Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 40034832Speter *h_errnop = statp->res_h_errno; 40134832Speter return (NS_NOTFOUND); 40234832Speter } 40334832Speter 40434832Speter *((struct netent **)rval) = NULL; 40534832Speter 40634832Speter strncpy(qbuf, net, sizeof(qbuf) - 1); 40734832Speter qbuf[sizeof(qbuf) - 1] = '\0'; 40810015Speter anslen = res_nsearch(statp, qbuf, C_IN, T_PTR, (u_char *)buf, 40910015Speter sizeof(*buf)); 41010015Speter if (anslen < 0) { 41110015Speter free(buf); 41210015Speter#ifdef DEBUG 41310015Speter if (statp->options & RES_DEBUG) 41410015Speter printf("res_nsearch failed\n"); 41510015Speter#endif 41610015Speter return (NS_UNAVAIL); 41710015Speter } else if (anslen > sizeof(*buf)) { 41810015Speter free(buf); 41934832Speter#ifdef DEBUG 42010015Speter if (statp->options & RES_DEBUG) 42156498Speter printf("res_search static buffer too small\n"); 42210015Speter#endif 42310015Speter return (NS_UNAVAIL); 42410015Speter } 42510015Speter error = getnetanswer(buf, anslen, BYNAME, &ne, ned, statp); 42610015Speter free(buf); 42710015Speter if (error != 0) { 42810015Speter *h_errnop = statp->res_h_errno; 42910015Speter return (NS_NOTFOUND); 43010015Speter } 43112174Speter if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { 43234832Speter *errnop = errno; 43334832Speter RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 43410015Speter *h_errnop = statp->res_h_errno; 43534832Speter return (NS_RETURN); 43634832Speter } 43734832Speter *((struct netent **)rval) = nptr; 43810015Speter return (NS_SUCCESS); 43934832Speter} 44034832Speter 44134832Spetervoid 44234832Speter_setnetdnsent(int stayopen) 44334832Speter{ 44434832Speter res_state statp; 44534832Speter 44634832Speter statp = __res_state(); 44734832Speter if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) 44834832Speter return; 44934832Speter if (stayopen) 45034832Speter statp->options |= RES_STAYOPEN | RES_USEVC; 45134832Speter} 45234832Speter 45334832Spetervoid 45434832Speter_endnetdnsent(void) 45534832Speter{ 45634832Speter res_state statp; 45734832Speter 45834832Speter statp = __res_state(); 45934832Speter statp->options &= ~(RES_STAYOPEN | RES_USEVC); 46034832Speter res_nclose(statp); 46134832Speter} 46234832Speter