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*10544SStacey.Marshall@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 232830Sdjl * Use is subject to license terms. 242830Sdjl */ 252830Sdjl 262830Sdjl /* 270Sstevel@tonic-gate * dns_common.c 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate 302830Sdjl #include "dns_common.h" 310Sstevel@tonic-gate 322830Sdjl #pragma weak dn_expand 332830Sdjl #pragma weak res_ninit 342830Sdjl #pragma weak res_nsearch 352830Sdjl #pragma weak res_nclose 362830Sdjl #pragma weak ns_get16 372830Sdjl #pragma weak ns_get32 382830Sdjl #pragma weak __ns_get16 392830Sdjl #pragma weak __ns_get32 400Sstevel@tonic-gate 410Sstevel@tonic-gate #define DNS_ALIASES 0 420Sstevel@tonic-gate #define DNS_ADDRLIST 1 430Sstevel@tonic-gate #define DNS_MAPDLIST 2 440Sstevel@tonic-gate 456666Ssm26363 #ifndef tolower 466666Ssm26363 #define tolower(c) ((c) >= 'A' && (c) <= 'Z' ? (c) | 0x20 : (c)) 476666Ssm26363 #endif 486666Ssm26363 490Sstevel@tonic-gate static int 500Sstevel@tonic-gate dns_netdb_aliases(from_list, to_list, aliaspp, type, count, af_type) 510Sstevel@tonic-gate char **from_list, **to_list, **aliaspp; 520Sstevel@tonic-gate int type, *count, af_type; 530Sstevel@tonic-gate { 540Sstevel@tonic-gate char *fstr; 550Sstevel@tonic-gate int cnt = 0; 560Sstevel@tonic-gate size_t len; 570Sstevel@tonic-gate 580Sstevel@tonic-gate *count = 0; 590Sstevel@tonic-gate if ((char *)to_list >= *aliaspp) 600Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 610Sstevel@tonic-gate 620Sstevel@tonic-gate for (fstr = from_list[cnt]; fstr != NULL; fstr = from_list[cnt]) { 630Sstevel@tonic-gate if (type == DNS_ALIASES) 640Sstevel@tonic-gate len = strlen(fstr) + 1; 650Sstevel@tonic-gate else 660Sstevel@tonic-gate len = (af_type == AF_INET) ? sizeof (struct in_addr) 670Sstevel@tonic-gate : sizeof (struct in6_addr); 680Sstevel@tonic-gate *aliaspp -= len; 690Sstevel@tonic-gate to_list[cnt] = *aliaspp; 700Sstevel@tonic-gate if (*aliaspp <= (char *)&to_list[cnt+1]) 710Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 720Sstevel@tonic-gate if (type == DNS_MAPDLIST) { 732830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 742830Sdjl struct in6_addr *addr6p = (struct in6_addr *)*aliaspp; 750Sstevel@tonic-gate 760Sstevel@tonic-gate (void) memset(addr6p, '\0', sizeof (struct in6_addr)); 770Sstevel@tonic-gate (void) memcpy(&addr6p->s6_addr[12], fstr, 780Sstevel@tonic-gate sizeof (struct in_addr)); 790Sstevel@tonic-gate addr6p->s6_addr[10] = 0xffU; 800Sstevel@tonic-gate addr6p->s6_addr[11] = 0xffU; 810Sstevel@tonic-gate ++cnt; 820Sstevel@tonic-gate } else { 830Sstevel@tonic-gate (void) memcpy (*aliaspp, fstr, len); 840Sstevel@tonic-gate ++cnt; 850Sstevel@tonic-gate } 860Sstevel@tonic-gate } 870Sstevel@tonic-gate to_list[cnt] = NULL; 880Sstevel@tonic-gate 890Sstevel@tonic-gate *count = cnt; 900Sstevel@tonic-gate if (cnt == 0) 910Sstevel@tonic-gate return (NSS_STR_PARSE_PARSE); 920Sstevel@tonic-gate 930Sstevel@tonic-gate return (NSS_STR_PARSE_SUCCESS); 940Sstevel@tonic-gate } 950Sstevel@tonic-gate 960Sstevel@tonic-gate 970Sstevel@tonic-gate int 980Sstevel@tonic-gate ent2result(he, argp, af_type) 990Sstevel@tonic-gate struct hostent *he; 1000Sstevel@tonic-gate nss_XbyY_args_t *argp; 1010Sstevel@tonic-gate int af_type; 1020Sstevel@tonic-gate { 1030Sstevel@tonic-gate char *buffer, *limit; 1040Sstevel@tonic-gate int buflen = argp->buf.buflen; 1050Sstevel@tonic-gate int ret, count; 1060Sstevel@tonic-gate size_t len; 1070Sstevel@tonic-gate struct hostent *host; 1080Sstevel@tonic-gate struct in_addr *addrp; 1090Sstevel@tonic-gate struct in6_addr *addrp6; 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate limit = argp->buf.buffer + buflen; 1122830Sdjl host = (struct hostent *)argp->buf.result; 1130Sstevel@tonic-gate buffer = argp->buf.buffer; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* h_addrtype and h_length */ 1160Sstevel@tonic-gate host->h_addrtype = af_type; 1170Sstevel@tonic-gate host->h_length = (af_type == AF_INET) ? sizeof (struct in_addr) 1180Sstevel@tonic-gate : sizeof (struct in6_addr); 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate /* h_name */ 1210Sstevel@tonic-gate len = strlen(he->h_name) + 1; 1220Sstevel@tonic-gate host->h_name = buffer; 1230Sstevel@tonic-gate if (host->h_name + len >= limit) 1240Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 1250Sstevel@tonic-gate (void) memcpy(host->h_name, he->h_name, len); 1260Sstevel@tonic-gate buffer += len; 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* h_addr_list */ 1290Sstevel@tonic-gate if (af_type == AF_INET) { 1302830Sdjl addrp = (struct in_addr *)ROUND_DOWN(limit, sizeof (*addrp)); 1310Sstevel@tonic-gate host->h_addr_list = (char **) 1320Sstevel@tonic-gate ROUND_UP(buffer, sizeof (char **)); 1330Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_addr_list, host->h_addr_list, 1340Sstevel@tonic-gate (char **)&addrp, DNS_ADDRLIST, &count, af_type); 1350Sstevel@tonic-gate if (ret != NSS_STR_PARSE_SUCCESS) 1360Sstevel@tonic-gate return (ret); 1370Sstevel@tonic-gate /* h_aliases */ 1380Sstevel@tonic-gate host->h_aliases = host->h_addr_list + count + 1; 1390Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_aliases, host->h_aliases, 1400Sstevel@tonic-gate (char **)&addrp, DNS_ALIASES, &count, af_type); 1410Sstevel@tonic-gate } else { 1420Sstevel@tonic-gate addrp6 = (struct in6_addr *) 1430Sstevel@tonic-gate ROUND_DOWN(limit, sizeof (*addrp6)); 1440Sstevel@tonic-gate host->h_addr_list = (char **) 1450Sstevel@tonic-gate ROUND_UP(buffer, sizeof (char **)); 1460Sstevel@tonic-gate if (he->h_addrtype == AF_INET && af_type == AF_INET6) { 1470Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_addr_list, 1480Sstevel@tonic-gate host->h_addr_list, (char **)&addrp6, 1490Sstevel@tonic-gate DNS_MAPDLIST, &count, af_type); 1500Sstevel@tonic-gate } else { 1510Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_addr_list, 1520Sstevel@tonic-gate host->h_addr_list, (char **)&addrp6, 1530Sstevel@tonic-gate DNS_ADDRLIST, &count, af_type); 1540Sstevel@tonic-gate } 1550Sstevel@tonic-gate if (ret != NSS_STR_PARSE_SUCCESS) 1560Sstevel@tonic-gate return (ret); 1570Sstevel@tonic-gate /* h_aliases */ 1580Sstevel@tonic-gate host->h_aliases = host->h_addr_list + count + 1; 1590Sstevel@tonic-gate ret = dns_netdb_aliases(he->h_aliases, host->h_aliases, 1600Sstevel@tonic-gate (char **)&addrp6, DNS_ALIASES, &count, af_type); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate if (ret == NSS_STR_PARSE_PARSE) 1630Sstevel@tonic-gate ret = NSS_STR_PARSE_SUCCESS; 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate return (ret); 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 1682830Sdjl /* 1692830Sdjl * Convert the hostent structure into string in the following 1702830Sdjl * format: 1712830Sdjl * 1722830Sdjl * IP-address official-host-name nicknames ... 1732830Sdjl * 1742830Sdjl * If more than one IP-addresses matches the official-host-name, 1752830Sdjl * the above line will be followed by: 1762830Sdjl * IP-address-1 official-host-name 1772830Sdjl * IP-address-2 official-host-name 1782830Sdjl * ... 1792830Sdjl * 1802830Sdjl * This is so that the str2hostent function in libnsl 1812830Sdjl * can convert the string back to the original hostent 1822830Sdjl * data. 1832830Sdjl */ 1842830Sdjl int 1852830Sdjl ent2str( 1862830Sdjl struct hostent *hp, 1872830Sdjl nss_XbyY_args_t *ap, 1882830Sdjl int af_type) 1892830Sdjl { 1902830Sdjl char **p; 1912830Sdjl char obuf[INET6_ADDRSTRLEN]; 1922830Sdjl void *addr; 1932830Sdjl struct in_addr in4; 1942830Sdjl int af; 1952830Sdjl int n; 1962830Sdjl const char *res; 1972830Sdjl char **q; 1982830Sdjl int l = ap->buf.buflen; 1992830Sdjl char *s = ap->buf.buffer; 2002830Sdjl 2012830Sdjl /* 2022830Sdjl * for "hosts" lookup, we only want address type of 2032830Sdjl * AF_INET. For "ipnodes", we can have both AF_INET 2042830Sdjl * and AF_INET6. 2052830Sdjl */ 2062830Sdjl if (af_type == AF_INET && hp->h_addrtype != AF_INET) 2072830Sdjl return (NSS_STR_PARSE_PARSE); 2082830Sdjl 2092830Sdjl for (p = hp->h_addr_list; *p != 0; p++) { 2102830Sdjl 2112830Sdjl if (p != hp->h_addr_list) { 2122830Sdjl *s = '\n'; 2132830Sdjl s++; 2142830Sdjl l--; 2152830Sdjl } 2162830Sdjl 2172830Sdjl if (hp->h_addrtype == AF_INET6) { 2182830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 2192830Sdjl if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)*p)) { 2202830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 2212830Sdjl IN6_V4MAPPED_TO_INADDR((struct in6_addr *)*p, 2225161Smichen &in4); 2232830Sdjl af = AF_INET; 2242830Sdjl addr = &in4; 2252830Sdjl } else { 2262830Sdjl af = AF_INET6; 2272830Sdjl addr = *p; 2282830Sdjl } 2292830Sdjl } else { 2302830Sdjl af = AF_INET; 2312830Sdjl addr = *p; 2322830Sdjl } 2332830Sdjl res = inet_ntop(af, addr, obuf, sizeof (obuf)); 2342830Sdjl if (res == NULL) 2352830Sdjl return (NSS_STR_PARSE_PARSE); 2362830Sdjl 2375161Smichen if ((n = snprintf(s, l, "%s", res)) >= l) 2382830Sdjl return (NSS_STR_PARSE_ERANGE); 2392830Sdjl l -= n; 2402830Sdjl s += n; 2415161Smichen if (hp->h_name != NULL && *hp->h_name != '\0') { 2425161Smichen if ((n = snprintf(s, l, " %s", hp->h_name)) >= l) 2435161Smichen return (NSS_STR_PARSE_ERANGE); 2445161Smichen l -= n; 2455161Smichen s += n; 2465161Smichen } 2472830Sdjl if (p == hp->h_addr_list) { 2482830Sdjl for (q = hp->h_aliases; q && *q; q++) { 2492830Sdjl if ((n = snprintf(s, l, " %s", *q)) >= l) 2502830Sdjl return (NSS_STR_PARSE_ERANGE); 2512830Sdjl l -= n; 2522830Sdjl s += n; 2532830Sdjl } 2542830Sdjl } 2552830Sdjl } 2562830Sdjl 2572830Sdjl ap->returnlen = s - ap->buf.buffer; 2582830Sdjl return (NSS_STR_PARSE_SUCCESS); 2592830Sdjl } 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate nss_backend_t * 2620Sstevel@tonic-gate _nss_dns_constr(dns_backend_op_t ops[], int n_ops) 2630Sstevel@tonic-gate { 2640Sstevel@tonic-gate dns_backend_ptr_t be; 2650Sstevel@tonic-gate 2662830Sdjl if ((be = (dns_backend_ptr_t)malloc(sizeof (*be))) == 0) 2670Sstevel@tonic-gate return (0); 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate be->ops = ops; 2700Sstevel@tonic-gate be->n_ops = n_ops; 2712830Sdjl return ((nss_backend_t *)be); 2722830Sdjl } 2732830Sdjl 2743176Smichen /* 2753176Smichen * __res_ndestroy is a simplified version of the non-public function 2763176Smichen * res_ndestroy in libresolv.so.2. Before res_ndestroy can be made 2773176Smichen * public, __res_ndestroy will be used to make sure the memory pointed 2783176Smichen * by statp->_u._ext.ext is freed after res_nclose() is called. 2793176Smichen */ 2803176Smichen static void 2813176Smichen __res_ndestroy(res_state statp) { 2823176Smichen res_nclose(statp); 2833176Smichen if (statp->_u._ext.ext != NULL) 2843176Smichen free(statp->_u._ext.ext); 2853176Smichen } 2862830Sdjl 2872830Sdjl /* 2886666Ssm26363 * name_is_alias(aliases_ptr, name_ptr) 2896666Ssm26363 * Verify name matches an alias in the provided aliases list. 2906666Ssm26363 * 2916666Ssm26363 * Within DNS there should be only one canonical name, aliases should 2926666Ssm26363 * all refer to the one canonical. However alias chains do occur and 2936666Ssm26363 * pre BIND 9 servers may also respond with multiple CNAMEs. This 2946666Ssm26363 * routine checks if a given name has been provided as a CNAME in the 2956666Ssm26363 * response. This assumes that the chains have been sent in-order. 2966666Ssm26363 * 2976666Ssm26363 * INPUT: 2986666Ssm26363 * aliases_ptr: space separated list of alias names. 2996666Ssm26363 * name_ptr: name to look for in aliases_ptr list. 300*10544SStacey.Marshall@Sun.COM * RETURNS: NSS_SUCCESS or NSS_NOTFOUND 3016666Ssm26363 * NSS_SUCCESS indicates that the name is listed in the collected aliases. 3026666Ssm26363 */ 3036666Ssm26363 static nss_status_t 3046666Ssm26363 name_is_alias(char *aliases_ptr, char *name_ptr) { 3056666Ssm26363 char *host_ptr; 3066666Ssm26363 /* Loop through alias string and compare it against host string. */ 3076666Ssm26363 while (*aliases_ptr != '\0') { 3086666Ssm26363 host_ptr = name_ptr; 3096666Ssm26363 3106666Ssm26363 /* Compare name with alias. */ 3116666Ssm26363 while (tolower(*host_ptr) == tolower(*aliases_ptr) && 3126666Ssm26363 *host_ptr != '\0') { 3136666Ssm26363 host_ptr++; 3146666Ssm26363 aliases_ptr++; 3156666Ssm26363 } 3166666Ssm26363 3176666Ssm26363 /* 3186666Ssm26363 * If name was exhausted and the next character in the 3196666Ssm26363 * alias is either the end-of-string or space 3206666Ssm26363 * character then we have a match. 3216666Ssm26363 */ 3226666Ssm26363 if (*host_ptr == '\0' && 3236666Ssm26363 (*aliases_ptr == '\0' || *aliases_ptr == ' ')) { 3246666Ssm26363 return (NSS_SUCCESS); 3256666Ssm26363 } 3266666Ssm26363 3276666Ssm26363 /* Alias did not match, step over remainder of alias. */ 3286666Ssm26363 while (*aliases_ptr != ' ' && *aliases_ptr != '\0') 3296666Ssm26363 aliases_ptr++; 3306666Ssm26363 /* Step over separator character. */ 3316666Ssm26363 while (*aliases_ptr == ' ') aliases_ptr++; 3326666Ssm26363 } 333*10544SStacey.Marshall@Sun.COM return (NSS_NOTFOUND); 3346666Ssm26363 } 3356666Ssm26363 3366666Ssm26363 /* 3372830Sdjl * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 3382830Sdjl * nss2 get hosts/ipnodes with ttl backend DNS search engine. 3392830Sdjl * 3402830Sdjl * This API is given a pointer to a packed buffer, and the buffer size 3412830Sdjl * It's job is to perform the appropriate res_nsearch, extract the 3422830Sdjl * results and build a unmarshalled hosts/ipnodes result buffer. 3432830Sdjl * Additionally in the extended results a nssuint_t ttl is placed. 3442830Sdjl * This ttl is the lessor of the ttl's extracted from the result. 3452830Sdjl * 3462830Sdjl * ***Currently the first version of this API only performs simple 3472830Sdjl * single res_nsearch lookups for with T_A or T_AAAA results. 3482830Sdjl * Other searches are deferred to the generic API w/t ttls. 3492830Sdjl * 3502830Sdjl * This function is not a generic res_* operation. It only performs 3512830Sdjl * a single T_A or T_AAAA lookups*** 3522830Sdjl * 3532830Sdjl * RETURNS: NSS_SUCCESS or NSS_ERROR 3542830Sdjl * If an NSS_ERROR result is returned, nscd is expected 3552830Sdjl * to resubmit the gethosts request using the old style 3562830Sdjl * nsswitch lookup format. 3572830Sdjl */ 3582830Sdjl 3592830Sdjl nss_status_t 3602830Sdjl _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) 3612830Sdjl { 3622830Sdjl /* nss buffer variables */ 3632830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 3642830Sdjl nss_XbyY_args_t arg; 3652830Sdjl char *dbname; 3662830Sdjl int dbop; 3672830Sdjl nss_status_t sret; 3682830Sdjl size_t bsize, blen; 3692830Sdjl char *bptr; 3702830Sdjl /* resolver query variables */ 3712924Smichen struct __res_state stat, *statp; /* dns state block */ 3722924Smichen union msg { 3732924Smichen uchar_t buf[NS_MAXMSG]; /* max legal DNS answer size */ 3742924Smichen HEADER h; 3752924Smichen } resbuf; 3762924Smichen char aliases[NS_MAXMSG]; /* set of aliases */ 3772830Sdjl const char *name; 3782830Sdjl int qtype; 3792830Sdjl /* answer parsing variables */ 3802830Sdjl HEADER *hp; 3812830Sdjl uchar_t *cp; /* current location in message */ 3822830Sdjl uchar_t *bom; /* start of message */ 3832830Sdjl uchar_t *eom; /* end of message */ 3842830Sdjl uchar_t *eor; /* end of record */ 3852830Sdjl int ancount, qdcount; 3862830Sdjl int type, class; 3872830Sdjl nssuint_t nttl, ttl, *pttl; /* The purpose of this API */ 3882830Sdjl int n, ret; 3892830Sdjl const char *np; 3902830Sdjl /* temporary buffers */ 3912830Sdjl char nbuf[INET6_ADDRSTRLEN]; /* address parser */ 3922830Sdjl char host[MAXHOSTNAMELEN]; /* result host name */ 3932830Sdjl char ans[MAXHOSTNAMELEN]; /* record name */ 3942830Sdjl char aname[MAXHOSTNAMELEN]; /* alias result (C_NAME) */ 3952830Sdjl /* misc variables */ 3962830Sdjl int af; 3972830Sdjl char *ap, *apc; 398*10544SStacey.Marshall@Sun.COM int hlen = 0, alen, iplen, len, isans; 3992830Sdjl 4002924Smichen statp = &stat; 4012924Smichen (void) memset(statp, '\0', sizeof (struct __res_state)); 4022924Smichen if (res_ninit(statp) == -1) 4032924Smichen return (NSS_ERROR); 4042924Smichen 4052924Smichen ap = apc = (char *)aliases; 4062830Sdjl alen = 0; 4072830Sdjl ttl = (nssuint_t)0xFFFFFFF; /* start w/max, find smaller */ 4082830Sdjl 4092830Sdjl /* save space for ttl otherwise, why bother... */ 4102830Sdjl bsize = pbuf->data_len - sizeof (nssuint_t); 4112830Sdjl bptr = (char *)buffer + pbuf->data_off; 4122830Sdjl blen = 0; 4132830Sdjl sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg); 4142830Sdjl if (sret != NSS_SUCCESS) { 4153176Smichen __res_ndestroy(statp); 4162830Sdjl return (NSS_ERROR); 4172830Sdjl } 4182830Sdjl 4192830Sdjl if (ipnode) { 4202830Sdjl /* initially only handle the simple cases */ 4212924Smichen if (arg.key.ipnode.flags != 0) { 4223176Smichen __res_ndestroy(statp); 4232830Sdjl return (NSS_ERROR); 4242924Smichen } 4252830Sdjl name = arg.key.ipnode.name; 4262830Sdjl if (arg.key.ipnode.af_family == AF_INET6) 4272830Sdjl qtype = T_AAAA; 4282830Sdjl else 4292830Sdjl qtype = T_A; 4302830Sdjl } else { 4312830Sdjl name = arg.key.name; 4322830Sdjl qtype = T_A; 4332830Sdjl } 4342924Smichen ret = res_nsearch(statp, name, C_IN, qtype, resbuf.buf, NS_MAXMSG); 4352830Sdjl if (ret == -1) { 4362924Smichen if (statp->res_h_errno == HOST_NOT_FOUND) { 4372830Sdjl pbuf->p_herrno = HOST_NOT_FOUND; 4382830Sdjl pbuf->p_status = NSS_NOTFOUND; 4392830Sdjl pbuf->data_len = 0; 4403176Smichen __res_ndestroy(statp); 4412830Sdjl return (NSS_NOTFOUND); 4422830Sdjl } 4432830Sdjl /* else lookup error - handle in general code */ 4443176Smichen __res_ndestroy(statp); 4452830Sdjl return (NSS_ERROR); 4462830Sdjl } 4472830Sdjl 4482924Smichen cp = resbuf.buf; 4492924Smichen hp = (HEADER *)&resbuf.h; 4502830Sdjl bom = cp; 4512830Sdjl eom = cp + ret; 4522830Sdjl 4532830Sdjl ancount = ntohs(hp->ancount); 4542830Sdjl qdcount = ntohs(hp->qdcount); 4552830Sdjl cp += HFIXEDSZ; 4562924Smichen if (qdcount != 1) { 4573176Smichen __res_ndestroy(statp); 4582830Sdjl return (NSS_ERROR); 4592924Smichen } 4602830Sdjl n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN); 4612830Sdjl if (n < 0) { 4623176Smichen __res_ndestroy(statp); 4632830Sdjl return (NSS_ERROR); 4642830Sdjl } else 4652830Sdjl hlen = strlen(host); 4665161Smichen /* no host name is an error, return */ 4675161Smichen if (hlen <= 0) { 4685161Smichen __res_ndestroy(statp); 4695161Smichen return (NSS_ERROR); 4705161Smichen } 4712830Sdjl cp += n + QFIXEDSZ; 4722924Smichen if (cp > eom) { 4733176Smichen __res_ndestroy(statp); 4742830Sdjl return (NSS_ERROR); 4752924Smichen } 4762830Sdjl while (ancount-- > 0 && cp < eom && blen < bsize) { 4772830Sdjl n = dn_expand(bom, eom, cp, ans, MAXHOSTNAMELEN); 4782830Sdjl if (n > 0) { 4796666Ssm26363 /* 4806666Ssm26363 * Check that the expanded name is either the 4816666Ssm26363 * name we asked for or a learned alias. 4826666Ssm26363 */ 483*10544SStacey.Marshall@Sun.COM if ((isans = strncasecmp(host, ans, hlen)) != 0 && 484*10544SStacey.Marshall@Sun.COM (alen == 0 || name_is_alias(aliases, ans) 485*10544SStacey.Marshall@Sun.COM == NSS_NOTFOUND)) { 4863176Smichen __res_ndestroy(statp); 4872830Sdjl return (NSS_ERROR); /* spoof? */ 4882924Smichen } 4892830Sdjl } 4902830Sdjl cp += n; 4912830Sdjl /* bounds check */ 4922830Sdjl type = ns_get16(cp); /* type */ 4932830Sdjl cp += INT16SZ; 4942830Sdjl class = ns_get16(cp); /* class */ 4952830Sdjl cp += INT16SZ; 496*10544SStacey.Marshall@Sun.COM nttl = (nssuint_t)ns_get32(cp); /* ttl in sec */ 4972830Sdjl if (nttl < ttl) 4982830Sdjl ttl = nttl; 4992830Sdjl cp += INT32SZ; 5002830Sdjl n = ns_get16(cp); /* len */ 5012830Sdjl cp += INT16SZ; 5022830Sdjl if (class != C_IN) { 5032830Sdjl cp += n; 5042830Sdjl continue; 5052830Sdjl } 5062830Sdjl eor = cp + n; 5072830Sdjl if (type == T_CNAME) { 5086666Ssm26363 /* 509*10544SStacey.Marshall@Sun.COM * The name looked up is really an alias and the 510*10544SStacey.Marshall@Sun.COM * canonical name should be in the RDATA. 511*10544SStacey.Marshall@Sun.COM * A canonical name may have several aliases but an 512*10544SStacey.Marshall@Sun.COM * alias should only have one canonical name. 513*10544SStacey.Marshall@Sun.COM * However multiple CNAMEs and CNAME chains do exist! 514*10544SStacey.Marshall@Sun.COM * 515*10544SStacey.Marshall@Sun.COM * Just error out on attempted buffer overflow exploit, 516*10544SStacey.Marshall@Sun.COM * generic code will syslog. 517*10544SStacey.Marshall@Sun.COM * 5186666Ssm26363 */ 5192830Sdjl n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN); 520*10544SStacey.Marshall@Sun.COM if (n > 0 && (len = strlen(aname)) > 0) { 521*10544SStacey.Marshall@Sun.COM if (isans == 0) { /* host matched ans. */ 5222830Sdjl /* 523*10544SStacey.Marshall@Sun.COM * Append host to alias list. 5242830Sdjl */ 525*10544SStacey.Marshall@Sun.COM if (alen + hlen + 2 > NS_MAXMSG) { 5263176Smichen __res_ndestroy(statp); 5272830Sdjl return (NSS_ERROR); 5283176Smichen } 5292830Sdjl *apc++ = ' '; 5302830Sdjl alen++; 531*10544SStacey.Marshall@Sun.COM (void) strlcpy(apc, host, 532*10544SStacey.Marshall@Sun.COM NS_MAXMSG - alen); 533*10544SStacey.Marshall@Sun.COM alen += hlen; 534*10544SStacey.Marshall@Sun.COM apc += hlen; 5352830Sdjl } 536*10544SStacey.Marshall@Sun.COM /* 537*10544SStacey.Marshall@Sun.COM * Overwrite host with canonical name. 538*10544SStacey.Marshall@Sun.COM */ 539*10544SStacey.Marshall@Sun.COM if (strlcpy(host, aname, MAXHOSTNAMELEN) >= 540*10544SStacey.Marshall@Sun.COM MAXHOSTNAMELEN) { 541*10544SStacey.Marshall@Sun.COM __res_ndestroy(statp); 542*10544SStacey.Marshall@Sun.COM return (NSS_ERROR); 543*10544SStacey.Marshall@Sun.COM } 544*10544SStacey.Marshall@Sun.COM hlen = len; 5452830Sdjl } 5462830Sdjl cp += n; 5472830Sdjl continue; 5482830Sdjl } 5492830Sdjl if (type != qtype) { 5502830Sdjl cp += n; 5512830Sdjl continue; 5522830Sdjl } 5532830Sdjl /* check data size */ 5542830Sdjl if ((type == T_A && n != INADDRSZ) || 5552830Sdjl (type == T_AAAA && n != IN6ADDRSZ)) { 5562830Sdjl cp += n; 5572830Sdjl continue; 5582830Sdjl } 5592830Sdjl af = (type == T_A ? AF_INET : AF_INET6); 5602830Sdjl np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN); 5612924Smichen if (np == NULL) { 5623176Smichen __res_ndestroy(statp); 5632830Sdjl return (NSS_ERROR); 5642924Smichen } 5652830Sdjl cp += n; 5662830Sdjl /* append IP host aliases to results */ 5672830Sdjl iplen = strlen(np); 5682830Sdjl /* ip <SP> hostname [<SP>][aliases] */ 5692830Sdjl len = iplen + 2 + hlen + alen; 5702830Sdjl if (alen > 0) 5712830Sdjl len++; 5723176Smichen if (blen + len > bsize) { 5733176Smichen __res_ndestroy(statp); 5742830Sdjl return (NSS_ERROR); 5753176Smichen } 5762830Sdjl (void) strlcpy(bptr, np, bsize - blen); 5772830Sdjl blen += iplen; 5782830Sdjl bptr += iplen; 5792830Sdjl *bptr++ = ' '; 5802830Sdjl blen++; 5812830Sdjl (void) strlcpy(bptr, host, bsize - blen); 5822830Sdjl blen += hlen; 5832830Sdjl bptr += hlen; 5842830Sdjl if (alen > 0) { 5852830Sdjl *bptr++ = ' '; 5862830Sdjl blen++; 5872830Sdjl (void) strlcpy(bptr, ap, bsize - blen); 5882830Sdjl blen += alen; 5892830Sdjl bptr += alen; 5902830Sdjl } 5912830Sdjl *bptr++ = '\n'; 5922830Sdjl blen++; 5932830Sdjl } 5942830Sdjl /* Presumably the buffer is now filled. */ 5952830Sdjl len = ROUND_UP(blen, sizeof (nssuint_t)); 5962830Sdjl /* still room? */ 5972830Sdjl if (len + sizeof (nssuint_t) > pbuf->data_len) { 5982830Sdjl /* sigh, no, what happened? */ 5993176Smichen __res_ndestroy(statp); 6002830Sdjl return (NSS_ERROR); 6012830Sdjl } 6022830Sdjl pbuf->ext_off = pbuf->data_off + len; 6032830Sdjl pbuf->ext_len = sizeof (nssuint_t); 6042830Sdjl pbuf->data_len = blen; 6052830Sdjl pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off)); 6062830Sdjl *pttl = ttl; 6073176Smichen __res_ndestroy(statp); 6082830Sdjl return (NSS_SUCCESS); 6092830Sdjl } 610