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 266*3176Smichen /* 267*3176Smichen * __res_ndestroy is a simplified version of the non-public function 268*3176Smichen * res_ndestroy in libresolv.so.2. Before res_ndestroy can be made 269*3176Smichen * public, __res_ndestroy will be used to make sure the memory pointed 270*3176Smichen * by statp->_u._ext.ext is freed after res_nclose() is called. 271*3176Smichen */ 272*3176Smichen static void 273*3176Smichen __res_ndestroy(res_state statp) { 274*3176Smichen res_nclose(statp); 275*3176Smichen if (statp->_u._ext.ext != NULL) 276*3176Smichen free(statp->_u._ext.ext); 277*3176Smichen } 2782830Sdjl 2792830Sdjl /* 2802830Sdjl * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 2812830Sdjl * nss2 get hosts/ipnodes with ttl backend DNS search engine. 2822830Sdjl * 2832830Sdjl * This API is given a pointer to a packed buffer, and the buffer size 2842830Sdjl * It's job is to perform the appropriate res_nsearch, extract the 2852830Sdjl * results and build a unmarshalled hosts/ipnodes result buffer. 2862830Sdjl * Additionally in the extended results a nssuint_t ttl is placed. 2872830Sdjl * This ttl is the lessor of the ttl's extracted from the result. 2882830Sdjl * 2892830Sdjl * ***Currently the first version of this API only performs simple 2902830Sdjl * single res_nsearch lookups for with T_A or T_AAAA results. 2912830Sdjl * Other searches are deferred to the generic API w/t ttls. 2922830Sdjl * 2932830Sdjl * This function is not a generic res_* operation. It only performs 2942830Sdjl * a single T_A or T_AAAA lookups*** 2952830Sdjl * 2962830Sdjl * RETURNS: NSS_SUCCESS or NSS_ERROR 2972830Sdjl * If an NSS_ERROR result is returned, nscd is expected 2982830Sdjl * to resubmit the gethosts request using the old style 2992830Sdjl * nsswitch lookup format. 3002830Sdjl */ 3012830Sdjl 3022830Sdjl nss_status_t 3032830Sdjl _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 3042830Sdjl { 3052830Sdjl /* nss buffer variables */ 3062830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 3072830Sdjl nss_XbyY_args_t arg; 3082830Sdjl char *dbname; 3092830Sdjl int dbop; 3102830Sdjl nss_status_t sret; 3112830Sdjl size_t bsize, blen; 3122830Sdjl char *bptr; 3132830Sdjl /* resolver query variables */ 3142924Smichen struct __res_state stat, *statp; /* dns state block */ 3152924Smichen union msg { 3162924Smichen uchar_t buf[NS_MAXMSG]; /* max legal DNS answer size */ 3172924Smichen HEADER h; 3182924Smichen } resbuf; 3192924Smichen char aliases[NS_MAXMSG]; /* set of aliases */ 3202830Sdjl const char *name; 3212830Sdjl int qtype; 3222830Sdjl /* answer parsing variables */ 3232830Sdjl HEADER *hp; 3242830Sdjl uchar_t *cp; /* current location in message */ 3252830Sdjl uchar_t *bom; /* start of message */ 3262830Sdjl uchar_t *eom; /* end of message */ 3272830Sdjl uchar_t *eor; /* end of record */ 3282830Sdjl int ancount, qdcount; 3292830Sdjl int type, class; 3302830Sdjl nssuint_t nttl, ttl, *pttl; /* The purpose of this API */ 3312830Sdjl int n, ret; 3322830Sdjl const char *np; 3332830Sdjl /* temporary buffers */ 3342830Sdjl char nbuf[INET6_ADDRSTRLEN]; /* address parser */ 3352830Sdjl char host[MAXHOSTNAMELEN]; /* result host name */ 3362830Sdjl char ans[MAXHOSTNAMELEN]; /* record name */ 3372830Sdjl char aname[MAXHOSTNAMELEN]; /* alias result (C_NAME) */ 3382830Sdjl /* misc variables */ 3392830Sdjl int af; 3402830Sdjl char *ap, *apc; 3412830Sdjl int hlen, alen, iplen, len; 3422830Sdjl 3432924Smichen statp = &stat; 3442924Smichen (void) memset(statp, '\0', sizeof (struct __res_state)); 3452924Smichen if (res_ninit(statp) == -1) 3462924Smichen return (NSS_ERROR); 3472924Smichen 3482924Smichen ap = apc = (char *)aliases; 3492830Sdjl alen = 0; 3502830Sdjl ttl = (nssuint_t)0xFFFFFFF; /* start w/max, find smaller */ 3512830Sdjl 3522830Sdjl /* save space for ttl otherwise, why bother... */ 3532830Sdjl bsize = pbuf->data_len - sizeof (nssuint_t); 3542830Sdjl bptr = (char *)buffer + pbuf->data_off; 3552830Sdjl blen = 0; 3562830Sdjl sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg); 3572830Sdjl if (sret != NSS_SUCCESS) { 358*3176Smichen __res_ndestroy(statp); 3592830Sdjl return (NSS_ERROR); 3602830Sdjl } 3612830Sdjl 3622830Sdjl if (ipnode) { 3632830Sdjl /* initially only handle the simple cases */ 3642924Smichen if (arg.key.ipnode.flags != 0) { 365*3176Smichen __res_ndestroy(statp); 3662830Sdjl return (NSS_ERROR); 3672924Smichen } 3682830Sdjl name = arg.key.ipnode.name; 3692830Sdjl if (arg.key.ipnode.af_family == AF_INET6) 3702830Sdjl qtype = T_AAAA; 3712830Sdjl else 3722830Sdjl qtype = T_A; 3732830Sdjl } else { 3742830Sdjl name = arg.key.name; 3752830Sdjl qtype = T_A; 3762830Sdjl } 3772924Smichen ret = res_nsearch(statp, name, C_IN, qtype, resbuf.buf, NS_MAXMSG); 3782830Sdjl if (ret == -1) { 3792924Smichen if (statp->res_h_errno == HOST_NOT_FOUND) { 3802830Sdjl pbuf->p_herrno = HOST_NOT_FOUND; 3812830Sdjl pbuf->p_status = NSS_NOTFOUND; 3822830Sdjl pbuf->data_len = 0; 383*3176Smichen __res_ndestroy(statp); 3842830Sdjl return (NSS_NOTFOUND); 3852830Sdjl } 3862830Sdjl /* else lookup error - handle in general code */ 387*3176Smichen __res_ndestroy(statp); 3882830Sdjl return (NSS_ERROR); 3892830Sdjl } 3902830Sdjl 3912924Smichen cp = resbuf.buf; 3922924Smichen hp = (HEADER *)&resbuf.h; 3932830Sdjl bom = cp; 3942830Sdjl eom = cp + ret; 3952830Sdjl 3962830Sdjl ancount = ntohs(hp->ancount); 3972830Sdjl qdcount = ntohs(hp->qdcount); 3982830Sdjl cp += HFIXEDSZ; 3992924Smichen if (qdcount != 1) { 400*3176Smichen __res_ndestroy(statp); 4012830Sdjl return (NSS_ERROR); 4022924Smichen } 4032830Sdjl n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN); 4042830Sdjl if (n < 0) { 405*3176Smichen __res_ndestroy(statp); 4062830Sdjl return (NSS_ERROR); 4072830Sdjl } else 4082830Sdjl hlen = strlen(host); 4092830Sdjl cp += n + QFIXEDSZ; 4102924Smichen if (cp > eom) { 411*3176Smichen __res_ndestroy(statp); 4122830Sdjl return (NSS_ERROR); 4132924Smichen } 4142830Sdjl while (ancount-- > 0 && cp < eom && blen < bsize) { 4152830Sdjl n = dn_expand(bom, eom, cp, ans, MAXHOSTNAMELEN); 4162830Sdjl if (n > 0) { 4172924Smichen if (strncasecmp(host, ans, hlen) != 0) { 418*3176Smichen __res_ndestroy(statp); 4192830Sdjl return (NSS_ERROR); /* spoof? */ 4202924Smichen } 4212830Sdjl } 4222830Sdjl cp += n; 4232830Sdjl /* bounds check */ 4242830Sdjl type = ns_get16(cp); /* type */ 4252830Sdjl cp += INT16SZ; 4262830Sdjl class = ns_get16(cp); /* class */ 4272830Sdjl cp += INT16SZ; 4282830Sdjl nttl = (nssuint_t)ns_get32(cp); /* ttl in sec */ 4292830Sdjl if (nttl < ttl) 4302830Sdjl ttl = nttl; 4312830Sdjl cp += INT32SZ; 4322830Sdjl n = ns_get16(cp); /* len */ 4332830Sdjl cp += INT16SZ; 4342830Sdjl if (class != C_IN) { 4352830Sdjl cp += n; 4362830Sdjl continue; 4372830Sdjl } 4382830Sdjl eor = cp + n; 4392830Sdjl if (type == T_CNAME) { 4402830Sdjl /* add an alias to the alias list */ 4412830Sdjl n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN); 4422830Sdjl if (n > 0) { 4432830Sdjl len = strlen(aname); 4442830Sdjl if (len > 0) { 4452830Sdjl /* 4462830Sdjl * Just error out if there is an 4472830Sdjl * attempted buffer overflow exploit 4482830Sdjl * generic code will do a syslog 4492830Sdjl */ 450*3176Smichen if (alen + len + 2 > NS_MAXMSG) { 451*3176Smichen __res_ndestroy(statp); 4522830Sdjl return (NSS_ERROR); 453*3176Smichen } 4542830Sdjl *apc++ = ' '; 4552830Sdjl alen++; 4562830Sdjl (void) strlcpy(apc, aname, len + 1); 4572830Sdjl alen += len; 4582830Sdjl apc += len; 4592830Sdjl } 4602830Sdjl } 4612830Sdjl cp += n; 4622830Sdjl continue; 4632830Sdjl } 4642830Sdjl if (type != qtype) { 4652830Sdjl cp += n; 4662830Sdjl continue; 4672830Sdjl } 4682830Sdjl /* check data size */ 4692830Sdjl if ((type == T_A && n != INADDRSZ) || 4702830Sdjl (type == T_AAAA && n != IN6ADDRSZ)) { 4712830Sdjl cp += n; 4722830Sdjl continue; 4732830Sdjl } 4742830Sdjl af = (type == T_A ? AF_INET : AF_INET6); 4752830Sdjl np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN); 4762924Smichen if (np == NULL) { 477*3176Smichen __res_ndestroy(statp); 4782830Sdjl return (NSS_ERROR); 4792924Smichen } 4802830Sdjl cp += n; 4812830Sdjl /* append IP host aliases to results */ 4822830Sdjl iplen = strlen(np); 4832830Sdjl /* ip <SP> hostname [<SP>][aliases] */ 4842830Sdjl len = iplen + 2 + hlen + alen; 4852830Sdjl if (alen > 0) 4862830Sdjl len++; 487*3176Smichen if (blen + len > bsize) { 488*3176Smichen __res_ndestroy(statp); 4892830Sdjl return (NSS_ERROR); 490*3176Smichen } 4912830Sdjl (void) strlcpy(bptr, np, bsize - blen); 4922830Sdjl blen += iplen; 4932830Sdjl bptr += iplen; 4942830Sdjl *bptr++ = ' '; 4952830Sdjl blen++; 4962830Sdjl (void) strlcpy(bptr, host, bsize - blen); 4972830Sdjl blen += hlen; 4982830Sdjl bptr += hlen; 4992830Sdjl if (alen > 0) { 5002830Sdjl *bptr++ = ' '; 5012830Sdjl blen++; 5022830Sdjl (void) strlcpy(bptr, ap, bsize - blen); 5032830Sdjl blen += alen; 5042830Sdjl bptr += alen; 5052830Sdjl } 5062830Sdjl *bptr++ = '\n'; 5072830Sdjl blen++; 5082830Sdjl } 5092830Sdjl /* Presumably the buffer is now filled. */ 5102830Sdjl len = ROUND_UP(blen, sizeof (nssuint_t)); 5112830Sdjl /* still room? */ 5122830Sdjl if (len + sizeof (nssuint_t) > pbuf->data_len) { 5132830Sdjl /* sigh, no, what happened? */ 514*3176Smichen __res_ndestroy(statp); 5152830Sdjl return (NSS_ERROR); 5162830Sdjl } 5172830Sdjl pbuf->ext_off = pbuf->data_off + len; 5182830Sdjl pbuf->ext_len = sizeof (nssuint_t); 5192830Sdjl pbuf->data_len = blen; 5202830Sdjl pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off)); 5212830Sdjl *pttl = ttl; 522*3176Smichen __res_ndestroy(statp); 5232830Sdjl return (NSS_SUCCESS); 5242830Sdjl } 525