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 /* 222830Sdjl * Copyright 2006 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, 2202830Sdjl &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 2352830Sdjl if ((n = snprintf(s, l, "%s %s", res, hp->h_name)) >= l) 2362830Sdjl return (NSS_STR_PARSE_ERANGE); 2372830Sdjl l -= n; 2382830Sdjl s += n; 2392830Sdjl if (p == hp->h_addr_list) { 2402830Sdjl for (q = hp->h_aliases; q && *q; q++) { 2412830Sdjl if ((n = snprintf(s, l, " %s", *q)) >= l) 2422830Sdjl return (NSS_STR_PARSE_ERANGE); 2432830Sdjl l -= n; 2442830Sdjl s += n; 2452830Sdjl } 2462830Sdjl } 2472830Sdjl } 2482830Sdjl 2492830Sdjl ap->returnlen = s - ap->buf.buffer; 2502830Sdjl return (NSS_STR_PARSE_SUCCESS); 2512830Sdjl } 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 2582830Sdjl 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; 2632830Sdjl return ((nss_backend_t *)be); 2642830Sdjl } 2652830Sdjl 2662830Sdjl 2672830Sdjl /* 2682830Sdjl * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 2692830Sdjl * nss2 get hosts/ipnodes with ttl backend DNS search engine. 2702830Sdjl * 2712830Sdjl * This API is given a pointer to a packed buffer, and the buffer size 2722830Sdjl * It's job is to perform the appropriate res_nsearch, extract the 2732830Sdjl * results and build a unmarshalled hosts/ipnodes result buffer. 2742830Sdjl * Additionally in the extended results a nssuint_t ttl is placed. 2752830Sdjl * This ttl is the lessor of the ttl's extracted from the result. 2762830Sdjl * 2772830Sdjl * ***Currently the first version of this API only performs simple 2782830Sdjl * single res_nsearch lookups for with T_A or T_AAAA results. 2792830Sdjl * Other searches are deferred to the generic API w/t ttls. 2802830Sdjl * 2812830Sdjl * This function is not a generic res_* operation. It only performs 2822830Sdjl * a single T_A or T_AAAA lookups*** 2832830Sdjl * 2842830Sdjl * RETURNS: NSS_SUCCESS or NSS_ERROR 2852830Sdjl * If an NSS_ERROR result is returned, nscd is expected 2862830Sdjl * to resubmit the gethosts request using the old style 2872830Sdjl * nsswitch lookup format. 2882830Sdjl */ 2892830Sdjl 2902830Sdjl nss_status_t 2912830Sdjl _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 2922830Sdjl { 2932830Sdjl /* nss buffer variables */ 2942830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 2952830Sdjl nss_XbyY_args_t arg; 2962830Sdjl char *dbname; 2972830Sdjl int dbop; 2982830Sdjl nss_status_t sret; 2992830Sdjl size_t bsize, blen; 3002830Sdjl char *bptr; 3012830Sdjl /* resolver query variables */ 302*2924Smichen struct __res_state stat, *statp; /* dns state block */ 303*2924Smichen union msg { 304*2924Smichen uchar_t buf[NS_MAXMSG]; /* max legal DNS answer size */ 305*2924Smichen HEADER h; 306*2924Smichen } resbuf; 307*2924Smichen char aliases[NS_MAXMSG]; /* set of aliases */ 3082830Sdjl const char *name; 3092830Sdjl int qtype; 3102830Sdjl /* answer parsing variables */ 3112830Sdjl HEADER *hp; 3122830Sdjl uchar_t *cp; /* current location in message */ 3132830Sdjl uchar_t *bom; /* start of message */ 3142830Sdjl uchar_t *eom; /* end of message */ 3152830Sdjl uchar_t *eor; /* end of record */ 3162830Sdjl int ancount, qdcount; 3172830Sdjl int type, class; 3182830Sdjl nssuint_t nttl, ttl, *pttl; /* The purpose of this API */ 3192830Sdjl int n, ret; 3202830Sdjl const char *np; 3212830Sdjl /* temporary buffers */ 3222830Sdjl char nbuf[INET6_ADDRSTRLEN]; /* address parser */ 3232830Sdjl char host[MAXHOSTNAMELEN]; /* result host name */ 3242830Sdjl char ans[MAXHOSTNAMELEN]; /* record name */ 3252830Sdjl char aname[MAXHOSTNAMELEN]; /* alias result (C_NAME) */ 3262830Sdjl /* misc variables */ 3272830Sdjl int af; 3282830Sdjl char *ap, *apc; 3292830Sdjl int hlen, alen, iplen, len; 3302830Sdjl 331*2924Smichen statp = &stat; 332*2924Smichen (void) memset(statp, '\0', sizeof (struct __res_state)); 333*2924Smichen if (res_ninit(statp) == -1) 334*2924Smichen return (NSS_ERROR); 335*2924Smichen 336*2924Smichen ap = apc = (char *)aliases; 3372830Sdjl alen = 0; 3382830Sdjl ttl = (nssuint_t)0xFFFFFFF; /* start w/max, find smaller */ 3392830Sdjl 3402830Sdjl /* save space for ttl otherwise, why bother... */ 3412830Sdjl bsize = pbuf->data_len - sizeof (nssuint_t); 3422830Sdjl bptr = (char *)buffer + pbuf->data_off; 3432830Sdjl blen = 0; 3442830Sdjl sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg); 3452830Sdjl if (sret != NSS_SUCCESS) { 346*2924Smichen res_nclose(statp); 3472830Sdjl return (NSS_ERROR); 3482830Sdjl } 3492830Sdjl 3502830Sdjl if (ipnode) { 3512830Sdjl /* initially only handle the simple cases */ 352*2924Smichen if (arg.key.ipnode.flags != 0) { 353*2924Smichen res_nclose(statp); 3542830Sdjl return (NSS_ERROR); 355*2924Smichen } 3562830Sdjl name = arg.key.ipnode.name; 3572830Sdjl if (arg.key.ipnode.af_family == AF_INET6) 3582830Sdjl qtype = T_AAAA; 3592830Sdjl else 3602830Sdjl qtype = T_A; 3612830Sdjl } else { 3622830Sdjl name = arg.key.name; 3632830Sdjl qtype = T_A; 3642830Sdjl } 365*2924Smichen ret = res_nsearch(statp, name, C_IN, qtype, resbuf.buf, NS_MAXMSG); 3662830Sdjl if (ret == -1) { 367*2924Smichen if (statp->res_h_errno == HOST_NOT_FOUND) { 3682830Sdjl pbuf->p_herrno = HOST_NOT_FOUND; 3692830Sdjl pbuf->p_status = NSS_NOTFOUND; 3702830Sdjl pbuf->data_len = 0; 371*2924Smichen res_nclose(statp); 3722830Sdjl return (NSS_NOTFOUND); 3732830Sdjl } 3742830Sdjl /* else lookup error - handle in general code */ 375*2924Smichen res_nclose(statp); 3762830Sdjl return (NSS_ERROR); 3772830Sdjl } 3782830Sdjl 379*2924Smichen cp = resbuf.buf; 380*2924Smichen hp = (HEADER *)&resbuf.h; 3812830Sdjl bom = cp; 3822830Sdjl eom = cp + ret; 3832830Sdjl 3842830Sdjl ancount = ntohs(hp->ancount); 3852830Sdjl qdcount = ntohs(hp->qdcount); 3862830Sdjl cp += HFIXEDSZ; 387*2924Smichen if (qdcount != 1) { 388*2924Smichen res_nclose(statp); 3892830Sdjl return (NSS_ERROR); 390*2924Smichen } 3912830Sdjl n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN); 3922830Sdjl if (n < 0) { 393*2924Smichen res_nclose(statp); 3942830Sdjl return (NSS_ERROR); 3952830Sdjl } else 3962830Sdjl hlen = strlen(host); 3972830Sdjl cp += n + QFIXEDSZ; 398*2924Smichen if (cp > eom) { 399*2924Smichen res_nclose(statp); 4002830Sdjl return (NSS_ERROR); 401*2924Smichen } 4022830Sdjl while (ancount-- > 0 && cp < eom && blen < bsize) { 4032830Sdjl n = dn_expand(bom, eom, cp, ans, MAXHOSTNAMELEN); 4042830Sdjl if (n > 0) { 405*2924Smichen if (strncasecmp(host, ans, hlen) != 0) { 406*2924Smichen res_nclose(statp); 4072830Sdjl return (NSS_ERROR); /* spoof? */ 408*2924Smichen } 4092830Sdjl } 4102830Sdjl cp += n; 4112830Sdjl /* bounds check */ 4122830Sdjl type = ns_get16(cp); /* type */ 4132830Sdjl cp += INT16SZ; 4142830Sdjl class = ns_get16(cp); /* class */ 4152830Sdjl cp += INT16SZ; 4162830Sdjl nttl = (nssuint_t)ns_get32(cp); /* ttl in sec */ 4172830Sdjl if (nttl < ttl) 4182830Sdjl ttl = nttl; 4192830Sdjl cp += INT32SZ; 4202830Sdjl n = ns_get16(cp); /* len */ 4212830Sdjl cp += INT16SZ; 4222830Sdjl if (class != C_IN) { 4232830Sdjl cp += n; 4242830Sdjl continue; 4252830Sdjl } 4262830Sdjl eor = cp + n; 4272830Sdjl if (type == T_CNAME) { 4282830Sdjl /* add an alias to the alias list */ 4292830Sdjl n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN); 4302830Sdjl if (n > 0) { 4312830Sdjl len = strlen(aname); 4322830Sdjl if (len > 0) { 4332830Sdjl /* 4342830Sdjl * Just error out if there is an 4352830Sdjl * attempted buffer overflow exploit 4362830Sdjl * generic code will do a syslog 4372830Sdjl */ 4382830Sdjl if (alen + len + 2 > NS_MAXMSG) 4392830Sdjl return (NSS_ERROR); 4402830Sdjl *apc++ = ' '; 4412830Sdjl alen++; 4422830Sdjl (void) strlcpy(apc, aname, len + 1); 4432830Sdjl alen += len; 4442830Sdjl apc += len; 4452830Sdjl } 4462830Sdjl } 4472830Sdjl cp += n; 4482830Sdjl continue; 4492830Sdjl } 4502830Sdjl if (type != qtype) { 4512830Sdjl cp += n; 4522830Sdjl continue; 4532830Sdjl } 4542830Sdjl /* check data size */ 4552830Sdjl if ((type == T_A && n != INADDRSZ) || 4562830Sdjl (type == T_AAAA && n != IN6ADDRSZ)) { 4572830Sdjl cp += n; 4582830Sdjl continue; 4592830Sdjl } 4602830Sdjl af = (type == T_A ? AF_INET : AF_INET6); 4612830Sdjl np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN); 462*2924Smichen if (np == NULL) { 463*2924Smichen res_nclose(statp); 4642830Sdjl return (NSS_ERROR); 465*2924Smichen } 4662830Sdjl cp += n; 4672830Sdjl /* append IP host aliases to results */ 4682830Sdjl iplen = strlen(np); 4692830Sdjl /* ip <SP> hostname [<SP>][aliases] */ 4702830Sdjl len = iplen + 2 + hlen + alen; 4712830Sdjl if (alen > 0) 4722830Sdjl len++; 4732830Sdjl if (blen + len > bsize) 4742830Sdjl return (NSS_ERROR); 4752830Sdjl (void) strlcpy(bptr, np, bsize - blen); 4762830Sdjl blen += iplen; 4772830Sdjl bptr += iplen; 4782830Sdjl *bptr++ = ' '; 4792830Sdjl blen++; 4802830Sdjl (void) strlcpy(bptr, host, bsize - blen); 4812830Sdjl blen += hlen; 4822830Sdjl bptr += hlen; 4832830Sdjl if (alen > 0) { 4842830Sdjl *bptr++ = ' '; 4852830Sdjl blen++; 4862830Sdjl (void) strlcpy(bptr, ap, bsize - blen); 4872830Sdjl blen += alen; 4882830Sdjl bptr += alen; 4892830Sdjl } 4902830Sdjl *bptr++ = '\n'; 4912830Sdjl blen++; 4922830Sdjl } 4932830Sdjl /* Presumably the buffer is now filled. */ 4942830Sdjl len = ROUND_UP(blen, sizeof (nssuint_t)); 4952830Sdjl /* still room? */ 4962830Sdjl if (len + sizeof (nssuint_t) > pbuf->data_len) { 4972830Sdjl /* sigh, no, what happened? */ 4982830Sdjl return (NSS_ERROR); 4992830Sdjl } 5002830Sdjl pbuf->ext_off = pbuf->data_off + len; 5012830Sdjl pbuf->ext_len = sizeof (nssuint_t); 5022830Sdjl pbuf->data_len = blen; 5032830Sdjl pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off)); 5042830Sdjl *pttl = ttl; 505*2924Smichen res_nclose(statp); 5062830Sdjl return (NSS_SUCCESS); 5072830Sdjl } 508