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 52830Sdjl * Common Development and Distribution License (the "License"). 62830Sdjl * 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*5161Smichen * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 232830Sdjl * Use is subject to license terms. 242830Sdjl */ 252830Sdjl 262830Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 272830Sdjl 282830Sdjl /* 290Sstevel@tonic-gate * dns_common.c 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 322830Sdjl #include "dns_common.h" 330Sstevel@tonic-gate 342830Sdjl #pragma weak dn_expand 352830Sdjl #pragma weak res_ninit 362830Sdjl #pragma weak res_nsearch 372830Sdjl #pragma weak res_nclose 382830Sdjl #pragma weak ns_get16 392830Sdjl #pragma weak ns_get32 402830Sdjl #pragma weak __ns_get16 412830Sdjl #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) { 712830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 722830Sdjl 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; 1102830Sdjl 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) { 1282830Sdjl 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 1662830Sdjl /* 1672830Sdjl * Convert the hostent structure into string in the following 1682830Sdjl * format: 1692830Sdjl * 1702830Sdjl * IP-address official-host-name nicknames ... 1712830Sdjl * 1722830Sdjl * If more than one IP-addresses matches the official-host-name, 1732830Sdjl * the above line will be followed by: 1742830Sdjl * IP-address-1 official-host-name 1752830Sdjl * IP-address-2 official-host-name 1762830Sdjl * ... 1772830Sdjl * 1782830Sdjl * This is so that the str2hostent function in libnsl 1792830Sdjl * can convert the string back to the original hostent 1802830Sdjl * data. 1812830Sdjl */ 1822830Sdjl int 1832830Sdjl ent2str( 1842830Sdjl struct hostent *hp, 1852830Sdjl nss_XbyY_args_t *ap, 1862830Sdjl int af_type) 1872830Sdjl { 1882830Sdjl char **p; 1892830Sdjl char obuf[INET6_ADDRSTRLEN]; 1902830Sdjl void *addr; 1912830Sdjl struct in_addr in4; 1922830Sdjl int af; 1932830Sdjl int n; 1942830Sdjl const char *res; 1952830Sdjl char **q; 1962830Sdjl int l = ap->buf.buflen; 1972830Sdjl char *s = ap->buf.buffer; 1982830Sdjl 1992830Sdjl /* 2002830Sdjl * for "hosts" lookup, we only want address type of 2012830Sdjl * AF_INET. For "ipnodes", we can have both AF_INET 2022830Sdjl * and AF_INET6. 2032830Sdjl */ 2042830Sdjl if (af_type == AF_INET && hp->h_addrtype != AF_INET) 2052830Sdjl return (NSS_STR_PARSE_PARSE); 2062830Sdjl 2072830Sdjl for (p = hp->h_addr_list; *p != 0; p++) { 2082830Sdjl 2092830Sdjl if (p != hp->h_addr_list) { 2102830Sdjl *s = '\n'; 2112830Sdjl s++; 2122830Sdjl l--; 2132830Sdjl } 2142830Sdjl 2152830Sdjl if (hp->h_addrtype == AF_INET6) { 2162830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 2172830Sdjl if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)*p)) { 2182830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 2192830Sdjl IN6_V4MAPPED_TO_INADDR((struct in6_addr *)*p, 220*5161Smichen &in4); 2212830Sdjl af = AF_INET; 2222830Sdjl addr = &in4; 2232830Sdjl } else { 2242830Sdjl af = AF_INET6; 2252830Sdjl addr = *p; 2262830Sdjl } 2272830Sdjl } else { 2282830Sdjl af = AF_INET; 2292830Sdjl addr = *p; 2302830Sdjl } 2312830Sdjl res = inet_ntop(af, addr, obuf, sizeof (obuf)); 2322830Sdjl if (res == NULL) 2332830Sdjl return (NSS_STR_PARSE_PARSE); 2342830Sdjl 235*5161Smichen if ((n = snprintf(s, l, "%s", res)) >= l) 2362830Sdjl return (NSS_STR_PARSE_ERANGE); 2372830Sdjl l -= n; 2382830Sdjl s += n; 239*5161Smichen if (hp->h_name != NULL && *hp->h_name != '\0') { 240*5161Smichen if ((n = snprintf(s, l, " %s", hp->h_name)) >= l) 241*5161Smichen return (NSS_STR_PARSE_ERANGE); 242*5161Smichen l -= n; 243*5161Smichen s += n; 244*5161Smichen } 2452830Sdjl if (p == hp->h_addr_list) { 2462830Sdjl for (q = hp->h_aliases; q && *q; q++) { 2472830Sdjl if ((n = snprintf(s, l, " %s", *q)) >= l) 2482830Sdjl return (NSS_STR_PARSE_ERANGE); 2492830Sdjl l -= n; 2502830Sdjl s += n; 2512830Sdjl } 2522830Sdjl } 2532830Sdjl } 2542830Sdjl 2552830Sdjl ap->returnlen = s - ap->buf.buffer; 2562830Sdjl return (NSS_STR_PARSE_SUCCESS); 2572830Sdjl } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate nss_backend_t * 2600Sstevel@tonic-gate _nss_dns_constr(dns_backend_op_t ops[], int n_ops) 2610Sstevel@tonic-gate { 2620Sstevel@tonic-gate dns_backend_ptr_t be; 2630Sstevel@tonic-gate 2642830Sdjl if ((be = (dns_backend_ptr_t)malloc(sizeof (*be))) == 0) 2650Sstevel@tonic-gate return (0); 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate be->ops = ops; 2680Sstevel@tonic-gate be->n_ops = n_ops; 2692830Sdjl return ((nss_backend_t *)be); 2702830Sdjl } 2712830Sdjl 2723176Smichen /* 2733176Smichen * __res_ndestroy is a simplified version of the non-public function 2743176Smichen * res_ndestroy in libresolv.so.2. Before res_ndestroy can be made 2753176Smichen * public, __res_ndestroy will be used to make sure the memory pointed 2763176Smichen * by statp->_u._ext.ext is freed after res_nclose() is called. 2773176Smichen */ 2783176Smichen static void 2793176Smichen __res_ndestroy(res_state statp) { 2803176Smichen res_nclose(statp); 2813176Smichen if (statp->_u._ext.ext != NULL) 2823176Smichen free(statp->_u._ext.ext); 2833176Smichen } 2842830Sdjl 2852830Sdjl /* 2862830Sdjl * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 2872830Sdjl * nss2 get hosts/ipnodes with ttl backend DNS search engine. 2882830Sdjl * 2892830Sdjl * This API is given a pointer to a packed buffer, and the buffer size 2902830Sdjl * It's job is to perform the appropriate res_nsearch, extract the 2912830Sdjl * results and build a unmarshalled hosts/ipnodes result buffer. 2922830Sdjl * Additionally in the extended results a nssuint_t ttl is placed. 2932830Sdjl * This ttl is the lessor of the ttl's extracted from the result. 2942830Sdjl * 2952830Sdjl * ***Currently the first version of this API only performs simple 2962830Sdjl * single res_nsearch lookups for with T_A or T_AAAA results. 2972830Sdjl * Other searches are deferred to the generic API w/t ttls. 2982830Sdjl * 2992830Sdjl * This function is not a generic res_* operation. It only performs 3002830Sdjl * a single T_A or T_AAAA lookups*** 3012830Sdjl * 3022830Sdjl * RETURNS: NSS_SUCCESS or NSS_ERROR 3032830Sdjl * If an NSS_ERROR result is returned, nscd is expected 3042830Sdjl * to resubmit the gethosts request using the old style 3052830Sdjl * nsswitch lookup format. 3062830Sdjl */ 3072830Sdjl 3082830Sdjl nss_status_t 3092830Sdjl _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 3102830Sdjl { 3112830Sdjl /* nss buffer variables */ 3122830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 3132830Sdjl nss_XbyY_args_t arg; 3142830Sdjl char *dbname; 3152830Sdjl int dbop; 3162830Sdjl nss_status_t sret; 3172830Sdjl size_t bsize, blen; 3182830Sdjl char *bptr; 3192830Sdjl /* resolver query variables */ 3202924Smichen struct __res_state stat, *statp; /* dns state block */ 3212924Smichen union msg { 3222924Smichen uchar_t buf[NS_MAXMSG]; /* max legal DNS answer size */ 3232924Smichen HEADER h; 3242924Smichen } resbuf; 3252924Smichen char aliases[NS_MAXMSG]; /* set of aliases */ 3262830Sdjl const char *name; 3272830Sdjl int qtype; 3282830Sdjl /* answer parsing variables */ 3292830Sdjl HEADER *hp; 3302830Sdjl uchar_t *cp; /* current location in message */ 3312830Sdjl uchar_t *bom; /* start of message */ 3322830Sdjl uchar_t *eom; /* end of message */ 3332830Sdjl uchar_t *eor; /* end of record */ 3342830Sdjl int ancount, qdcount; 3352830Sdjl int type, class; 3362830Sdjl nssuint_t nttl, ttl, *pttl; /* The purpose of this API */ 3372830Sdjl int n, ret; 3382830Sdjl const char *np; 3392830Sdjl /* temporary buffers */ 3402830Sdjl char nbuf[INET6_ADDRSTRLEN]; /* address parser */ 3412830Sdjl char host[MAXHOSTNAMELEN]; /* result host name */ 3422830Sdjl char ans[MAXHOSTNAMELEN]; /* record name */ 3432830Sdjl char aname[MAXHOSTNAMELEN]; /* alias result (C_NAME) */ 3442830Sdjl /* misc variables */ 3452830Sdjl int af; 3462830Sdjl char *ap, *apc; 347*5161Smichen int hlen = 0, alen, iplen, len; 3482830Sdjl 3492924Smichen statp = &stat; 3502924Smichen (void) memset(statp, '\0', sizeof (struct __res_state)); 3512924Smichen if (res_ninit(statp) == -1) 3522924Smichen return (NSS_ERROR); 3532924Smichen 3542924Smichen ap = apc = (char *)aliases; 3552830Sdjl alen = 0; 3562830Sdjl ttl = (nssuint_t)0xFFFFFFF; /* start w/max, find smaller */ 3572830Sdjl 3582830Sdjl /* save space for ttl otherwise, why bother... */ 3592830Sdjl bsize = pbuf->data_len - sizeof (nssuint_t); 3602830Sdjl bptr = (char *)buffer + pbuf->data_off; 3612830Sdjl blen = 0; 3622830Sdjl sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg); 3632830Sdjl if (sret != NSS_SUCCESS) { 3643176Smichen __res_ndestroy(statp); 3652830Sdjl return (NSS_ERROR); 3662830Sdjl } 3672830Sdjl 3682830Sdjl if (ipnode) { 3692830Sdjl /* initially only handle the simple cases */ 3702924Smichen if (arg.key.ipnode.flags != 0) { 3713176Smichen __res_ndestroy(statp); 3722830Sdjl return (NSS_ERROR); 3732924Smichen } 3742830Sdjl name = arg.key.ipnode.name; 3752830Sdjl if (arg.key.ipnode.af_family == AF_INET6) 3762830Sdjl qtype = T_AAAA; 3772830Sdjl else 3782830Sdjl qtype = T_A; 3792830Sdjl } else { 3802830Sdjl name = arg.key.name; 3812830Sdjl qtype = T_A; 3822830Sdjl } 3832924Smichen ret = res_nsearch(statp, name, C_IN, qtype, resbuf.buf, NS_MAXMSG); 3842830Sdjl if (ret == -1) { 3852924Smichen if (statp->res_h_errno == HOST_NOT_FOUND) { 3862830Sdjl pbuf->p_herrno = HOST_NOT_FOUND; 3872830Sdjl pbuf->p_status = NSS_NOTFOUND; 3882830Sdjl pbuf->data_len = 0; 3893176Smichen __res_ndestroy(statp); 3902830Sdjl return (NSS_NOTFOUND); 3912830Sdjl } 3922830Sdjl /* else lookup error - handle in general code */ 3933176Smichen __res_ndestroy(statp); 3942830Sdjl return (NSS_ERROR); 3952830Sdjl } 3962830Sdjl 3972924Smichen cp = resbuf.buf; 3982924Smichen hp = (HEADER *)&resbuf.h; 3992830Sdjl bom = cp; 4002830Sdjl eom = cp + ret; 4012830Sdjl 4022830Sdjl ancount = ntohs(hp->ancount); 4032830Sdjl qdcount = ntohs(hp->qdcount); 4042830Sdjl cp += HFIXEDSZ; 4052924Smichen if (qdcount != 1) { 4063176Smichen __res_ndestroy(statp); 4072830Sdjl return (NSS_ERROR); 4082924Smichen } 4092830Sdjl n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN); 4102830Sdjl if (n < 0) { 4113176Smichen __res_ndestroy(statp); 4122830Sdjl return (NSS_ERROR); 4132830Sdjl } else 4142830Sdjl hlen = strlen(host); 415*5161Smichen /* no host name is an error, return */ 416*5161Smichen if (hlen <= 0) { 417*5161Smichen __res_ndestroy(statp); 418*5161Smichen return (NSS_ERROR); 419*5161Smichen } 4202830Sdjl cp += n + QFIXEDSZ; 4212924Smichen if (cp > eom) { 4223176Smichen __res_ndestroy(statp); 4232830Sdjl return (NSS_ERROR); 4242924Smichen } 4252830Sdjl while (ancount-- > 0 && cp < eom && blen < bsize) { 4262830Sdjl n = dn_expand(bom, eom, cp, ans, MAXHOSTNAMELEN); 4272830Sdjl if (n > 0) { 4282924Smichen if (strncasecmp(host, ans, hlen) != 0) { 4293176Smichen __res_ndestroy(statp); 4302830Sdjl return (NSS_ERROR); /* spoof? */ 4312924Smichen } 4322830Sdjl } 4332830Sdjl cp += n; 4342830Sdjl /* bounds check */ 4352830Sdjl type = ns_get16(cp); /* type */ 4362830Sdjl cp += INT16SZ; 4372830Sdjl class = ns_get16(cp); /* class */ 4382830Sdjl cp += INT16SZ; 4392830Sdjl nttl = (nssuint_t)ns_get32(cp); /* ttl in sec */ 4402830Sdjl if (nttl < ttl) 4412830Sdjl ttl = nttl; 4422830Sdjl cp += INT32SZ; 4432830Sdjl n = ns_get16(cp); /* len */ 4442830Sdjl cp += INT16SZ; 4452830Sdjl if (class != C_IN) { 4462830Sdjl cp += n; 4472830Sdjl continue; 4482830Sdjl } 4492830Sdjl eor = cp + n; 4502830Sdjl if (type == T_CNAME) { 4512830Sdjl /* add an alias to the alias list */ 4522830Sdjl n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN); 4532830Sdjl if (n > 0) { 4542830Sdjl len = strlen(aname); 4552830Sdjl if (len > 0) { 4562830Sdjl /* 4572830Sdjl * Just error out if there is an 4582830Sdjl * attempted buffer overflow exploit 4592830Sdjl * generic code will do a syslog 4602830Sdjl */ 4613176Smichen if (alen + len + 2 > NS_MAXMSG) { 4623176Smichen __res_ndestroy(statp); 4632830Sdjl return (NSS_ERROR); 4643176Smichen } 4652830Sdjl *apc++ = ' '; 4662830Sdjl alen++; 4672830Sdjl (void) strlcpy(apc, aname, len + 1); 4682830Sdjl alen += len; 4692830Sdjl apc += len; 4702830Sdjl } 4712830Sdjl } 4722830Sdjl cp += n; 4732830Sdjl continue; 4742830Sdjl } 4752830Sdjl if (type != qtype) { 4762830Sdjl cp += n; 4772830Sdjl continue; 4782830Sdjl } 4792830Sdjl /* check data size */ 4802830Sdjl if ((type == T_A && n != INADDRSZ) || 4812830Sdjl (type == T_AAAA && n != IN6ADDRSZ)) { 4822830Sdjl cp += n; 4832830Sdjl continue; 4842830Sdjl } 4852830Sdjl af = (type == T_A ? AF_INET : AF_INET6); 4862830Sdjl np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN); 4872924Smichen if (np == NULL) { 4883176Smichen __res_ndestroy(statp); 4892830Sdjl return (NSS_ERROR); 4902924Smichen } 4912830Sdjl cp += n; 4922830Sdjl /* append IP host aliases to results */ 4932830Sdjl iplen = strlen(np); 4942830Sdjl /* ip <SP> hostname [<SP>][aliases] */ 4952830Sdjl len = iplen + 2 + hlen + alen; 4962830Sdjl if (alen > 0) 4972830Sdjl len++; 4983176Smichen if (blen + len > bsize) { 4993176Smichen __res_ndestroy(statp); 5002830Sdjl return (NSS_ERROR); 5013176Smichen } 5022830Sdjl (void) strlcpy(bptr, np, bsize - blen); 5032830Sdjl blen += iplen; 5042830Sdjl bptr += iplen; 5052830Sdjl *bptr++ = ' '; 5062830Sdjl blen++; 5072830Sdjl (void) strlcpy(bptr, host, bsize - blen); 5082830Sdjl blen += hlen; 5092830Sdjl bptr += hlen; 5102830Sdjl if (alen > 0) { 5112830Sdjl *bptr++ = ' '; 5122830Sdjl blen++; 5132830Sdjl (void) strlcpy(bptr, ap, bsize - blen); 5142830Sdjl blen += alen; 5152830Sdjl bptr += alen; 5162830Sdjl } 5172830Sdjl *bptr++ = '\n'; 5182830Sdjl blen++; 5192830Sdjl } 5202830Sdjl /* Presumably the buffer is now filled. */ 5212830Sdjl len = ROUND_UP(blen, sizeof (nssuint_t)); 5222830Sdjl /* still room? */ 5232830Sdjl if (len + sizeof (nssuint_t) > pbuf->data_len) { 5242830Sdjl /* sigh, no, what happened? */ 5253176Smichen __res_ndestroy(statp); 5262830Sdjl return (NSS_ERROR); 5272830Sdjl } 5282830Sdjl pbuf->ext_off = pbuf->data_off + len; 5292830Sdjl pbuf->ext_len = sizeof (nssuint_t); 5302830Sdjl pbuf->data_len = blen; 5312830Sdjl pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off)); 5322830Sdjl *pttl = ttl; 5333176Smichen __res_ndestroy(statp); 5342830Sdjl return (NSS_SUCCESS); 5352830Sdjl } 536