10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2830Sdjl * Common Development and Distribution License (the "License"). 6*2830Sdjl * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2830Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*2830Sdjl * Use is subject to license terms. 24*2830Sdjl */ 25*2830Sdjl 26*2830Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 27*2830Sdjl 28*2830Sdjl /* 290Sstevel@tonic-gate * dns_common.c 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 32*2830Sdjl #include "dns_common.h" 330Sstevel@tonic-gate 34*2830Sdjl #pragma weak dn_expand 35*2830Sdjl #pragma weak res_ninit 36*2830Sdjl #pragma weak res_nsearch 37*2830Sdjl #pragma weak res_nclose 38*2830Sdjl #pragma weak ns_get16 39*2830Sdjl #pragma weak ns_get32 40*2830Sdjl #pragma weak __ns_get16 41*2830Sdjl #pragma weak __ns_get32 420Sstevel@tonic-gate 430Sstevel@tonic-gate #define DNS_ALIASES 0 440Sstevel@tonic-gate #define DNS_ADDRLIST 1 450Sstevel@tonic-gate #define DNS_MAPDLIST 2 460Sstevel@tonic-gate 470Sstevel@tonic-gate static int 480Sstevel@tonic-gate dns_netdb_aliases(from_list, to_list, aliaspp, type, count, af_type) 490Sstevel@tonic-gate char **from_list, **to_list, **aliaspp; 500Sstevel@tonic-gate int type, *count, af_type; 510Sstevel@tonic-gate { 520Sstevel@tonic-gate char *fstr; 530Sstevel@tonic-gate int cnt = 0; 540Sstevel@tonic-gate size_t len; 550Sstevel@tonic-gate 560Sstevel@tonic-gate *count = 0; 570Sstevel@tonic-gate if ((char *)to_list >= *aliaspp) 580Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 590Sstevel@tonic-gate 600Sstevel@tonic-gate for (fstr = from_list[cnt]; fstr != NULL; fstr = from_list[cnt]) { 610Sstevel@tonic-gate if (type == DNS_ALIASES) 620Sstevel@tonic-gate len = strlen(fstr) + 1; 630Sstevel@tonic-gate else 640Sstevel@tonic-gate len = (af_type == AF_INET) ? sizeof (struct in_addr) 650Sstevel@tonic-gate : sizeof (struct in6_addr); 660Sstevel@tonic-gate *aliaspp -= len; 670Sstevel@tonic-gate to_list[cnt] = *aliaspp; 680Sstevel@tonic-gate if (*aliaspp <= (char *)&to_list[cnt+1]) 690Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 700Sstevel@tonic-gate if (type == DNS_MAPDLIST) { 71*2830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 72*2830Sdjl struct in6_addr *addr6p = (struct in6_addr *)*aliaspp; 730Sstevel@tonic-gate 740Sstevel@tonic-gate (void) memset(addr6p, '\0', sizeof (struct in6_addr)); 750Sstevel@tonic-gate (void) memcpy(&addr6p->s6_addr[12], fstr, 760Sstevel@tonic-gate sizeof (struct in_addr)); 770Sstevel@tonic-gate addr6p->s6_addr[10] = 0xffU; 780Sstevel@tonic-gate addr6p->s6_addr[11] = 0xffU; 790Sstevel@tonic-gate ++cnt; 800Sstevel@tonic-gate } else { 810Sstevel@tonic-gate (void) memcpy (*aliaspp, fstr, len); 820Sstevel@tonic-gate ++cnt; 830Sstevel@tonic-gate } 840Sstevel@tonic-gate } 850Sstevel@tonic-gate to_list[cnt] = NULL; 860Sstevel@tonic-gate 870Sstevel@tonic-gate *count = cnt; 880Sstevel@tonic-gate if (cnt == 0) 890Sstevel@tonic-gate return (NSS_STR_PARSE_PARSE); 900Sstevel@tonic-gate 910Sstevel@tonic-gate return (NSS_STR_PARSE_SUCCESS); 920Sstevel@tonic-gate } 930Sstevel@tonic-gate 940Sstevel@tonic-gate 950Sstevel@tonic-gate int 960Sstevel@tonic-gate ent2result(he, argp, af_type) 970Sstevel@tonic-gate struct hostent *he; 980Sstevel@tonic-gate nss_XbyY_args_t *argp; 990Sstevel@tonic-gate int af_type; 1000Sstevel@tonic-gate { 1010Sstevel@tonic-gate char *buffer, *limit; 1020Sstevel@tonic-gate int buflen = argp->buf.buflen; 1030Sstevel@tonic-gate int ret, count; 1040Sstevel@tonic-gate size_t len; 1050Sstevel@tonic-gate struct hostent *host; 1060Sstevel@tonic-gate struct in_addr *addrp; 1070Sstevel@tonic-gate struct in6_addr *addrp6; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate limit = argp->buf.buffer + buflen; 110*2830Sdjl host = (struct hostent *)argp->buf.result; 1110Sstevel@tonic-gate buffer = argp->buf.buffer; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate /* h_addrtype and h_length */ 1140Sstevel@tonic-gate host->h_addrtype = af_type; 1150Sstevel@tonic-gate host->h_length = (af_type == AF_INET) ? sizeof (struct in_addr) 1160Sstevel@tonic-gate : sizeof (struct in6_addr); 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* h_name */ 1190Sstevel@tonic-gate len = strlen(he->h_name) + 1; 1200Sstevel@tonic-gate host->h_name = buffer; 1210Sstevel@tonic-gate if (host->h_name + len >= limit) 1220Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 1230Sstevel@tonic-gate (void) memcpy(host->h_name, he->h_name, len); 1240Sstevel@tonic-gate buffer += len; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate /* h_addr_list */ 1270Sstevel@tonic-gate if (af_type == AF_INET) { 128*2830Sdjl addrp = (struct in_addr *)ROUND_DOWN(limit, sizeof (*addrp)); 1290Sstevel@tonic-gate host->h_addr_list = (char **) 1300Sstevel@tonic-gate ROUND_UP(buffer, sizeof (char **)); 1310Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_addr_list, host->h_addr_list, 1320Sstevel@tonic-gate (char **)&addrp, DNS_ADDRLIST, &count, af_type); 1330Sstevel@tonic-gate if (ret != NSS_STR_PARSE_SUCCESS) 1340Sstevel@tonic-gate return (ret); 1350Sstevel@tonic-gate /* h_aliases */ 1360Sstevel@tonic-gate host->h_aliases = host->h_addr_list + count + 1; 1370Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_aliases, host->h_aliases, 1380Sstevel@tonic-gate (char **)&addrp, DNS_ALIASES, &count, af_type); 1390Sstevel@tonic-gate } else { 1400Sstevel@tonic-gate addrp6 = (struct in6_addr *) 1410Sstevel@tonic-gate ROUND_DOWN(limit, sizeof (*addrp6)); 1420Sstevel@tonic-gate host->h_addr_list = (char **) 1430Sstevel@tonic-gate ROUND_UP(buffer, sizeof (char **)); 1440Sstevel@tonic-gate if (he->h_addrtype == AF_INET && af_type == AF_INET6) { 1450Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_addr_list, 1460Sstevel@tonic-gate host->h_addr_list, (char **)&addrp6, 1470Sstevel@tonic-gate DNS_MAPDLIST, &count, af_type); 1480Sstevel@tonic-gate } else { 1490Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_addr_list, 1500Sstevel@tonic-gate host->h_addr_list, (char **)&addrp6, 1510Sstevel@tonic-gate DNS_ADDRLIST, &count, af_type); 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate if (ret != NSS_STR_PARSE_SUCCESS) 1540Sstevel@tonic-gate return (ret); 1550Sstevel@tonic-gate /* h_aliases */ 1560Sstevel@tonic-gate host->h_aliases = host->h_addr_list + count + 1; 1570Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_aliases, host->h_aliases, 1580Sstevel@tonic-gate (char **)&addrp6, DNS_ALIASES, &count, af_type); 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate if (ret == NSS_STR_PARSE_PARSE) 1610Sstevel@tonic-gate ret = NSS_STR_PARSE_SUCCESS; 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate return (ret); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 166*2830Sdjl /* 167*2830Sdjl * Convert the hostent structure into string in the following 168*2830Sdjl * format: 169*2830Sdjl * 170*2830Sdjl * IP-address official-host-name nicknames ... 171*2830Sdjl * 172*2830Sdjl * If more than one IP-addresses matches the official-host-name, 173*2830Sdjl * the above line will be followed by: 174*2830Sdjl * IP-address-1 official-host-name 175*2830Sdjl * IP-address-2 official-host-name 176*2830Sdjl * ... 177*2830Sdjl * 178*2830Sdjl * This is so that the str2hostent function in libnsl 179*2830Sdjl * can convert the string back to the original hostent 180*2830Sdjl * data. 181*2830Sdjl */ 182*2830Sdjl int 183*2830Sdjl ent2str( 184*2830Sdjl struct hostent *hp, 185*2830Sdjl nss_XbyY_args_t *ap, 186*2830Sdjl int af_type) 187*2830Sdjl { 188*2830Sdjl char **p; 189*2830Sdjl char obuf[INET6_ADDRSTRLEN]; 190*2830Sdjl void *addr; 191*2830Sdjl struct in_addr in4; 192*2830Sdjl int af; 193*2830Sdjl int n; 194*2830Sdjl const char *res; 195*2830Sdjl char **q; 196*2830Sdjl int l = ap->buf.buflen; 197*2830Sdjl char *s = ap->buf.buffer; 198*2830Sdjl 199*2830Sdjl /* 200*2830Sdjl * for "hosts" lookup, we only want address type of 201*2830Sdjl * AF_INET. For "ipnodes", we can have both AF_INET 202*2830Sdjl * and AF_INET6. 203*2830Sdjl */ 204*2830Sdjl if (af_type == AF_INET && hp->h_addrtype != AF_INET) 205*2830Sdjl return (NSS_STR_PARSE_PARSE); 206*2830Sdjl 207*2830Sdjl for (p = hp->h_addr_list; *p != 0; p++) { 208*2830Sdjl 209*2830Sdjl if (p != hp->h_addr_list) { 210*2830Sdjl *s = '\n'; 211*2830Sdjl s++; 212*2830Sdjl l--; 213*2830Sdjl } 214*2830Sdjl 215*2830Sdjl if (hp->h_addrtype == AF_INET6) { 216*2830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 217*2830Sdjl if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)*p)) { 218*2830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 219*2830Sdjl IN6_V4MAPPED_TO_INADDR((struct in6_addr *)*p, 220*2830Sdjl &in4); 221*2830Sdjl af = AF_INET; 222*2830Sdjl addr = &in4; 223*2830Sdjl } else { 224*2830Sdjl af = AF_INET6; 225*2830Sdjl addr = *p; 226*2830Sdjl } 227*2830Sdjl } else { 228*2830Sdjl af = AF_INET; 229*2830Sdjl addr = *p; 230*2830Sdjl } 231*2830Sdjl res = inet_ntop(af, addr, obuf, sizeof (obuf)); 232*2830Sdjl if (res == NULL) 233*2830Sdjl return (NSS_STR_PARSE_PARSE); 234*2830Sdjl 235*2830Sdjl if ((n = snprintf(s, l, "%s %s", res, hp->h_name)) >= l) 236*2830Sdjl return (NSS_STR_PARSE_ERANGE); 237*2830Sdjl l -= n; 238*2830Sdjl s += n; 239*2830Sdjl if (p == hp->h_addr_list) { 240*2830Sdjl for (q = hp->h_aliases; q && *q; q++) { 241*2830Sdjl if ((n = snprintf(s, l, " %s", *q)) >= l) 242*2830Sdjl return (NSS_STR_PARSE_ERANGE); 243*2830Sdjl l -= n; 244*2830Sdjl s += n; 245*2830Sdjl } 246*2830Sdjl } 247*2830Sdjl } 248*2830Sdjl 249*2830Sdjl ap->returnlen = s - ap->buf.buffer; 250*2830Sdjl return (NSS_STR_PARSE_SUCCESS); 251*2830Sdjl } 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate nss_backend_t * 2540Sstevel@tonic-gate _nss_dns_constr(dns_backend_op_t ops[], int n_ops) 2550Sstevel@tonic-gate { 2560Sstevel@tonic-gate dns_backend_ptr_t be; 2570Sstevel@tonic-gate 258*2830Sdjl if ((be = (dns_backend_ptr_t)malloc(sizeof (*be))) == 0) 2590Sstevel@tonic-gate return (0); 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate be->ops = ops; 2620Sstevel@tonic-gate be->n_ops = n_ops; 263*2830Sdjl return ((nss_backend_t *)be); 264*2830Sdjl } 265*2830Sdjl 266*2830Sdjl 267*2830Sdjl /* 268*2830Sdjl * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 269*2830Sdjl * nss2 get hosts/ipnodes with ttl backend DNS search engine. 270*2830Sdjl * 271*2830Sdjl * This API is given a pointer to a packed buffer, and the buffer size 272*2830Sdjl * It's job is to perform the appropriate res_nsearch, extract the 273*2830Sdjl * results and build a unmarshalled hosts/ipnodes result buffer. 274*2830Sdjl * Additionally in the extended results a nssuint_t ttl is placed. 275*2830Sdjl * This ttl is the lessor of the ttl's extracted from the result. 276*2830Sdjl * 277*2830Sdjl * ***Currently the first version of this API only performs simple 278*2830Sdjl * single res_nsearch lookups for with T_A or T_AAAA results. 279*2830Sdjl * Other searches are deferred to the generic API w/t ttls. 280*2830Sdjl * 281*2830Sdjl * This function is not a generic res_* operation. It only performs 282*2830Sdjl * a single T_A or T_AAAA lookups*** 283*2830Sdjl * 284*2830Sdjl * RETURNS: NSS_SUCCESS or NSS_ERROR 285*2830Sdjl * If an NSS_ERROR result is returned, nscd is expected 286*2830Sdjl * to resubmit the gethosts request using the old style 287*2830Sdjl * nsswitch lookup format. 288*2830Sdjl */ 289*2830Sdjl 290*2830Sdjl struct tsd_priv { 291*2830Sdjl struct __res_state *statp; /* dns state block */ 292*2830Sdjl union msg { 293*2830Sdjl uchar_t buf[NS_MAXMSG]; /* max legal DNS answer size */ 294*2830Sdjl HEADER h; 295*2830Sdjl } resbuf; 296*2830Sdjl char aliases[NS_MAXMSG]; /* set of aliases */ 297*2830Sdjl }; 298*2830Sdjl 299*2830Sdjl static void ghttlcleanup(void *ptr) 300*2830Sdjl { 301*2830Sdjl struct tsd_priv *priv = (struct tsd_priv *)ptr; 302*2830Sdjl 303*2830Sdjl if (priv) { 304*2830Sdjl if (priv->statp != NULL) { 305*2830Sdjl res_nclose(priv->statp); 306*2830Sdjl free((void *)priv->statp); 307*2830Sdjl } 308*2830Sdjl free(ptr); 309*2830Sdjl } 3100Sstevel@tonic-gate } 311*2830Sdjl 312*2830Sdjl nss_status_t 313*2830Sdjl _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 314*2830Sdjl { 315*2830Sdjl /* nss buffer variables */ 316*2830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 317*2830Sdjl nss_XbyY_args_t arg; 318*2830Sdjl char *dbname; 319*2830Sdjl int dbop; 320*2830Sdjl nss_status_t sret; 321*2830Sdjl size_t bsize, blen; 322*2830Sdjl char *bptr; 323*2830Sdjl /* resolver query variables */ 324*2830Sdjl static mutex_t keylock; 325*2830Sdjl static thread_key_t key; 326*2830Sdjl static int once_per_keyname = 0; 327*2830Sdjl struct tsd_priv *tsd = NULL; 328*2830Sdjl const char *name; 329*2830Sdjl int qtype; 330*2830Sdjl /* answer parsing variables */ 331*2830Sdjl HEADER *hp; 332*2830Sdjl uchar_t *cp; /* current location in message */ 333*2830Sdjl uchar_t *bom; /* start of message */ 334*2830Sdjl uchar_t *eom; /* end of message */ 335*2830Sdjl uchar_t *eor; /* end of record */ 336*2830Sdjl int ancount, qdcount; 337*2830Sdjl int type, class; 338*2830Sdjl nssuint_t nttl, ttl, *pttl; /* The purpose of this API */ 339*2830Sdjl int n, ret; 340*2830Sdjl const char *np; 341*2830Sdjl /* temporary buffers */ 342*2830Sdjl char nbuf[INET6_ADDRSTRLEN]; /* address parser */ 343*2830Sdjl char host[MAXHOSTNAMELEN]; /* result host name */ 344*2830Sdjl char ans[MAXHOSTNAMELEN]; /* record name */ 345*2830Sdjl char aname[MAXHOSTNAMELEN]; /* alias result (C_NAME) */ 346*2830Sdjl /* misc variables */ 347*2830Sdjl int af; 348*2830Sdjl char *ap, *apc; 349*2830Sdjl int hlen, alen, iplen, len; 350*2830Sdjl 351*2830Sdjl if (!once_per_keyname) { 352*2830Sdjl (void) mutex_lock(&keylock); 353*2830Sdjl if (!once_per_keyname) { 354*2830Sdjl (void) thr_keycreate(&key, ghttlcleanup); 355*2830Sdjl once_per_keyname++; 356*2830Sdjl } 357*2830Sdjl (void) mutex_unlock(&keylock); 358*2830Sdjl } 359*2830Sdjl (void) thr_getspecific(key, (void **)&tsd); 360*2830Sdjl if (tsd == NULL) { 361*2830Sdjl tsd = (struct tsd_priv *)calloc(1, sizeof (struct tsd_priv)); 362*2830Sdjl (void) thr_setspecific(key, (void *)tsd); 363*2830Sdjl (void) thr_getspecific(key, (void **)&tsd); 364*2830Sdjl tsd->statp = (struct __res_state *) 365*2830Sdjl calloc(1, sizeof (struct __res_state)); 366*2830Sdjl if (tsd->statp == NULL) 367*2830Sdjl return (NSS_ERROR); 368*2830Sdjl if (res_ninit(tsd->statp) == -1) { 369*2830Sdjl free(tsd->statp); 370*2830Sdjl return (NSS_ERROR); 371*2830Sdjl } 372*2830Sdjl } 373*2830Sdjl ap = apc = (char *)tsd->aliases; 374*2830Sdjl alen = 0; 375*2830Sdjl ttl = (nssuint_t)0xFFFFFFF; /* start w/max, find smaller */ 376*2830Sdjl 377*2830Sdjl /* save space for ttl otherwise, why bother... */ 378*2830Sdjl bsize = pbuf->data_len - sizeof (nssuint_t); 379*2830Sdjl bptr = (char *)buffer + pbuf->data_off; 380*2830Sdjl blen = 0; 381*2830Sdjl sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg); 382*2830Sdjl if (sret != NSS_SUCCESS) { 383*2830Sdjl return (NSS_ERROR); 384*2830Sdjl } 385*2830Sdjl 386*2830Sdjl if (ipnode) { 387*2830Sdjl /* initially only handle the simple cases */ 388*2830Sdjl if (arg.key.ipnode.flags != 0) 389*2830Sdjl return (NSS_ERROR); 390*2830Sdjl name = arg.key.ipnode.name; 391*2830Sdjl if (arg.key.ipnode.af_family == AF_INET6) 392*2830Sdjl qtype = T_AAAA; 393*2830Sdjl else 394*2830Sdjl qtype = T_A; 395*2830Sdjl } else { 396*2830Sdjl name = arg.key.name; 397*2830Sdjl qtype = T_A; 398*2830Sdjl } 399*2830Sdjl ret = res_nsearch(tsd->statp, name, C_IN, qtype, 400*2830Sdjl tsd->resbuf.buf, NS_MAXMSG); 401*2830Sdjl if (ret == -1) { 402*2830Sdjl if (tsd->statp->res_h_errno == HOST_NOT_FOUND) { 403*2830Sdjl pbuf->p_herrno = HOST_NOT_FOUND; 404*2830Sdjl pbuf->p_status = NSS_NOTFOUND; 405*2830Sdjl pbuf->data_len = 0; 406*2830Sdjl return (NSS_NOTFOUND); 407*2830Sdjl } 408*2830Sdjl /* else lookup error - handle in general code */ 409*2830Sdjl return (NSS_ERROR); 410*2830Sdjl } 411*2830Sdjl 412*2830Sdjl cp = tsd->resbuf.buf; 413*2830Sdjl hp = (HEADER *)&tsd->resbuf.h; 414*2830Sdjl bom = cp; 415*2830Sdjl eom = cp + ret; 416*2830Sdjl 417*2830Sdjl ancount = ntohs(hp->ancount); 418*2830Sdjl qdcount = ntohs(hp->qdcount); 419*2830Sdjl cp += HFIXEDSZ; 420*2830Sdjl if (qdcount != 1) 421*2830Sdjl return (NSS_ERROR); 422*2830Sdjl n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN); 423*2830Sdjl if (n < 0) { 424*2830Sdjl return (NSS_ERROR); 425*2830Sdjl } else 426*2830Sdjl hlen = strlen(host); 427*2830Sdjl cp += n + QFIXEDSZ; 428*2830Sdjl if (cp > eom) 429*2830Sdjl return (NSS_ERROR); 430*2830Sdjl while (ancount-- > 0 && cp < eom && blen < bsize) { 431*2830Sdjl n = dn_expand(bom, eom, cp, ans, MAXHOSTNAMELEN); 432*2830Sdjl if (n > 0) { 433*2830Sdjl if (strncasecmp(host, ans, hlen) != 0) 434*2830Sdjl return (NSS_ERROR); /* spoof? */ 435*2830Sdjl } 436*2830Sdjl cp += n; 437*2830Sdjl /* bounds check */ 438*2830Sdjl type = ns_get16(cp); /* type */ 439*2830Sdjl cp += INT16SZ; 440*2830Sdjl class = ns_get16(cp); /* class */ 441*2830Sdjl cp += INT16SZ; 442*2830Sdjl nttl = (nssuint_t)ns_get32(cp); /* ttl in sec */ 443*2830Sdjl if (nttl < ttl) 444*2830Sdjl ttl = nttl; 445*2830Sdjl cp += INT32SZ; 446*2830Sdjl n = ns_get16(cp); /* len */ 447*2830Sdjl cp += INT16SZ; 448*2830Sdjl if (class != C_IN) { 449*2830Sdjl cp += n; 450*2830Sdjl continue; 451*2830Sdjl } 452*2830Sdjl eor = cp + n; 453*2830Sdjl if (type == T_CNAME) { 454*2830Sdjl /* add an alias to the alias list */ 455*2830Sdjl n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN); 456*2830Sdjl if (n > 0) { 457*2830Sdjl len = strlen(aname); 458*2830Sdjl if (len > 0) { 459*2830Sdjl /* 460*2830Sdjl * Just error out if there is an 461*2830Sdjl * attempted buffer overflow exploit 462*2830Sdjl * generic code will do a syslog 463*2830Sdjl */ 464*2830Sdjl if (alen + len + 2 > NS_MAXMSG) 465*2830Sdjl return (NSS_ERROR); 466*2830Sdjl *apc++ = ' '; 467*2830Sdjl alen++; 468*2830Sdjl (void) strlcpy(apc, aname, len + 1); 469*2830Sdjl alen += len; 470*2830Sdjl apc += len; 471*2830Sdjl } 472*2830Sdjl } 473*2830Sdjl cp += n; 474*2830Sdjl continue; 475*2830Sdjl } 476*2830Sdjl if (type != qtype) { 477*2830Sdjl cp += n; 478*2830Sdjl continue; 479*2830Sdjl } 480*2830Sdjl /* check data size */ 481*2830Sdjl if ((type == T_A && n != INADDRSZ) || 482*2830Sdjl (type == T_AAAA && n != IN6ADDRSZ)) { 483*2830Sdjl cp += n; 484*2830Sdjl continue; 485*2830Sdjl } 486*2830Sdjl af = (type == T_A ? AF_INET : AF_INET6); 487*2830Sdjl np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN); 488*2830Sdjl if (np == NULL) 489*2830Sdjl return (NSS_ERROR); 490*2830Sdjl cp += n; 491*2830Sdjl /* append IP host aliases to results */ 492*2830Sdjl iplen = strlen(np); 493*2830Sdjl /* ip <SP> hostname [<SP>][aliases] */ 494*2830Sdjl len = iplen + 2 + hlen + alen; 495*2830Sdjl if (alen > 0) 496*2830Sdjl len++; 497*2830Sdjl if (blen + len > bsize) 498*2830Sdjl return (NSS_ERROR); 499*2830Sdjl (void) strlcpy(bptr, np, bsize - blen); 500*2830Sdjl blen += iplen; 501*2830Sdjl bptr += iplen; 502*2830Sdjl *bptr++ = ' '; 503*2830Sdjl blen++; 504*2830Sdjl (void) strlcpy(bptr, host, bsize - blen); 505*2830Sdjl blen += hlen; 506*2830Sdjl bptr += hlen; 507*2830Sdjl if (alen > 0) { 508*2830Sdjl *bptr++ = ' '; 509*2830Sdjl blen++; 510*2830Sdjl (void) strlcpy(bptr, ap, bsize - blen); 511*2830Sdjl blen += alen; 512*2830Sdjl bptr += alen; 513*2830Sdjl } 514*2830Sdjl *bptr++ = '\n'; 515*2830Sdjl blen++; 516*2830Sdjl } 517*2830Sdjl /* Presumably the buffer is now filled. */ 518*2830Sdjl len = ROUND_UP(blen, sizeof (nssuint_t)); 519*2830Sdjl /* still room? */ 520*2830Sdjl if (len + sizeof (nssuint_t) > pbuf->data_len) { 521*2830Sdjl /* sigh, no, what happened? */ 522*2830Sdjl return (NSS_ERROR); 523*2830Sdjl } 524*2830Sdjl pbuf->ext_off = pbuf->data_off + len; 525*2830Sdjl pbuf->ext_len = sizeof (nssuint_t); 526*2830Sdjl pbuf->data_len = blen; 527*2830Sdjl pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off)); 528*2830Sdjl *pttl = ttl; 529*2830Sdjl return (NSS_SUCCESS); 530*2830Sdjl } 531