1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate /* 7*0Sstevel@tonic-gate * Copyright (c) 1996-1999 by Internet Software Consortium. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 10*0Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 11*0Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 12*0Sstevel@tonic-gate * 13*0Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 14*0Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 15*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 16*0Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 17*0Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 18*0Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 19*0Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*0Sstevel@tonic-gate * SOFTWARE. 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate 23*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 26*0Sstevel@tonic-gate static const char rcsid[] = "$Id: dns_nw.c,v 1.25 2002/07/18 02:07:43 marka Exp $"; 27*0Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* Imports. */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include "port_before.h" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/param.h> 34*0Sstevel@tonic-gate #include <sys/socket.h> 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #include <netinet/in.h> 37*0Sstevel@tonic-gate #include <arpa/inet.h> 38*0Sstevel@tonic-gate #include <arpa/nameser.h> 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #include <ctype.h> 41*0Sstevel@tonic-gate #include <errno.h> 42*0Sstevel@tonic-gate #include <netdb.h> 43*0Sstevel@tonic-gate #include <resolv.h> 44*0Sstevel@tonic-gate #include <stdio.h> 45*0Sstevel@tonic-gate #include <stdlib.h> 46*0Sstevel@tonic-gate #include <string.h> 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include <isc/memcluster.h> 49*0Sstevel@tonic-gate #include <irs.h> 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate #include "port_after.h" 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #include "irs_p.h" 54*0Sstevel@tonic-gate #include "dns_p.h" 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate #ifdef SPRINTF_CHAR 57*0Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x) 58*0Sstevel@tonic-gate #else 59*0Sstevel@tonic-gate # define SPRINTF(x) sprintf x 60*0Sstevel@tonic-gate #endif 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate /* Definitions. */ 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate #define MAXALIASES 35 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate #define MAXPACKET (64*1024) 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate struct pvt { 69*0Sstevel@tonic-gate struct nwent net; 70*0Sstevel@tonic-gate char * ali[MAXALIASES]; 71*0Sstevel@tonic-gate char buf[BUFSIZ+1]; 72*0Sstevel@tonic-gate struct __res_state * res; 73*0Sstevel@tonic-gate void (*free_res)(void *); 74*0Sstevel@tonic-gate }; 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate typedef union { 77*0Sstevel@tonic-gate long al; 78*0Sstevel@tonic-gate char ac; 79*0Sstevel@tonic-gate } align; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate enum by_what { by_addr, by_name }; 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* Forwards. */ 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate static void nw_close(struct irs_nw *); 86*0Sstevel@tonic-gate static struct nwent * nw_byname(struct irs_nw *, const char *, int); 87*0Sstevel@tonic-gate static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); 88*0Sstevel@tonic-gate static struct nwent * nw_next(struct irs_nw *); 89*0Sstevel@tonic-gate static void nw_rewind(struct irs_nw *); 90*0Sstevel@tonic-gate static void nw_minimize(struct irs_nw *); 91*0Sstevel@tonic-gate static struct __res_state * nw_res_get(struct irs_nw *this); 92*0Sstevel@tonic-gate static void nw_res_set(struct irs_nw *this, 93*0Sstevel@tonic-gate struct __res_state *res, 94*0Sstevel@tonic-gate void (*free_res)(void *)); 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); 97*0Sstevel@tonic-gate static struct nwent * get1101byname(struct irs_nw *, const char *); 98*0Sstevel@tonic-gate static struct nwent * get1101answer(struct irs_nw *, 99*0Sstevel@tonic-gate u_char *ansbuf, int anslen, 100*0Sstevel@tonic-gate enum by_what by_what, 101*0Sstevel@tonic-gate int af, const char *name, 102*0Sstevel@tonic-gate const u_char *addr, int addrlen); 103*0Sstevel@tonic-gate static struct nwent * get1101mask(struct irs_nw *this, struct nwent *); 104*0Sstevel@tonic-gate static int make1101inaddr(const u_char *, int, char *, int); 105*0Sstevel@tonic-gate static void normalize_name(char *name); 106*0Sstevel@tonic-gate static int init(struct irs_nw *this); 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /* Exports. */ 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate struct irs_nw * 111*0Sstevel@tonic-gate irs_dns_nw(struct irs_acc *this) { 112*0Sstevel@tonic-gate struct irs_nw *nw; 113*0Sstevel@tonic-gate struct pvt *pvt; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate UNUSED(this); 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (!(pvt = memget(sizeof *pvt))) { 118*0Sstevel@tonic-gate errno = ENOMEM; 119*0Sstevel@tonic-gate return (NULL); 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate memset(pvt, 0, sizeof *pvt); 122*0Sstevel@tonic-gate if (!(nw = memget(sizeof *nw))) { 123*0Sstevel@tonic-gate memput(pvt, sizeof *pvt); 124*0Sstevel@tonic-gate errno = ENOMEM; 125*0Sstevel@tonic-gate return (NULL); 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate memset(nw, 0x5e, sizeof *nw); 128*0Sstevel@tonic-gate nw->private = pvt; 129*0Sstevel@tonic-gate nw->close = nw_close; 130*0Sstevel@tonic-gate nw->byname = nw_byname; 131*0Sstevel@tonic-gate nw->byaddr = nw_byaddr; 132*0Sstevel@tonic-gate nw->next = nw_next; 133*0Sstevel@tonic-gate nw->rewind = nw_rewind; 134*0Sstevel@tonic-gate nw->minimize = nw_minimize; 135*0Sstevel@tonic-gate nw->res_get = nw_res_get; 136*0Sstevel@tonic-gate nw->res_set = nw_res_set; 137*0Sstevel@tonic-gate return (nw); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate /* Methods. */ 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate static void 143*0Sstevel@tonic-gate nw_close(struct irs_nw *this) { 144*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate nw_minimize(this); 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (pvt->res && pvt->free_res) 149*0Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate memput(pvt, sizeof *pvt); 152*0Sstevel@tonic-gate memput(this, sizeof *this); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate static struct nwent * 156*0Sstevel@tonic-gate nw_byname(struct irs_nw *this, const char *name, int af) { 157*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate if (init(this) == -1) 160*0Sstevel@tonic-gate return (NULL); 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate switch (af) { 163*0Sstevel@tonic-gate case AF_INET: 164*0Sstevel@tonic-gate return (get1101byname(this, name)); 165*0Sstevel@tonic-gate default: 166*0Sstevel@tonic-gate (void)NULL; 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 169*0Sstevel@tonic-gate errno = EAFNOSUPPORT; 170*0Sstevel@tonic-gate return (NULL); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate static struct nwent * 174*0Sstevel@tonic-gate nw_byaddr(struct irs_nw *this, void *net, int len, int af) { 175*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate if (init(this) == -1) 178*0Sstevel@tonic-gate return (NULL); 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate switch (af) { 181*0Sstevel@tonic-gate case AF_INET: 182*0Sstevel@tonic-gate return (get1101byaddr(this, net, len)); 183*0Sstevel@tonic-gate default: 184*0Sstevel@tonic-gate (void)NULL; 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 187*0Sstevel@tonic-gate errno = EAFNOSUPPORT; 188*0Sstevel@tonic-gate return (NULL); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate static struct nwent * 192*0Sstevel@tonic-gate nw_next(struct irs_nw *this) { 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate UNUSED(this); 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate return (NULL); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate static void 200*0Sstevel@tonic-gate nw_rewind(struct irs_nw *this) { 201*0Sstevel@tonic-gate UNUSED(this); 202*0Sstevel@tonic-gate /* NOOP */ 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate static void 206*0Sstevel@tonic-gate nw_minimize(struct irs_nw *this) { 207*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate if (pvt->res) 210*0Sstevel@tonic-gate res_nclose(pvt->res); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate static struct __res_state * 214*0Sstevel@tonic-gate nw_res_get(struct irs_nw *this) { 215*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate if (!pvt->res) { 218*0Sstevel@tonic-gate struct __res_state *res; 219*0Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 220*0Sstevel@tonic-gate if (!res) { 221*0Sstevel@tonic-gate errno = ENOMEM; 222*0Sstevel@tonic-gate return (NULL); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate memset(res, 0, sizeof *res); 225*0Sstevel@tonic-gate nw_res_set(this, res, free); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate return (pvt->res); 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate static void 232*0Sstevel@tonic-gate nw_res_set(struct irs_nw *this, struct __res_state *res, 233*0Sstevel@tonic-gate void (*free_res)(void *)) { 234*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate if (pvt->res && pvt->free_res) { 237*0Sstevel@tonic-gate res_nclose(pvt->res); 238*0Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate pvt->res = res; 242*0Sstevel@tonic-gate pvt->free_res = free_res; 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate /* Private. */ 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate static struct nwent * 248*0Sstevel@tonic-gate get1101byname(struct irs_nw *this, const char *name) { 249*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 250*0Sstevel@tonic-gate u_char *ansbuf; 251*0Sstevel@tonic-gate int anslen; 252*0Sstevel@tonic-gate struct nwent *result; 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate ansbuf = memget(MAXPACKET); 255*0Sstevel@tonic-gate if (ansbuf == NULL) { 256*0Sstevel@tonic-gate errno = ENOMEM; 257*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 258*0Sstevel@tonic-gate return (NULL); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET); 261*0Sstevel@tonic-gate if (anslen < 0) { 262*0Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 263*0Sstevel@tonic-gate return (NULL); 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, 266*0Sstevel@tonic-gate AF_INET, name, NULL, 0)); 267*0Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 268*0Sstevel@tonic-gate return (result); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate static struct nwent * 272*0Sstevel@tonic-gate get1101byaddr(struct irs_nw *this, u_char *net, int len) { 273*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 274*0Sstevel@tonic-gate char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; 275*0Sstevel@tonic-gate struct nwent *result; 276*0Sstevel@tonic-gate u_char *ansbuf; 277*0Sstevel@tonic-gate int anslen; 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate if (len < 1 || len > 32) { 280*0Sstevel@tonic-gate errno = EINVAL; 281*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 282*0Sstevel@tonic-gate return (NULL); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) 285*0Sstevel@tonic-gate return (NULL); 286*0Sstevel@tonic-gate ansbuf = memget(MAXPACKET); 287*0Sstevel@tonic-gate if (ansbuf == NULL) { 288*0Sstevel@tonic-gate errno = ENOMEM; 289*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 290*0Sstevel@tonic-gate return (NULL); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET); 293*0Sstevel@tonic-gate if (anslen < 0) { 294*0Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 295*0Sstevel@tonic-gate return (NULL); 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, 298*0Sstevel@tonic-gate AF_INET, NULL, net, len)); 299*0Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 300*0Sstevel@tonic-gate return (result); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate static struct nwent * 304*0Sstevel@tonic-gate get1101answer(struct irs_nw *this, 305*0Sstevel@tonic-gate u_char *ansbuf, int anslen, enum by_what by_what, 306*0Sstevel@tonic-gate int af, const char *name, const u_char *addr, int addrlen) 307*0Sstevel@tonic-gate { 308*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 309*0Sstevel@tonic-gate int type, class, ancount, qdcount, haveanswer; 310*0Sstevel@tonic-gate char *bp, *ep, **ap; 311*0Sstevel@tonic-gate u_char *cp, *eom; 312*0Sstevel@tonic-gate HEADER *hp; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* Initialize, and parse header. */ 315*0Sstevel@tonic-gate eom = ansbuf + anslen; 316*0Sstevel@tonic-gate if (ansbuf + HFIXEDSZ > eom) { 317*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 318*0Sstevel@tonic-gate return (NULL); 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate hp = (HEADER *)ansbuf; 321*0Sstevel@tonic-gate cp = ansbuf + HFIXEDSZ; 322*0Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 323*0Sstevel@tonic-gate while (qdcount-- > 0) { 324*0Sstevel@tonic-gate int n = dn_skipname(cp, eom); 325*0Sstevel@tonic-gate cp += n + QFIXEDSZ; 326*0Sstevel@tonic-gate if (n < 0 || cp > eom) { 327*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 328*0Sstevel@tonic-gate return (NULL); 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate ancount = ntohs(hp->ancount); 332*0Sstevel@tonic-gate if (!ancount) { 333*0Sstevel@tonic-gate if (hp->aa) 334*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 335*0Sstevel@tonic-gate else 336*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); 337*0Sstevel@tonic-gate return (NULL); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /* Prepare a return structure. */ 341*0Sstevel@tonic-gate bp = pvt->buf; 342*0Sstevel@tonic-gate ep = pvt->buf + sizeof (pvt->buf); 343*0Sstevel@tonic-gate pvt->net.n_name = NULL; 344*0Sstevel@tonic-gate pvt->net.n_aliases = pvt->ali; 345*0Sstevel@tonic-gate pvt->net.n_addrtype = af; 346*0Sstevel@tonic-gate pvt->net.n_addr = NULL; 347*0Sstevel@tonic-gate pvt->net.n_length = addrlen; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* Save input key if given. */ 350*0Sstevel@tonic-gate switch (by_what) { 351*0Sstevel@tonic-gate case by_name: 352*0Sstevel@tonic-gate if (name != NULL) { 353*0Sstevel@tonic-gate int n = strlen(name) + 1; 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate if (n > (ep - bp)) { 356*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 357*0Sstevel@tonic-gate return (NULL); 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate #ifdef HAVE_STRLCPY 360*0Sstevel@tonic-gate strlcpy(bp, name, ep - bp); 361*0Sstevel@tonic-gate pvt->net.n_name = bp; 362*0Sstevel@tonic-gate #else 363*0Sstevel@tonic-gate pvt->net.n_name = strcpy(bp, name); 364*0Sstevel@tonic-gate #endif 365*0Sstevel@tonic-gate bp += n; 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate break; 368*0Sstevel@tonic-gate case by_addr: 369*0Sstevel@tonic-gate if (addr != NULL && addrlen != 0) { 370*0Sstevel@tonic-gate int n = addrlen / 8 + ((addrlen % 8) != 0); 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate if (INADDRSZ > (ep - bp)) { 373*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 374*0Sstevel@tonic-gate return (NULL); 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate memset(bp, 0, INADDRSZ); 377*0Sstevel@tonic-gate memcpy(bp, addr, n); 378*0Sstevel@tonic-gate pvt->net.n_addr = bp; 379*0Sstevel@tonic-gate bp += INADDRSZ; 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate break; 382*0Sstevel@tonic-gate default: 383*0Sstevel@tonic-gate abort(); 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate /* Parse the answer, collect aliases. */ 387*0Sstevel@tonic-gate ap = pvt->ali; 388*0Sstevel@tonic-gate haveanswer = 0; 389*0Sstevel@tonic-gate while (--ancount >= 0 && cp < eom) { 390*0Sstevel@tonic-gate int n = dn_expand(ansbuf, eom, cp, bp, ep - bp); 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate cp += n; /* Owner */ 393*0Sstevel@tonic-gate if (n < 0 || !maybe_dnok(pvt->res, bp) || 394*0Sstevel@tonic-gate cp + 3 * INT16SZ + INT32SZ > eom) { 395*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 396*0Sstevel@tonic-gate return (NULL); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate GETSHORT(type, cp); /* Type */ 399*0Sstevel@tonic-gate GETSHORT(class, cp); /* Class */ 400*0Sstevel@tonic-gate cp += INT32SZ; /* TTL */ 401*0Sstevel@tonic-gate GETSHORT(n, cp); /* RDLENGTH */ 402*0Sstevel@tonic-gate if (class == C_IN && type == T_PTR) { 403*0Sstevel@tonic-gate int nn; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate nn = dn_expand(ansbuf, eom, cp, bp, ep - bp); 406*0Sstevel@tonic-gate if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) { 407*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 408*0Sstevel@tonic-gate return (NULL); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate normalize_name(bp); 411*0Sstevel@tonic-gate switch (by_what) { 412*0Sstevel@tonic-gate case by_addr: { 413*0Sstevel@tonic-gate if (pvt->net.n_name == NULL) 414*0Sstevel@tonic-gate pvt->net.n_name = bp; 415*0Sstevel@tonic-gate else if (ns_samename(pvt->net.n_name, bp) == 1) 416*0Sstevel@tonic-gate break; 417*0Sstevel@tonic-gate else 418*0Sstevel@tonic-gate *ap++ = bp; 419*0Sstevel@tonic-gate nn = strlen(bp) + 1; 420*0Sstevel@tonic-gate bp += nn; 421*0Sstevel@tonic-gate haveanswer++; 422*0Sstevel@tonic-gate break; 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate case by_name: { 425*0Sstevel@tonic-gate u_int b1, b2, b3, b4; 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gate if (pvt->net.n_addr != NULL || 428*0Sstevel@tonic-gate sscanf(bp, "%u.%u.%u.%u.in-addr.arpa", 429*0Sstevel@tonic-gate &b1, &b2, &b3, &b4) != 4) 430*0Sstevel@tonic-gate break; 431*0Sstevel@tonic-gate if ((ep - bp) < INADDRSZ) { 432*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 433*0Sstevel@tonic-gate return (NULL); 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate pvt->net.n_addr = bp; 436*0Sstevel@tonic-gate *bp++ = b4; 437*0Sstevel@tonic-gate *bp++ = b3; 438*0Sstevel@tonic-gate *bp++ = b2; 439*0Sstevel@tonic-gate *bp++ = b1; 440*0Sstevel@tonic-gate pvt->net.n_length = INADDRSZ * 8; 441*0Sstevel@tonic-gate haveanswer++; 442*0Sstevel@tonic-gate } 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate cp += n; /* RDATA */ 446*0Sstevel@tonic-gate } 447*0Sstevel@tonic-gate if (!haveanswer) { 448*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); 449*0Sstevel@tonic-gate return (NULL); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate *ap = NULL; 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate return (&pvt->net); 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate static struct nwent * 457*0Sstevel@tonic-gate get1101mask(struct irs_nw *this, struct nwent *nwent) { 458*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 459*0Sstevel@tonic-gate char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; 460*0Sstevel@tonic-gate int anslen, type, class, ancount, qdcount; 461*0Sstevel@tonic-gate u_char *ansbuf, *cp, *eom; 462*0Sstevel@tonic-gate HEADER *hp; 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate if (!nwent) 465*0Sstevel@tonic-gate return (NULL); 466*0Sstevel@tonic-gate if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf) 467*0Sstevel@tonic-gate < 0) { 468*0Sstevel@tonic-gate /* "First, do no harm." */ 469*0Sstevel@tonic-gate return (nwent); 470*0Sstevel@tonic-gate } 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate ansbuf = memget(MAXPACKET); 473*0Sstevel@tonic-gate if (ansbuf == NULL) { 474*0Sstevel@tonic-gate errno = ENOMEM; 475*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 476*0Sstevel@tonic-gate return (NULL); 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate /* Query for the A RR that would hold this network's mask. */ 479*0Sstevel@tonic-gate anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET); 480*0Sstevel@tonic-gate if (anslen < HFIXEDSZ) { 481*0Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 482*0Sstevel@tonic-gate return (nwent); 483*0Sstevel@tonic-gate } 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate /* Initialize, and parse header. */ 486*0Sstevel@tonic-gate hp = (HEADER *)ansbuf; 487*0Sstevel@tonic-gate cp = ansbuf + HFIXEDSZ; 488*0Sstevel@tonic-gate eom = ansbuf + anslen; 489*0Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 490*0Sstevel@tonic-gate while (qdcount-- > 0) { 491*0Sstevel@tonic-gate int n = dn_skipname(cp, eom); 492*0Sstevel@tonic-gate cp += n + QFIXEDSZ; 493*0Sstevel@tonic-gate if (n < 0 || cp > eom) { 494*0Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 495*0Sstevel@tonic-gate return (nwent); 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate ancount = ntohs(hp->ancount); 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate /* Parse the answer, collect aliases. */ 501*0Sstevel@tonic-gate while (--ancount >= 0 && cp < eom) { 502*0Sstevel@tonic-gate int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate if (n < 0 || !maybe_dnok(pvt->res, owner)) 505*0Sstevel@tonic-gate break; 506*0Sstevel@tonic-gate cp += n; /* Owner */ 507*0Sstevel@tonic-gate if (cp + 3 * INT16SZ + INT32SZ > eom) 508*0Sstevel@tonic-gate break; 509*0Sstevel@tonic-gate GETSHORT(type, cp); /* Type */ 510*0Sstevel@tonic-gate GETSHORT(class, cp); /* Class */ 511*0Sstevel@tonic-gate cp += INT32SZ; /* TTL */ 512*0Sstevel@tonic-gate GETSHORT(n, cp); /* RDLENGTH */ 513*0Sstevel@tonic-gate if (cp + n > eom) 514*0Sstevel@tonic-gate break; 515*0Sstevel@tonic-gate if (n == INADDRSZ && class == C_IN && type == T_A && 516*0Sstevel@tonic-gate ns_samename(qbuf, owner) == 1) { 517*0Sstevel@tonic-gate /* This A RR indicates the actual netmask. */ 518*0Sstevel@tonic-gate int nn, mm; 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate nwent->n_length = 0; 521*0Sstevel@tonic-gate for (nn = 0; nn < INADDRSZ; nn++) 522*0Sstevel@tonic-gate for (mm = 7; mm >= 0; mm--) 523*0Sstevel@tonic-gate if (cp[nn] & (1 << mm)) 524*0Sstevel@tonic-gate nwent->n_length++; 525*0Sstevel@tonic-gate else 526*0Sstevel@tonic-gate break; 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate cp += n; /* RDATA */ 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate memput(ansbuf, MAXPACKET); 531*0Sstevel@tonic-gate return (nwent); 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate static int 535*0Sstevel@tonic-gate make1101inaddr(const u_char *net, int bits, char *name, int size) { 536*0Sstevel@tonic-gate int n, m; 537*0Sstevel@tonic-gate char *ep; 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate ep = name + size; 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate /* Zero fill any whole bytes left out of the prefix. */ 542*0Sstevel@tonic-gate for (n = (32 - bits) / 8; n > 0; n--) { 543*0Sstevel@tonic-gate if (ep - name < (int)(sizeof "0.")) 544*0Sstevel@tonic-gate goto emsgsize; 545*0Sstevel@tonic-gate m = SPRINTF((name, "0.")); 546*0Sstevel@tonic-gate name += m; 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate /* Format the partial byte, if any, within the prefix. */ 550*0Sstevel@tonic-gate if ((n = bits % 8) != 0) { 551*0Sstevel@tonic-gate if (ep - name < (int)(sizeof "255.")) 552*0Sstevel@tonic-gate goto emsgsize; 553*0Sstevel@tonic-gate m = SPRINTF((name, "%u.", 554*0Sstevel@tonic-gate net[bits / 8] & ~((1 << (8 - n)) - 1))); 555*0Sstevel@tonic-gate name += m; 556*0Sstevel@tonic-gate } 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate /* Format the whole bytes within the prefix. */ 559*0Sstevel@tonic-gate for (n = bits / 8; n > 0; n--) { 560*0Sstevel@tonic-gate if (ep - name < (int)(sizeof "255.")) 561*0Sstevel@tonic-gate goto emsgsize; 562*0Sstevel@tonic-gate m = SPRINTF((name, "%u.", net[n - 1])); 563*0Sstevel@tonic-gate name += m; 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate /* Add the static text. */ 567*0Sstevel@tonic-gate if (ep - name < (int)(sizeof "in-addr.arpa")) 568*0Sstevel@tonic-gate goto emsgsize; 569*0Sstevel@tonic-gate (void) SPRINTF((name, "in-addr.arpa")); 570*0Sstevel@tonic-gate return (0); 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate emsgsize: 573*0Sstevel@tonic-gate errno = EMSGSIZE; 574*0Sstevel@tonic-gate return (-1); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate static void 578*0Sstevel@tonic-gate normalize_name(char *name) { 579*0Sstevel@tonic-gate char *t; 580*0Sstevel@tonic-gate 581*0Sstevel@tonic-gate /* Make lower case. */ 582*0Sstevel@tonic-gate for (t = name; *t; t++) 583*0Sstevel@tonic-gate if (isascii((unsigned char)*t) && isupper((unsigned char)*t)) 584*0Sstevel@tonic-gate *t = tolower(*t); 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate /* Remove trailing dots. */ 587*0Sstevel@tonic-gate while (t > name && t[-1] == '.') 588*0Sstevel@tonic-gate *--t = '\0'; 589*0Sstevel@tonic-gate } 590*0Sstevel@tonic-gate 591*0Sstevel@tonic-gate static int 592*0Sstevel@tonic-gate init(struct irs_nw *this) { 593*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate if (!pvt->res && !nw_res_get(this)) 596*0Sstevel@tonic-gate return (-1); 597*0Sstevel@tonic-gate if (((pvt->res->options & RES_INIT) == 0) && 598*0Sstevel@tonic-gate res_ninit(pvt->res) == -1) 599*0Sstevel@tonic-gate return (-1); 600*0Sstevel@tonic-gate return (0); 601*0Sstevel@tonic-gate } 602