10Sstevel@tonic-gate /* 2*11038SRao.Shoaib@Sun.COM * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 30Sstevel@tonic-gate * Copyright (c) 1996-1999 by Internet Software Consortium. 40Sstevel@tonic-gate * 50Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 60Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 70Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 80Sstevel@tonic-gate * 9*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10*11038SRao.Shoaib@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*11038SRao.Shoaib@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12*11038SRao.Shoaib@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*11038SRao.Shoaib@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*11038SRao.Shoaib@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15*11038SRao.Shoaib@Sun.COM * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 160Sstevel@tonic-gate */ 170Sstevel@tonic-gate 180Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 19*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: dns_nw.c,v 1.12 2005/04/27 04:56:22 sra Exp $"; 200Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 210Sstevel@tonic-gate 220Sstevel@tonic-gate /* Imports. */ 230Sstevel@tonic-gate 240Sstevel@tonic-gate #include "port_before.h" 250Sstevel@tonic-gate 260Sstevel@tonic-gate #include <sys/param.h> 270Sstevel@tonic-gate #include <sys/socket.h> 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <netinet/in.h> 300Sstevel@tonic-gate #include <arpa/inet.h> 310Sstevel@tonic-gate #include <arpa/nameser.h> 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <ctype.h> 340Sstevel@tonic-gate #include <errno.h> 350Sstevel@tonic-gate #include <netdb.h> 360Sstevel@tonic-gate #include <resolv.h> 370Sstevel@tonic-gate #include <stdio.h> 380Sstevel@tonic-gate #include <stdlib.h> 390Sstevel@tonic-gate #include <string.h> 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include <isc/memcluster.h> 420Sstevel@tonic-gate #include <irs.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate #include "port_after.h" 450Sstevel@tonic-gate 460Sstevel@tonic-gate #include "irs_p.h" 470Sstevel@tonic-gate #include "dns_p.h" 480Sstevel@tonic-gate 490Sstevel@tonic-gate #ifdef SPRINTF_CHAR 500Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x) 510Sstevel@tonic-gate #else 520Sstevel@tonic-gate # define SPRINTF(x) sprintf x 530Sstevel@tonic-gate #endif 540Sstevel@tonic-gate 550Sstevel@tonic-gate /* Definitions. */ 560Sstevel@tonic-gate 570Sstevel@tonic-gate #define MAXALIASES 35 580Sstevel@tonic-gate 590Sstevel@tonic-gate #define MAXPACKET (64*1024) 600Sstevel@tonic-gate 610Sstevel@tonic-gate struct pvt { 620Sstevel@tonic-gate struct nwent net; 630Sstevel@tonic-gate char * ali[MAXALIASES]; 640Sstevel@tonic-gate char buf[BUFSIZ+1]; 650Sstevel@tonic-gate struct __res_state * res; 660Sstevel@tonic-gate void (*free_res)(void *); 670Sstevel@tonic-gate }; 680Sstevel@tonic-gate 690Sstevel@tonic-gate typedef union { 700Sstevel@tonic-gate long al; 710Sstevel@tonic-gate char ac; 720Sstevel@tonic-gate } align; 730Sstevel@tonic-gate 740Sstevel@tonic-gate enum by_what { by_addr, by_name }; 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* Forwards. */ 770Sstevel@tonic-gate 780Sstevel@tonic-gate static void nw_close(struct irs_nw *); 790Sstevel@tonic-gate static struct nwent * nw_byname(struct irs_nw *, const char *, int); 800Sstevel@tonic-gate static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); 810Sstevel@tonic-gate static struct nwent * nw_next(struct irs_nw *); 820Sstevel@tonic-gate static void nw_rewind(struct irs_nw *); 830Sstevel@tonic-gate static void nw_minimize(struct irs_nw *); 840Sstevel@tonic-gate static struct __res_state * nw_res_get(struct irs_nw *this); 850Sstevel@tonic-gate static void nw_res_set(struct irs_nw *this, 860Sstevel@tonic-gate struct __res_state *res, 870Sstevel@tonic-gate void (*free_res)(void *)); 880Sstevel@tonic-gate 890Sstevel@tonic-gate static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); 900Sstevel@tonic-gate static struct nwent * get1101byname(struct irs_nw *, const char *); 910Sstevel@tonic-gate static struct nwent * get1101answer(struct irs_nw *, 920Sstevel@tonic-gate u_char *ansbuf, int anslen, 930Sstevel@tonic-gate enum by_what by_what, 940Sstevel@tonic-gate int af, const char *name, 950Sstevel@tonic-gate const u_char *addr, int addrlen); 960Sstevel@tonic-gate static struct nwent * get1101mask(struct irs_nw *this, struct nwent *); 970Sstevel@tonic-gate static int make1101inaddr(const u_char *, int, char *, int); 980Sstevel@tonic-gate static void normalize_name(char *name); 990Sstevel@tonic-gate static int init(struct irs_nw *this); 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate /* Exports. */ 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate struct irs_nw * 1040Sstevel@tonic-gate irs_dns_nw(struct irs_acc *this) { 1050Sstevel@tonic-gate struct irs_nw *nw; 1060Sstevel@tonic-gate struct pvt *pvt; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate UNUSED(this); 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate if (!(pvt = memget(sizeof *pvt))) { 1110Sstevel@tonic-gate errno = ENOMEM; 1120Sstevel@tonic-gate return (NULL); 1130Sstevel@tonic-gate } 1140Sstevel@tonic-gate memset(pvt, 0, sizeof *pvt); 1150Sstevel@tonic-gate if (!(nw = memget(sizeof *nw))) { 1160Sstevel@tonic-gate memput(pvt, sizeof *pvt); 1170Sstevel@tonic-gate errno = ENOMEM; 1180Sstevel@tonic-gate return (NULL); 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate memset(nw, 0x5e, sizeof *nw); 1210Sstevel@tonic-gate nw->private = pvt; 1220Sstevel@tonic-gate nw->close = nw_close; 1230Sstevel@tonic-gate nw->byname = nw_byname; 1240Sstevel@tonic-gate nw->byaddr = nw_byaddr; 1250Sstevel@tonic-gate nw->next = nw_next; 1260Sstevel@tonic-gate nw->rewind = nw_rewind; 1270Sstevel@tonic-gate nw->minimize = nw_minimize; 1280Sstevel@tonic-gate nw->res_get = nw_res_get; 1290Sstevel@tonic-gate nw->res_set = nw_res_set; 1300Sstevel@tonic-gate return (nw); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* Methods. */ 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate static void 1360Sstevel@tonic-gate nw_close(struct irs_nw *this) { 1370Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate nw_minimize(this); 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate if (pvt->res && pvt->free_res) 1420Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate memput(pvt, sizeof *pvt); 1450Sstevel@tonic-gate memput(this, sizeof *this); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate static struct nwent * 1490Sstevel@tonic-gate nw_byname(struct irs_nw *this, const char *name, int af) { 1500Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate if (init(this) == -1) 1530Sstevel@tonic-gate return (NULL); 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate switch (af) { 1560Sstevel@tonic-gate case AF_INET: 1570Sstevel@tonic-gate return (get1101byname(this, name)); 1580Sstevel@tonic-gate default: 1590Sstevel@tonic-gate (void)NULL; 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 1620Sstevel@tonic-gate errno = EAFNOSUPPORT; 1630Sstevel@tonic-gate return (NULL); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate static struct nwent * 1670Sstevel@tonic-gate nw_byaddr(struct irs_nw *this, void *net, int len, int af) { 1680Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate if (init(this) == -1) 1710Sstevel@tonic-gate return (NULL); 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate switch (af) { 1740Sstevel@tonic-gate case AF_INET: 1750Sstevel@tonic-gate return (get1101byaddr(this, net, len)); 1760Sstevel@tonic-gate default: 1770Sstevel@tonic-gate (void)NULL; 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 1800Sstevel@tonic-gate errno = EAFNOSUPPORT; 1810Sstevel@tonic-gate return (NULL); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate static struct nwent * 1850Sstevel@tonic-gate nw_next(struct irs_nw *this) { 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate UNUSED(this); 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate return (NULL); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate static void 1930Sstevel@tonic-gate nw_rewind(struct irs_nw *this) { 1940Sstevel@tonic-gate UNUSED(this); 1950Sstevel@tonic-gate /* NOOP */ 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate static void 1990Sstevel@tonic-gate nw_minimize(struct irs_nw *this) { 2000Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate if (pvt->res) 2030Sstevel@tonic-gate res_nclose(pvt->res); 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate static struct __res_state * 2070Sstevel@tonic-gate nw_res_get(struct irs_nw *this) { 2080Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate if (!pvt->res) { 2110Sstevel@tonic-gate struct __res_state *res; 2120Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 2130Sstevel@tonic-gate if (!res) { 2140Sstevel@tonic-gate errno = ENOMEM; 2150Sstevel@tonic-gate return (NULL); 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate memset(res, 0, sizeof *res); 2180Sstevel@tonic-gate nw_res_set(this, res, free); 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate return (pvt->res); 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate static void 2250Sstevel@tonic-gate nw_res_set(struct irs_nw *this, struct __res_state *res, 2260Sstevel@tonic-gate void (*free_res)(void *)) { 2270Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate if (pvt->res && pvt->free_res) { 2300Sstevel@tonic-gate res_nclose(pvt->res); 2310Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate pvt->res = res; 2350Sstevel@tonic-gate pvt->free_res = free_res; 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* Private. */ 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate static struct nwent * 2410Sstevel@tonic-gate get1101byname(struct irs_nw *this, const char *name) { 2420Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2430Sstevel@tonic-gate u_char *ansbuf; 2440Sstevel@tonic-gate int anslen; 2450Sstevel@tonic-gate struct nwent *result; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate ansbuf = memget(MAXPACKET); 2480Sstevel@tonic-gate if (ansbuf == NULL) { 2490Sstevel@tonic-gate errno = ENOMEM; 2500Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2510Sstevel@tonic-gate return (NULL); 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET); 2540Sstevel@tonic-gate if (anslen < 0) { 2550Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 2560Sstevel@tonic-gate return (NULL); 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, 2590Sstevel@tonic-gate AF_INET, name, NULL, 0)); 2600Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 2610Sstevel@tonic-gate return (result); 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate static struct nwent * 2650Sstevel@tonic-gate get1101byaddr(struct irs_nw *this, u_char *net, int len) { 2660Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2670Sstevel@tonic-gate char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; 2680Sstevel@tonic-gate struct nwent *result; 2690Sstevel@tonic-gate u_char *ansbuf; 2700Sstevel@tonic-gate int anslen; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate if (len < 1 || len > 32) { 2730Sstevel@tonic-gate errno = EINVAL; 2740Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2750Sstevel@tonic-gate return (NULL); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) 2780Sstevel@tonic-gate return (NULL); 2790Sstevel@tonic-gate ansbuf = memget(MAXPACKET); 2800Sstevel@tonic-gate if (ansbuf == NULL) { 2810Sstevel@tonic-gate errno = ENOMEM; 2820Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2830Sstevel@tonic-gate return (NULL); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET); 2860Sstevel@tonic-gate if (anslen < 0) { 2870Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 2880Sstevel@tonic-gate return (NULL); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, 2910Sstevel@tonic-gate AF_INET, NULL, net, len)); 2920Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 2930Sstevel@tonic-gate return (result); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate static struct nwent * 2970Sstevel@tonic-gate get1101answer(struct irs_nw *this, 2980Sstevel@tonic-gate u_char *ansbuf, int anslen, enum by_what by_what, 2990Sstevel@tonic-gate int af, const char *name, const u_char *addr, int addrlen) 3000Sstevel@tonic-gate { 3010Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 3020Sstevel@tonic-gate int type, class, ancount, qdcount, haveanswer; 3030Sstevel@tonic-gate char *bp, *ep, **ap; 3040Sstevel@tonic-gate u_char *cp, *eom; 3050Sstevel@tonic-gate HEADER *hp; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate /* Initialize, and parse header. */ 3080Sstevel@tonic-gate eom = ansbuf + anslen; 3090Sstevel@tonic-gate if (ansbuf + HFIXEDSZ > eom) { 3100Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 3110Sstevel@tonic-gate return (NULL); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate hp = (HEADER *)ansbuf; 3140Sstevel@tonic-gate cp = ansbuf + HFIXEDSZ; 3150Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 3160Sstevel@tonic-gate while (qdcount-- > 0) { 3170Sstevel@tonic-gate int n = dn_skipname(cp, eom); 3180Sstevel@tonic-gate cp += n + QFIXEDSZ; 3190Sstevel@tonic-gate if (n < 0 || cp > eom) { 3200Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 3210Sstevel@tonic-gate return (NULL); 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate ancount = ntohs(hp->ancount); 3250Sstevel@tonic-gate if (!ancount) { 3260Sstevel@tonic-gate if (hp->aa) 3270Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 3280Sstevel@tonic-gate else 3290Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); 3300Sstevel@tonic-gate return (NULL); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate /* Prepare a return structure. */ 3340Sstevel@tonic-gate bp = pvt->buf; 335*11038SRao.Shoaib@Sun.COM ep = pvt->buf + sizeof(pvt->buf); 3360Sstevel@tonic-gate pvt->net.n_name = NULL; 3370Sstevel@tonic-gate pvt->net.n_aliases = pvt->ali; 3380Sstevel@tonic-gate pvt->net.n_addrtype = af; 3390Sstevel@tonic-gate pvt->net.n_addr = NULL; 3400Sstevel@tonic-gate pvt->net.n_length = addrlen; 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate /* Save input key if given. */ 3430Sstevel@tonic-gate switch (by_what) { 3440Sstevel@tonic-gate case by_name: 3450Sstevel@tonic-gate if (name != NULL) { 3460Sstevel@tonic-gate int n = strlen(name) + 1; 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate if (n > (ep - bp)) { 3490Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 3500Sstevel@tonic-gate return (NULL); 3510Sstevel@tonic-gate } 352*11038SRao.Shoaib@Sun.COM pvt->net.n_name = strcpy(bp, name); /* (checked) */ 3530Sstevel@tonic-gate bp += n; 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate break; 3560Sstevel@tonic-gate case by_addr: 3570Sstevel@tonic-gate if (addr != NULL && addrlen != 0) { 3580Sstevel@tonic-gate int n = addrlen / 8 + ((addrlen % 8) != 0); 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate if (INADDRSZ > (ep - bp)) { 3610Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 3620Sstevel@tonic-gate return (NULL); 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate memset(bp, 0, INADDRSZ); 3650Sstevel@tonic-gate memcpy(bp, addr, n); 3660Sstevel@tonic-gate pvt->net.n_addr = bp; 3670Sstevel@tonic-gate bp += INADDRSZ; 3680Sstevel@tonic-gate } 3690Sstevel@tonic-gate break; 3700Sstevel@tonic-gate default: 3710Sstevel@tonic-gate abort(); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate /* Parse the answer, collect aliases. */ 3750Sstevel@tonic-gate ap = pvt->ali; 3760Sstevel@tonic-gate haveanswer = 0; 3770Sstevel@tonic-gate while (--ancount >= 0 && cp < eom) { 3780Sstevel@tonic-gate int n = dn_expand(ansbuf, eom, cp, bp, ep - bp); 3790Sstevel@tonic-gate 380*11038SRao.Shoaib@Sun.COM cp += n; /*%< Owner */ 3810Sstevel@tonic-gate if (n < 0 || !maybe_dnok(pvt->res, bp) || 3820Sstevel@tonic-gate cp + 3 * INT16SZ + INT32SZ > eom) { 3830Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 3840Sstevel@tonic-gate return (NULL); 3850Sstevel@tonic-gate } 386*11038SRao.Shoaib@Sun.COM GETSHORT(type, cp); /*%< Type */ 387*11038SRao.Shoaib@Sun.COM GETSHORT(class, cp); /*%< Class */ 388*11038SRao.Shoaib@Sun.COM cp += INT32SZ; /*%< TTL */ 389*11038SRao.Shoaib@Sun.COM GETSHORT(n, cp); /*%< RDLENGTH */ 3900Sstevel@tonic-gate if (class == C_IN && type == T_PTR) { 3910Sstevel@tonic-gate int nn; 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate nn = dn_expand(ansbuf, eom, cp, bp, ep - bp); 3940Sstevel@tonic-gate if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) { 3950Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 3960Sstevel@tonic-gate return (NULL); 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate normalize_name(bp); 3990Sstevel@tonic-gate switch (by_what) { 4000Sstevel@tonic-gate case by_addr: { 4010Sstevel@tonic-gate if (pvt->net.n_name == NULL) 4020Sstevel@tonic-gate pvt->net.n_name = bp; 4030Sstevel@tonic-gate else if (ns_samename(pvt->net.n_name, bp) == 1) 4040Sstevel@tonic-gate break; 4050Sstevel@tonic-gate else 4060Sstevel@tonic-gate *ap++ = bp; 4070Sstevel@tonic-gate nn = strlen(bp) + 1; 4080Sstevel@tonic-gate bp += nn; 4090Sstevel@tonic-gate haveanswer++; 4100Sstevel@tonic-gate break; 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate case by_name: { 4130Sstevel@tonic-gate u_int b1, b2, b3, b4; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate if (pvt->net.n_addr != NULL || 4160Sstevel@tonic-gate sscanf(bp, "%u.%u.%u.%u.in-addr.arpa", 4170Sstevel@tonic-gate &b1, &b2, &b3, &b4) != 4) 4180Sstevel@tonic-gate break; 4190Sstevel@tonic-gate if ((ep - bp) < INADDRSZ) { 4200Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 4210Sstevel@tonic-gate return (NULL); 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate pvt->net.n_addr = bp; 4240Sstevel@tonic-gate *bp++ = b4; 4250Sstevel@tonic-gate *bp++ = b3; 4260Sstevel@tonic-gate *bp++ = b2; 4270Sstevel@tonic-gate *bp++ = b1; 4280Sstevel@tonic-gate pvt->net.n_length = INADDRSZ * 8; 4290Sstevel@tonic-gate haveanswer++; 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate } 433*11038SRao.Shoaib@Sun.COM cp += n; /*%< RDATA */ 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate if (!haveanswer) { 4360Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); 4370Sstevel@tonic-gate return (NULL); 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate *ap = NULL; 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate return (&pvt->net); 4420Sstevel@tonic-gate } 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate static struct nwent * 4450Sstevel@tonic-gate get1101mask(struct irs_nw *this, struct nwent *nwent) { 4460Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 4470Sstevel@tonic-gate char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; 4480Sstevel@tonic-gate int anslen, type, class, ancount, qdcount; 4490Sstevel@tonic-gate u_char *ansbuf, *cp, *eom; 4500Sstevel@tonic-gate HEADER *hp; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate if (!nwent) 4530Sstevel@tonic-gate return (NULL); 4540Sstevel@tonic-gate if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf) 4550Sstevel@tonic-gate < 0) { 4560Sstevel@tonic-gate /* "First, do no harm." */ 4570Sstevel@tonic-gate return (nwent); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate ansbuf = memget(MAXPACKET); 4610Sstevel@tonic-gate if (ansbuf == NULL) { 4620Sstevel@tonic-gate errno = ENOMEM; 4630Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 4640Sstevel@tonic-gate return (NULL); 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate /* Query for the A RR that would hold this network's mask. */ 4670Sstevel@tonic-gate anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET); 4680Sstevel@tonic-gate if (anslen < HFIXEDSZ) { 4690Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 4700Sstevel@tonic-gate return (nwent); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate /* Initialize, and parse header. */ 4740Sstevel@tonic-gate hp = (HEADER *)ansbuf; 4750Sstevel@tonic-gate cp = ansbuf + HFIXEDSZ; 4760Sstevel@tonic-gate eom = ansbuf + anslen; 4770Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 4780Sstevel@tonic-gate while (qdcount-- > 0) { 4790Sstevel@tonic-gate int n = dn_skipname(cp, eom); 4800Sstevel@tonic-gate cp += n + QFIXEDSZ; 4810Sstevel@tonic-gate if (n < 0 || cp > eom) { 4820Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 4830Sstevel@tonic-gate return (nwent); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate ancount = ntohs(hp->ancount); 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate /* Parse the answer, collect aliases. */ 4890Sstevel@tonic-gate while (--ancount >= 0 && cp < eom) { 4900Sstevel@tonic-gate int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate if (n < 0 || !maybe_dnok(pvt->res, owner)) 4930Sstevel@tonic-gate break; 494*11038SRao.Shoaib@Sun.COM cp += n; /*%< Owner */ 4950Sstevel@tonic-gate if (cp + 3 * INT16SZ + INT32SZ > eom) 4960Sstevel@tonic-gate break; 497*11038SRao.Shoaib@Sun.COM GETSHORT(type, cp); /*%< Type */ 498*11038SRao.Shoaib@Sun.COM GETSHORT(class, cp); /*%< Class */ 499*11038SRao.Shoaib@Sun.COM cp += INT32SZ; /*%< TTL */ 500*11038SRao.Shoaib@Sun.COM GETSHORT(n, cp); /*%< RDLENGTH */ 5010Sstevel@tonic-gate if (cp + n > eom) 5020Sstevel@tonic-gate break; 5030Sstevel@tonic-gate if (n == INADDRSZ && class == C_IN && type == T_A && 5040Sstevel@tonic-gate ns_samename(qbuf, owner) == 1) { 5050Sstevel@tonic-gate /* This A RR indicates the actual netmask. */ 5060Sstevel@tonic-gate int nn, mm; 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate nwent->n_length = 0; 5090Sstevel@tonic-gate for (nn = 0; nn < INADDRSZ; nn++) 5100Sstevel@tonic-gate for (mm = 7; mm >= 0; mm--) 5110Sstevel@tonic-gate if (cp[nn] & (1 << mm)) 5120Sstevel@tonic-gate nwent->n_length++; 5130Sstevel@tonic-gate else 5140Sstevel@tonic-gate break; 5150Sstevel@tonic-gate } 516*11038SRao.Shoaib@Sun.COM cp += n; /*%< RDATA */ 5170Sstevel@tonic-gate } 5180Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 5190Sstevel@tonic-gate return (nwent); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate static int 5230Sstevel@tonic-gate make1101inaddr(const u_char *net, int bits, char *name, int size) { 5240Sstevel@tonic-gate int n, m; 5250Sstevel@tonic-gate char *ep; 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate ep = name + size; 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* Zero fill any whole bytes left out of the prefix. */ 5300Sstevel@tonic-gate for (n = (32 - bits) / 8; n > 0; n--) { 5310Sstevel@tonic-gate if (ep - name < (int)(sizeof "0.")) 5320Sstevel@tonic-gate goto emsgsize; 5330Sstevel@tonic-gate m = SPRINTF((name, "0.")); 5340Sstevel@tonic-gate name += m; 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate /* Format the partial byte, if any, within the prefix. */ 5380Sstevel@tonic-gate if ((n = bits % 8) != 0) { 5390Sstevel@tonic-gate if (ep - name < (int)(sizeof "255.")) 5400Sstevel@tonic-gate goto emsgsize; 5410Sstevel@tonic-gate m = SPRINTF((name, "%u.", 5420Sstevel@tonic-gate net[bits / 8] & ~((1 << (8 - n)) - 1))); 5430Sstevel@tonic-gate name += m; 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate /* Format the whole bytes within the prefix. */ 5470Sstevel@tonic-gate for (n = bits / 8; n > 0; n--) { 5480Sstevel@tonic-gate if (ep - name < (int)(sizeof "255.")) 5490Sstevel@tonic-gate goto emsgsize; 5500Sstevel@tonic-gate m = SPRINTF((name, "%u.", net[n - 1])); 5510Sstevel@tonic-gate name += m; 5520Sstevel@tonic-gate } 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate /* Add the static text. */ 5550Sstevel@tonic-gate if (ep - name < (int)(sizeof "in-addr.arpa")) 5560Sstevel@tonic-gate goto emsgsize; 5570Sstevel@tonic-gate (void) SPRINTF((name, "in-addr.arpa")); 5580Sstevel@tonic-gate return (0); 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate emsgsize: 5610Sstevel@tonic-gate errno = EMSGSIZE; 5620Sstevel@tonic-gate return (-1); 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate static void 5660Sstevel@tonic-gate normalize_name(char *name) { 5670Sstevel@tonic-gate char *t; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate /* Make lower case. */ 5700Sstevel@tonic-gate for (t = name; *t; t++) 5710Sstevel@tonic-gate if (isascii((unsigned char)*t) && isupper((unsigned char)*t)) 572*11038SRao.Shoaib@Sun.COM *t = tolower((*t)&0xff); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate /* Remove trailing dots. */ 5750Sstevel@tonic-gate while (t > name && t[-1] == '.') 5760Sstevel@tonic-gate *--t = '\0'; 5770Sstevel@tonic-gate } 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate static int 5800Sstevel@tonic-gate init(struct irs_nw *this) { 5810Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5820Sstevel@tonic-gate 5830Sstevel@tonic-gate if (!pvt->res && !nw_res_get(this)) 5840Sstevel@tonic-gate return (-1); 585*11038SRao.Shoaib@Sun.COM if (((pvt->res->options & RES_INIT) == 0U) && 5860Sstevel@tonic-gate res_ninit(pvt->res) == -1) 5870Sstevel@tonic-gate return (-1); 5880Sstevel@tonic-gate return (0); 5890Sstevel@tonic-gate } 590*11038SRao.Shoaib@Sun.COM 591*11038SRao.Shoaib@Sun.COM /*! \file */ 592