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 */ 212975Sjbeck 220Sstevel@tonic-gate /* 23*6812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 242830Sdjl * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * gethostent.c 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * In order to avoid duplicating libresolv code here, and since libresolv.so.2 330Sstevel@tonic-gate * provides res_-equivalents of the getXbyY and {set,get}Xent, lets call 340Sstevel@tonic-gate * re_gethostbyaddr() and so on from this file. Among other things, this 350Sstevel@tonic-gate * should help us avoid problems like the one described in bug 1264386, 360Sstevel@tonic-gate * where the internal getanswer() acquired new functionality in BIND 4.9.3, 370Sstevel@tonic-gate * but the local copy of getanswer() in this file wasn't updated, so that new 380Sstevel@tonic-gate * functionality wasn't available to the name service switch. 390Sstevel@tonic-gate */ 400Sstevel@tonic-gate 410Sstevel@tonic-gate #define gethostbyaddr res_gethostbyaddr 420Sstevel@tonic-gate #define gethostbyname res_gethostbyname 430Sstevel@tonic-gate #define gethostbyname2 res_gethostbyname2 440Sstevel@tonic-gate #define sethostent res_sethostent 450Sstevel@tonic-gate #define endhostent res_endhostent 460Sstevel@tonic-gate 470Sstevel@tonic-gate #include "dns_common.h" 480Sstevel@tonic-gate 490Sstevel@tonic-gate extern char *inet_ntoa(struct in_addr in); 500Sstevel@tonic-gate 510Sstevel@tonic-gate struct hostent *_gethostbyname(int *h_errnop, const char *name); 520Sstevel@tonic-gate static struct hostent *_gethostbyaddr(int *h_errnop, const char *addr, 530Sstevel@tonic-gate int len, int type); 540Sstevel@tonic-gate struct hostent *_nss_dns_gethostbyname2(int *h_errnop, const char *name); 550Sstevel@tonic-gate 560Sstevel@tonic-gate #pragma weak res_gethostbyname 570Sstevel@tonic-gate #pragma weak res_gethostbyname2 580Sstevel@tonic-gate #pragma weak res_gethostbyaddr 590Sstevel@tonic-gate #pragma weak res_sethostent 600Sstevel@tonic-gate #pragma weak res_endhostent 610Sstevel@tonic-gate 620Sstevel@tonic-gate nss_backend_t *_nss_dns_constr(dns_backend_op_t ops[], int n_ops); 630Sstevel@tonic-gate nss_status_t __nss_dns_getbyaddr(dns_backend_ptr_t, void *); 640Sstevel@tonic-gate 650Sstevel@tonic-gate typedef union { 660Sstevel@tonic-gate long al; 670Sstevel@tonic-gate char ac; 680Sstevel@tonic-gate } align; 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * Internet Name Domain Server (DNS) only implementation. 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate static struct hostent * 740Sstevel@tonic-gate _gethostbyaddr(int *h_errnop, const char *addr, int len, int type) 750Sstevel@tonic-gate { 760Sstevel@tonic-gate struct hostent *hp; 770Sstevel@tonic-gate 780Sstevel@tonic-gate hp = gethostbyaddr(addr, len, type); 790Sstevel@tonic-gate *h_errnop = *get_h_errno(); 800Sstevel@tonic-gate return (hp); 810Sstevel@tonic-gate } 820Sstevel@tonic-gate 830Sstevel@tonic-gate struct hostent * 840Sstevel@tonic-gate _nss_dns_gethostbyname2(int *h_errnop, const char *name) 850Sstevel@tonic-gate { 860Sstevel@tonic-gate struct hostent *hp; 870Sstevel@tonic-gate 880Sstevel@tonic-gate hp = gethostbyname2(name, AF_INET6); 890Sstevel@tonic-gate *h_errnop = *get_h_errno(); 900Sstevel@tonic-gate return (hp); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate struct hostent * 940Sstevel@tonic-gate _gethostbyname(int *h_errnop, const char *name) 950Sstevel@tonic-gate { 960Sstevel@tonic-gate struct hostent *hp; 970Sstevel@tonic-gate 980Sstevel@tonic-gate hp = gethostbyname(name); 990Sstevel@tonic-gate *h_errnop = *get_h_errno(); 1000Sstevel@tonic-gate return (hp); 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate static void 1040Sstevel@tonic-gate _sethostent(errp, stayopen) 1050Sstevel@tonic-gate nss_status_t *errp; 1060Sstevel@tonic-gate int stayopen; 1070Sstevel@tonic-gate { 1080Sstevel@tonic-gate int ret; 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate ret = sethostent(stayopen); 1110Sstevel@tonic-gate if (ret == 0) 1120Sstevel@tonic-gate *errp = NSS_SUCCESS; 1130Sstevel@tonic-gate else 1140Sstevel@tonic-gate *errp = NSS_UNAVAIL; 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate static void 1180Sstevel@tonic-gate _endhostent(errp) 1190Sstevel@tonic-gate nss_status_t *errp; 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate int ret; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate ret = endhostent(); 1240Sstevel@tonic-gate if (ret == 0) 1250Sstevel@tonic-gate *errp = NSS_SUCCESS; 1260Sstevel@tonic-gate else 1270Sstevel@tonic-gate *errp = NSS_UNAVAIL; 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /*ARGSUSED*/ 1320Sstevel@tonic-gate static nss_status_t 1330Sstevel@tonic-gate getbyname(be, a) 1340Sstevel@tonic-gate dns_backend_ptr_t be; 1350Sstevel@tonic-gate void *a; 1360Sstevel@tonic-gate { 1370Sstevel@tonic-gate struct hostent *he; 1380Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1390Sstevel@tonic-gate int ret, mt_disabled; 1400Sstevel@tonic-gate int old_retry; 1410Sstevel@tonic-gate sigset_t oldmask; 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate switch_resolver_setup(&mt_disabled, &oldmask, &old_retry); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate he = _gethostbyname(&argp->h_errno, argp->key.name); 1460Sstevel@tonic-gate if (he != NULL) { 1472830Sdjl if (argp->buf.result == NULL) { 1482830Sdjl /* 1492830Sdjl * if asked to return data in string, 1502830Sdjl * convert the hostent structure into 1512830Sdjl * string data 1522830Sdjl */ 1532830Sdjl ret = ent2str(he, a, AF_INET); 1542830Sdjl if (ret == NSS_STR_PARSE_SUCCESS) 1552830Sdjl argp->returnval = argp->buf.buffer; 1560Sstevel@tonic-gate } else { 1572830Sdjl ret = ent2result(he, a, AF_INET); 1582830Sdjl if (ret == NSS_STR_PARSE_SUCCESS) 1592830Sdjl argp->returnval = argp->buf.result; 1602830Sdjl } 1612830Sdjl 1622830Sdjl if (ret != NSS_STR_PARSE_SUCCESS) { 1630Sstevel@tonic-gate argp->h_errno = HOST_NOT_FOUND; 1640Sstevel@tonic-gate if (ret == NSS_STR_PARSE_ERANGE) { 1650Sstevel@tonic-gate argp->erange = 1; 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate switch_resolver_reset(mt_disabled, oldmask, old_retry); 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate return (_herrno2nss(argp->h_errno)); 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate /*ARGSUSED*/ 1780Sstevel@tonic-gate static nss_status_t 1790Sstevel@tonic-gate getbyaddr(be, a) 1800Sstevel@tonic-gate dns_backend_ptr_t be; 1810Sstevel@tonic-gate void *a; 1820Sstevel@tonic-gate { 1830Sstevel@tonic-gate return (__nss_dns_getbyaddr(be, a)); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* 1880Sstevel@tonic-gate * Exposing a DNS backend specific interface so that it doesn't conflict 1890Sstevel@tonic-gate * with other getbyaddr() routines from other switch backends. 1900Sstevel@tonic-gate */ 1912830Sdjl /*ARGSUSED*/ 1920Sstevel@tonic-gate nss_status_t 1930Sstevel@tonic-gate __nss_dns_getbyaddr(be, a) 1940Sstevel@tonic-gate dns_backend_ptr_t be; 1950Sstevel@tonic-gate void *a; 1960Sstevel@tonic-gate { 1972975Sjbeck struct hostent *he; 1980Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1992975Sjbeck int ret, mt_disabled; 2000Sstevel@tonic-gate struct in_addr unmapv4; 2010Sstevel@tonic-gate sigset_t oldmask; 2020Sstevel@tonic-gate int af, addrlen; 2030Sstevel@tonic-gate void *addrp; 2040Sstevel@tonic-gate int old_retry; 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate switch_resolver_setup(&mt_disabled, &oldmask, &old_retry); 2070Sstevel@tonic-gate 2082830Sdjl /* LINTED: E_BAD_PTR_CAST_ALIGN */ 2090Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)argp->key.hostaddr.addr)) { 2100Sstevel@tonic-gate addrp = &unmapv4; 2110Sstevel@tonic-gate addrlen = sizeof (unmapv4); 2120Sstevel@tonic-gate af = AF_INET; 2132830Sdjl (void) memcpy(addrp, &argp->key.hostaddr.addr[12], addrlen); 2140Sstevel@tonic-gate } else { 2150Sstevel@tonic-gate addrp = (void *)argp->key.hostaddr.addr; 2160Sstevel@tonic-gate addrlen = argp->key.hostaddr.len; 2170Sstevel@tonic-gate af = argp->key.hostaddr.type; 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate he = _gethostbyaddr(&argp->h_errno, addrp, addrlen, af); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate if (he != NULL) { 2222975Sjbeck /* 2232975Sjbeck * if asked to return data in string, convert 2242975Sjbeck * the hostent structure into string data 2252975Sjbeck */ 2262975Sjbeck if (argp->buf.result == NULL) 2272975Sjbeck ret = ent2str(he, a, argp->key.hostaddr.type); 2282975Sjbeck else 2292975Sjbeck ret = ent2result(he, a, argp->key.hostaddr.type); 2300Sstevel@tonic-gate 2312975Sjbeck if (ret == NSS_STR_PARSE_SUCCESS) { 2322975Sjbeck if (argp->buf.result == NULL) 2332975Sjbeck argp->returnval = argp->buf.buffer; 2342975Sjbeck else 2352975Sjbeck argp->returnval = argp->buf.result; 2360Sstevel@tonic-gate } else { 2370Sstevel@tonic-gate argp->h_errno = HOST_NOT_FOUND; 2382975Sjbeck if (ret == NSS_STR_PARSE_ERANGE) 2390Sstevel@tonic-gate argp->erange = 1; 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate switch_resolver_reset(mt_disabled, oldmask, old_retry); 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate return (_herrno2nss(argp->h_errno)); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate /*ARGSUSED*/ 2500Sstevel@tonic-gate static nss_status_t 2510Sstevel@tonic-gate _nss_dns_getent(be, args) 2520Sstevel@tonic-gate dns_backend_ptr_t be; 2530Sstevel@tonic-gate void *args; 2540Sstevel@tonic-gate { 2550Sstevel@tonic-gate return (NSS_UNAVAIL); 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate /*ARGSUSED*/ 2600Sstevel@tonic-gate static nss_status_t 2610Sstevel@tonic-gate _nss_dns_setent(be, dummy) 2620Sstevel@tonic-gate dns_backend_ptr_t be; 2630Sstevel@tonic-gate void *dummy; 2640Sstevel@tonic-gate { 2650Sstevel@tonic-gate nss_status_t errp; 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate sigset_t oldmask, newmask; 2680Sstevel@tonic-gate int mt_disabled = 1; 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* 2710Sstevel@tonic-gate * Try to enable MT; if not, we have to single-thread libresolv 2720Sstevel@tonic-gate * access 2730Sstevel@tonic-gate */ 2740Sstevel@tonic-gate if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) { 2750Sstevel@tonic-gate (void) sigfillset(&newmask); 276*6812Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 277*6812Sraf (void) mutex_lock(&one_lane); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate _sethostent(&errp, 1); 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate if (mt_disabled) { 283*6812Sraf (void) mutex_unlock(&one_lane); 284*6812Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 2850Sstevel@tonic-gate } else { 2860Sstevel@tonic-gate (void) (*disable_mt)(); 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate return (errp); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /*ARGSUSED*/ 2940Sstevel@tonic-gate static nss_status_t 2950Sstevel@tonic-gate _nss_dns_endent(be, dummy) 2960Sstevel@tonic-gate dns_backend_ptr_t be; 2970Sstevel@tonic-gate void *dummy; 2980Sstevel@tonic-gate { 2990Sstevel@tonic-gate nss_status_t errp; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate sigset_t oldmask, newmask; 3020Sstevel@tonic-gate int mt_disabled = 1; 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate /* 3050Sstevel@tonic-gate * Try to enable MT; if not, we have to single-thread libresolv 3060Sstevel@tonic-gate * access 3070Sstevel@tonic-gate */ 3080Sstevel@tonic-gate if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) { 3090Sstevel@tonic-gate (void) sigfillset(&newmask); 310*6812Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 311*6812Sraf (void) mutex_lock(&one_lane); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate _endhostent(&errp); 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate if (mt_disabled) { 317*6812Sraf (void) mutex_unlock(&one_lane); 318*6812Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 3190Sstevel@tonic-gate } else { 3200Sstevel@tonic-gate (void) (*disable_mt)(); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate return (errp); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate /*ARGSUSED*/ 3280Sstevel@tonic-gate static nss_status_t 3290Sstevel@tonic-gate _nss_dns_destr(be, dummy) 3300Sstevel@tonic-gate dns_backend_ptr_t be; 3310Sstevel@tonic-gate void *dummy; 3320Sstevel@tonic-gate { 3330Sstevel@tonic-gate nss_status_t errp; 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate if (be != 0) { 3360Sstevel@tonic-gate /* === Should change to invoke ops[ENDENT] ? */ 3370Sstevel@tonic-gate sigset_t oldmask, newmask; 3380Sstevel@tonic-gate int mt_disabled = 1; 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) { 3410Sstevel@tonic-gate (void) sigfillset(&newmask); 342*6812Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 343*6812Sraf (void) mutex_lock(&one_lane); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate _endhostent(&errp); 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate if (mt_disabled) { 349*6812Sraf (void) mutex_unlock(&one_lane); 350*6812Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 3510Sstevel@tonic-gate } else { 3520Sstevel@tonic-gate (void) (*disable_mt)(); 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate free(be); 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate return (NSS_SUCCESS); /* In case anyone is dumb enough to check */ 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate static dns_backend_op_t host_ops[] = { 3620Sstevel@tonic-gate _nss_dns_destr, 3630Sstevel@tonic-gate _nss_dns_endent, 3640Sstevel@tonic-gate _nss_dns_setent, 3650Sstevel@tonic-gate _nss_dns_getent, 3660Sstevel@tonic-gate getbyname, 3670Sstevel@tonic-gate getbyaddr, 3680Sstevel@tonic-gate }; 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate /*ARGSUSED*/ 3710Sstevel@tonic-gate nss_backend_t * 3720Sstevel@tonic-gate _nss_dns_hosts_constr(dummy1, dummy2, dummy3) 3730Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 3740Sstevel@tonic-gate { 3750Sstevel@tonic-gate return (_nss_dns_constr(host_ops, 3760Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]))); 3770Sstevel@tonic-gate } 3782830Sdjl 3792830Sdjl /* 3802830Sdjl * optional NSS2 packed backend gethostsbyname with ttl 3812830Sdjl * entry point. 3822830Sdjl * 3832830Sdjl * Returns: 3842830Sdjl * NSS_SUCCESS - successful 3852830Sdjl * NSS_NOTFOUND - successful but nothing found 3862830Sdjl * NSS_ERROR - fallback to NSS backend lookup mode 3872830Sdjl * If successful, buffer will be filled with valid data 3882830Sdjl * 3892830Sdjl */ 3902830Sdjl 3912830Sdjl /*ARGSUSED*/ 3922830Sdjl nss_status_t 3932830Sdjl _nss_get_dns_hosts_name(dns_backend_ptr_t *be, void **bufp, size_t *sizep) 3942830Sdjl { 3952830Sdjl return (_nss_dns_gethost_withttl(*bufp, *sizep, 0)); 3962830Sdjl } 397