17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
58200fe25Srmesta * Common Development and Distribution License (the "License").
68200fe25Srmesta * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate * PSARC/2004/154 nfsmapid DNS enhancements implementation.
277c478bd9Sstevel@tonic-gate *
28ee89337bSMarcel Telka * As per RFC 7530, file owner and group attributes in version 4 of the
297c478bd9Sstevel@tonic-gate * NFS protocol are no longer exchanged between client and server as 32
307c478bd9Sstevel@tonic-gate * bit integral values. Instead, owner and group file attributes are
317c478bd9Sstevel@tonic-gate * exchanged between client and server as UTF8 strings of form
327c478bd9Sstevel@tonic-gate *
337c478bd9Sstevel@tonic-gate * 'user@domain' (ie. "joeblow@central.sun.com")
347c478bd9Sstevel@tonic-gate * 'group@domain' (ie. "staff@central.sun.com")
357c478bd9Sstevel@tonic-gate *
367c478bd9Sstevel@tonic-gate * This NFSv4 feature is far beyond anything NFSv2/v3 ever provided, as
377c478bd9Sstevel@tonic-gate * being able to describe a user with a unique string identifier provides
387c478bd9Sstevel@tonic-gate * a much more powerful and administrative friendly way of dealing with
397c478bd9Sstevel@tonic-gate * overlaps in the uid/gid number spaces. That notwithstanding, dealing
407c478bd9Sstevel@tonic-gate * with issues of correctly mapping user and group ownership in a cross-
417c478bd9Sstevel@tonic-gate * domain environment has proven a difficult problem to solve, since
427c478bd9Sstevel@tonic-gate * dealing with different permutations of client naming configurations
437c478bd9Sstevel@tonic-gate * (ie. NIS only, LDAP only, etc.) have bloated the problem. Thus, users
447c478bd9Sstevel@tonic-gate * utilizing clients and servers that have the 'domain' portion of the
457c478bd9Sstevel@tonic-gate * UTF8 attribute string configured differently than its peer server and
467c478bd9Sstevel@tonic-gate * client accordingly, will experience watching their files owned by the
477c478bd9Sstevel@tonic-gate * 'nobody' user and group. This is due to the fact that the 'domain's
487c478bd9Sstevel@tonic-gate * don't match and the nfsmapid daemon treats the attribute strings as
497c478bd9Sstevel@tonic-gate * unknown user(s) or group(s) (even though the actual uid/gid's may exist
507c478bd9Sstevel@tonic-gate * in the executing daemon's system). Please refer to PSARC/2004/154 for
517c478bd9Sstevel@tonic-gate * further background and motivation for these enhancements.
527c478bd9Sstevel@tonic-gate *
537c478bd9Sstevel@tonic-gate * The latest implementation of the nfsmapid daemon relies on a DNS TXT
547c478bd9Sstevel@tonic-gate * record. The behavior of nfsmapid is to first use the NFSMAPID_DOMAIN
557c478bd9Sstevel@tonic-gate * configuration option in /etc/default/nfs. If the option has not been
567c478bd9Sstevel@tonic-gate * set, then the nfsmapid daemon queries the configured DNS domain server
577c478bd9Sstevel@tonic-gate * for the _nfsv4idmapdomain TXT record. If the record exists, then the
587c478bd9Sstevel@tonic-gate * record's value is used as the 'domain' portion of the UTF8 attribute
597c478bd9Sstevel@tonic-gate * strings. If the TXT record has not been configured in the DNS server,
607c478bd9Sstevel@tonic-gate * then the daemon falls back to using the DNS domain name itself as the
617c478bd9Sstevel@tonic-gate * 'domain' portion of the attribute strings. Lastly, if the configured
627c478bd9Sstevel@tonic-gate * DNS server is unresponsive, the nfsmapid daemon falls back to using
637c478bd9Sstevel@tonic-gate * the DNS domain name as the 'domain' portion of the attribute strings,
647c478bd9Sstevel@tonic-gate * and fires up a query thread to keep contacting the DNS server until
657c478bd9Sstevel@tonic-gate * it responds with either a TXT record, or a lack thereof, in which
667c478bd9Sstevel@tonic-gate * case, nfsmapid just continues to utilize the DNS domain name.
677c478bd9Sstevel@tonic-gate */
688200fe25Srmesta #define __LIBMAPID_IMPL
698200fe25Srmesta #include <nfs/mapid.h>
70dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libshare.h>
71dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libscf.h>
72dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <limits.h>
73dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <rpcsvc/daemon_utils.h>
74dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h"
75dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States
768200fe25Srmesta #pragma init(_lib_init)
776d9307f9SVallish Vaidyeshwara #pragma fini(_lib_fini)
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate * DEBUG Only
817c478bd9Sstevel@tonic-gate * Decode any resolver errors and print out message to log
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate static int
resolv_error(void)847c478bd9Sstevel@tonic-gate resolv_error(void)
857c478bd9Sstevel@tonic-gate {
868200fe25Srmesta #ifndef DEBUG
878200fe25Srmesta
888200fe25Srmesta return (h_errno);
898200fe25Srmesta
908200fe25Srmesta #else /* DEBUG */
918200fe25Srmesta
927c478bd9Sstevel@tonic-gate static uint64_t msg_done[NS_ERRS] = {0};
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate switch (h_errno) {
958200fe25Srmesta case NETDB_INTERNAL:
968200fe25Srmesta syslog(LOG_ERR, EMSG_NETDB_INTERNAL, strerror(errno));
978200fe25Srmesta break;
987c478bd9Sstevel@tonic-gate
998200fe25Srmesta case HOST_NOT_FOUND:
1008200fe25Srmesta (void) rw_rdlock(&s_dns_impl_lock);
1018200fe25Srmesta msg_done[h_errno]++;
1028200fe25Srmesta if (!(msg_done[h_errno] % NFSMAPID_SLOG_RATE))
1038200fe25Srmesta syslog(LOG_ERR, EMSG_HOST_NOT_FOUND, s_dname);
1048200fe25Srmesta (void) rw_unlock(&s_dns_impl_lock);
1058200fe25Srmesta break;
1067c478bd9Sstevel@tonic-gate
1078200fe25Srmesta case TRY_AGAIN:
1088200fe25Srmesta /*
1098200fe25Srmesta * Nameserver is not responding.
1108200fe25Srmesta * Try again after a given timeout.
1118200fe25Srmesta */
1128200fe25Srmesta (void) rw_rdlock(&s_dns_impl_lock);
1138200fe25Srmesta msg_done[h_errno]++;
1148200fe25Srmesta if (!(msg_done[h_errno] % NFSMAPID_SLOG_RATE))
1158200fe25Srmesta syslog(LOG_ERR, EMSG_TRY_AGAIN, s_dname);
1168200fe25Srmesta (void) rw_unlock(&s_dns_impl_lock);
1178200fe25Srmesta break;
1187c478bd9Sstevel@tonic-gate
1198200fe25Srmesta case NO_RECOVERY:
1208200fe25Srmesta /*
1218200fe25Srmesta * This msg only really happens once, due
1228200fe25Srmesta * to s_dns_disabled flag (see below)
1238200fe25Srmesta */
1248200fe25Srmesta syslog(LOG_ERR, EMSG_NO_RECOVERY, hstrerror(h_errno));
1258200fe25Srmesta break;
1267c478bd9Sstevel@tonic-gate
1278200fe25Srmesta case NO_DATA:
1288200fe25Srmesta /*
1298200fe25Srmesta * No entries in the nameserver for
1308200fe25Srmesta * the specific record or record type.
1318200fe25Srmesta */
1328200fe25Srmesta (void) rw_rdlock(&s_dns_impl_lock);
1338200fe25Srmesta msg_done[h_errno]++;
1348200fe25Srmesta if (!(msg_done[h_errno] % NFSMAPID_SLOG_RATE))
1358200fe25Srmesta syslog(LOG_ERR, EMSG_NO_DATA, NFSMAPID_DNS_RR, s_dname);
1368200fe25Srmesta (void) rw_unlock(&s_dns_impl_lock);
1378200fe25Srmesta break;
1387c478bd9Sstevel@tonic-gate
1398200fe25Srmesta case NETDB_SUCCESS:
1408200fe25Srmesta default:
1418200fe25Srmesta break;
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate return (h_errno);
1448200fe25Srmesta
1458200fe25Srmesta #endif /* DEBUG */
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate * Reset the global state variables used for the TXT record.
1507c478bd9Sstevel@tonic-gate * Having these values reset to zero helps nfsmapid confirm
1517c478bd9Sstevel@tonic-gate * that a valid DNS TXT record was not found; in which case,
1527c478bd9Sstevel@tonic-gate * it would fall back to using the configured DNS domain name.
1537c478bd9Sstevel@tonic-gate *
1547c478bd9Sstevel@tonic-gate * If a valid DNS TXT record _was_ found, but subsequent contact
1557c478bd9Sstevel@tonic-gate * to the DNS server is somehow hindered, the previous DNS TXT
1567c478bd9Sstevel@tonic-gate * RR value continues to be used. Thus, in such instances, we
1577c478bd9Sstevel@tonic-gate * forego clearing the global config variables so nfsmapid can
1587c478bd9Sstevel@tonic-gate * continue to use a valid DNS TXT RR while contact to the DNS
1597c478bd9Sstevel@tonic-gate * server is reestablished.
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate static void
resolv_txt_reset(void)1627c478bd9Sstevel@tonic-gate resolv_txt_reset(void)
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate (void) rw_wrlock(&s_dns_impl_lock);
1657c478bd9Sstevel@tonic-gate bzero(s_txt_rr, sizeof (s_txt_rr));
1667c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
1677c478bd9Sstevel@tonic-gate
1688200fe25Srmesta (void) rw_wrlock(&s_dns_data_lock);
1697c478bd9Sstevel@tonic-gate if (!dns_txt_cached) {
1707c478bd9Sstevel@tonic-gate dns_txt_domain_len = 0;
1717c478bd9Sstevel@tonic-gate bzero(dns_txt_domain, DNAMEMAX);
1727c478bd9Sstevel@tonic-gate }
1738200fe25Srmesta (void) rw_unlock(&s_dns_data_lock);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate * Initialize resolver and populate &s_res struct
1787c478bd9Sstevel@tonic-gate *
1797c478bd9Sstevel@tonic-gate * DNS Domain is saved off sysdns_domain in case we
1807c478bd9Sstevel@tonic-gate * need to fall back to using the DNS domain name as
1817c478bd9Sstevel@tonic-gate * the v4 attribute string domain.
1827c478bd9Sstevel@tonic-gate */
1838200fe25Srmesta static int
resolv_init(void)1847c478bd9Sstevel@tonic-gate resolv_init(void)
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate size_t len;
1877c478bd9Sstevel@tonic-gate int n;
1887c478bd9Sstevel@tonic-gate struct __res_state res;
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate (void) mutex_lock(&s_res_lock);
1917c478bd9Sstevel@tonic-gate bzero(&s_res, sizeof (struct __res_state));
1927c478bd9Sstevel@tonic-gate n = h_errno = errno = 0;
1937c478bd9Sstevel@tonic-gate if ((n = res_ninit(&s_res)) < 0) {
1947c478bd9Sstevel@tonic-gate (void) mutex_unlock(&s_res_lock);
1957c478bd9Sstevel@tonic-gate (void) resolv_error();
1967c478bd9Sstevel@tonic-gate return (n);
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate res = s_res;
1997c478bd9Sstevel@tonic-gate (void) mutex_unlock(&s_res_lock);
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate len = strlen(res.defdname) + 1;
2027c478bd9Sstevel@tonic-gate (void) rw_wrlock(&s_dns_impl_lock);
2037c478bd9Sstevel@tonic-gate bzero(s_dname, sizeof (s_dname));
2047c478bd9Sstevel@tonic-gate (void) snprintf(s_dname, len, "%s", res.defdname);
2057c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
2067c478bd9Sstevel@tonic-gate
2078200fe25Srmesta (void) rw_wrlock(&s_dns_data_lock);
2087c478bd9Sstevel@tonic-gate (void) snprintf(sysdns_domain, len, "%s", res.defdname);
2098200fe25Srmesta (void) rw_unlock(&s_dns_data_lock);
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate return (0);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * Search criteria assumptions:
2167c478bd9Sstevel@tonic-gate *
2177c478bd9Sstevel@tonic-gate * The onus will fall on the sysadmins to correctly configure the TXT
2187c478bd9Sstevel@tonic-gate * record in the DNS domain where the box currently resides in order
2197c478bd9Sstevel@tonic-gate * for the record to be found. However, if they sysadmin chooses to
2207c478bd9Sstevel@tonic-gate * add the 'search' key to /etc/resolv.conf, then resolv_search()
2217c478bd9Sstevel@tonic-gate * _will_ traverse up the DNS tree as specified in the 'search' key.
2227c478bd9Sstevel@tonic-gate * Otherwise, we'll default the domain to the DNS domain itself.
2237c478bd9Sstevel@tonic-gate */
2247c478bd9Sstevel@tonic-gate static int
resolv_search(void)2257c478bd9Sstevel@tonic-gate resolv_search(void)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate int len;
2287c478bd9Sstevel@tonic-gate ans_t ans = {0};
2297c478bd9Sstevel@tonic-gate struct __res_state res;
2307c478bd9Sstevel@tonic-gate int type = T_TXT;
2317c478bd9Sstevel@tonic-gate int class = C_IN;
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate (void) mutex_lock(&s_res_lock);
2347c478bd9Sstevel@tonic-gate res = s_res;
2357c478bd9Sstevel@tonic-gate (void) mutex_unlock(&s_res_lock);
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate * Avoid holding locks across the res_nsearch() call to
2397c478bd9Sstevel@tonic-gate * prevent stalling threads during network partitions.
2407c478bd9Sstevel@tonic-gate */
2417c478bd9Sstevel@tonic-gate len = h_errno = errno = 0;
2427c478bd9Sstevel@tonic-gate if ((len = res_nsearch(&res, NFSMAPID_DNS_RR, class, type,
2437c478bd9Sstevel@tonic-gate ans.buf, sizeof (ans))) < 0)
2447c478bd9Sstevel@tonic-gate return (resolv_error());
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate (void) rw_wrlock(&s_dns_impl_lock);
2477c478bd9Sstevel@tonic-gate s_ans = ans;
2487c478bd9Sstevel@tonic-gate s_anslen = len;
2497c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate return (NETDB_SUCCESS);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate
254bfa62c28SVallish Vaidyeshwara /*
255bfa62c28SVallish Vaidyeshwara * Free all resolver state information stored in s_res
256bfa62c28SVallish Vaidyeshwara */
257bfa62c28SVallish Vaidyeshwara static void
resolv_destroy(void)258bfa62c28SVallish Vaidyeshwara resolv_destroy(void)
259bfa62c28SVallish Vaidyeshwara {
260bfa62c28SVallish Vaidyeshwara (void) mutex_lock(&s_res_lock);
261bfa62c28SVallish Vaidyeshwara res_ndestroy(&s_res);
262bfa62c28SVallish Vaidyeshwara (void) mutex_unlock(&s_res_lock);
263bfa62c28SVallish Vaidyeshwara }
264bfa62c28SVallish Vaidyeshwara
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate * Skip one DNS record
2677c478bd9Sstevel@tonic-gate */
2687c478bd9Sstevel@tonic-gate static uchar_t *
resolv_skip_rr(uchar_t * p,uchar_t * eom)2697c478bd9Sstevel@tonic-gate resolv_skip_rr(uchar_t *p, uchar_t *eom)
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate int t;
2727c478bd9Sstevel@tonic-gate int dlen;
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate * Skip compressed name
2767c478bd9Sstevel@tonic-gate */
2777c478bd9Sstevel@tonic-gate errno = 0;
2787c478bd9Sstevel@tonic-gate if ((t = dn_skipname(p, eom)) < 0) {
2798200fe25Srmesta #ifdef DEBUG
2808200fe25Srmesta syslog(LOG_ERR, "%s", strerror(errno));
2818200fe25Srmesta #endif
2827c478bd9Sstevel@tonic-gate return (NULL);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate * Advance pointer and make sure
2877c478bd9Sstevel@tonic-gate * we're still within the message
2887c478bd9Sstevel@tonic-gate */
2897c478bd9Sstevel@tonic-gate p += t;
2907c478bd9Sstevel@tonic-gate if ((p + RRFIXEDSZ) > eom)
2917c478bd9Sstevel@tonic-gate return (NULL);
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate * Now, just skip over the rr fields
2957c478bd9Sstevel@tonic-gate */
2967c478bd9Sstevel@tonic-gate p += INT16SZ; /* type */
2977c478bd9Sstevel@tonic-gate p += INT16SZ; /* class */
2987c478bd9Sstevel@tonic-gate p += INT32SZ; /* ttl */
2998200fe25Srmesta dlen = ns_get16(p);
3008200fe25Srmesta p += INT16SZ;
3017c478bd9Sstevel@tonic-gate p += dlen; /* dlen */
3027c478bd9Sstevel@tonic-gate if (p > eom)
3037c478bd9Sstevel@tonic-gate return (NULL);
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate return (p);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate * Process one TXT record.
3107c478bd9Sstevel@tonic-gate *
3117c478bd9Sstevel@tonic-gate * nfsmapid queries the DNS server for the specific _nfsv4idmapdomain
3127c478bd9Sstevel@tonic-gate * TXT record. Thus, if the TXT record exists, the answer section of
3137c478bd9Sstevel@tonic-gate * the DNS response carries the TXT record's value. Thus, we check that
3147c478bd9Sstevel@tonic-gate * the value is indeed a valid domain and set the modular s_txt_rr
3157c478bd9Sstevel@tonic-gate * global to the domain value.
3167c478bd9Sstevel@tonic-gate */
3177c478bd9Sstevel@tonic-gate static void
resolve_process_txt(uchar_t * p,int dlen)3187c478bd9Sstevel@tonic-gate resolve_process_txt(uchar_t *p, int dlen)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate char *rr_base = (char *)(p + 1);
3217c478bd9Sstevel@tonic-gate char *rr_end = (char *)(p + dlen);
3227c478bd9Sstevel@tonic-gate size_t len = rr_end - rr_base;
3238200fe25Srmesta #ifdef DEBUG
3247c478bd9Sstevel@tonic-gate static uint64_t msg_done = 0;
3258200fe25Srmesta #endif
3267c478bd9Sstevel@tonic-gate char tmp_txt_rr[DNAMEMAX];
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate if (len >= DNAMEMAX)
3297c478bd9Sstevel@tonic-gate return; /* process next TXT RR */
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate * make sure we have a clean buf since
3337c478bd9Sstevel@tonic-gate * we may've processed several TXT rr's
3347c478bd9Sstevel@tonic-gate */
3357c478bd9Sstevel@tonic-gate (void) rw_wrlock(&s_dns_impl_lock);
3367c478bd9Sstevel@tonic-gate bzero(s_txt_rr, sizeof (s_txt_rr));
3377c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate (void) strncpy(tmp_txt_rr, rr_base, len);
3407c478bd9Sstevel@tonic-gate tmp_txt_rr[len] = '\0';
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate * If there is a record and it's a valid domain, we're done.
3447c478bd9Sstevel@tonic-gate */
3458200fe25Srmesta if (rr_base[0] != '\0' && mapid_stdchk_domain(tmp_txt_rr) > 0) {
3467c478bd9Sstevel@tonic-gate (void) rw_wrlock(&s_dns_impl_lock);
3477c478bd9Sstevel@tonic-gate (void) strncpy(s_txt_rr, rr_base, len);
3487c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
3498200fe25Srmesta #ifdef DEBUG
3508200fe25Srmesta syslog(LOG_ERR, "TXT (Rec):\t%s", s_txt_rr);
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate } else if (!(msg_done++ % NFSMAPID_SLOG_RATE)) {
3537c478bd9Sstevel@tonic-gate /*
3547c478bd9Sstevel@tonic-gate * Otherwise, log the error
3557c478bd9Sstevel@tonic-gate */
3567c478bd9Sstevel@tonic-gate (void) rw_rdlock(&s_dns_impl_lock);
3578200fe25Srmesta syslog(LOG_ERR, EMSG_DNS_RR_INVAL, NFSMAPID_DNS_RR, s_dname);
3587c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
3598200fe25Srmesta #endif
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate * Decode any answer received from the DNS server. This interface is
3657c478bd9Sstevel@tonic-gate * capable of much more than just decoding TXT records. We maintain
3667c478bd9Sstevel@tonic-gate * focus on TXT rr's for now, but this will probably change once we
3677c478bd9Sstevel@tonic-gate * get the IETF approved application specific DNS RR.
3687c478bd9Sstevel@tonic-gate *
3697c478bd9Sstevel@tonic-gate * Here's an example of the TXT record we're decoding (as would appear
3707c478bd9Sstevel@tonic-gate * in the DNS zone file):
3717c478bd9Sstevel@tonic-gate *
3727c478bd9Sstevel@tonic-gate * _nfsv4idmapdomain IN TXT "sun.com"
3737c478bd9Sstevel@tonic-gate *
3747c478bd9Sstevel@tonic-gate * Once the IETF application specific DNS RR is granted, we should only
3757c478bd9Sstevel@tonic-gate * be changing the record flavor, but all should pretty much stay the
3767c478bd9Sstevel@tonic-gate * same.
3777c478bd9Sstevel@tonic-gate */
3787c478bd9Sstevel@tonic-gate static void
resolv_decode(void)3797c478bd9Sstevel@tonic-gate resolv_decode(void)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate uchar_t *buf;
3827c478bd9Sstevel@tonic-gate HEADER *hp;
3837c478bd9Sstevel@tonic-gate uchar_t name[DNAMEMAX];
3847c478bd9Sstevel@tonic-gate uchar_t *eom;
3857c478bd9Sstevel@tonic-gate uchar_t *p;
3867c478bd9Sstevel@tonic-gate int n;
3877c478bd9Sstevel@tonic-gate uint_t qd_cnt;
3887c478bd9Sstevel@tonic-gate uint_t an_cnt;
3897c478bd9Sstevel@tonic-gate uint_t ns_cnt;
3907c478bd9Sstevel@tonic-gate uint_t ar_cnt;
3917c478bd9Sstevel@tonic-gate uint_t cnt;
3927c478bd9Sstevel@tonic-gate uint_t type;
3937c478bd9Sstevel@tonic-gate int dlen;
3947c478bd9Sstevel@tonic-gate ans_t answer = {0};
3957c478bd9Sstevel@tonic-gate int answer_len = 0;
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate * Check the HEADER for any signs of errors
3997c478bd9Sstevel@tonic-gate * and extract the answer counts for later.
4007c478bd9Sstevel@tonic-gate */
4017c478bd9Sstevel@tonic-gate (void) rw_rdlock(&s_dns_impl_lock);
4027c478bd9Sstevel@tonic-gate answer = s_ans;
4037c478bd9Sstevel@tonic-gate answer_len = s_anslen;
4047c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate buf = (uchar_t *)&answer.buf;
4077c478bd9Sstevel@tonic-gate hp = (HEADER *)&answer.hdr;
4087c478bd9Sstevel@tonic-gate eom = (uchar_t *)(buf + answer_len);
4097c478bd9Sstevel@tonic-gate if (hp->rcode != NOERROR) {
4108200fe25Srmesta #ifdef DEBUG
4118200fe25Srmesta syslog(LOG_ERR, "errno: %s", strerror(errno));
4128200fe25Srmesta syslog(LOG_ERR, "h_errno: %s", hstrerror(h_errno));
4138200fe25Srmesta #endif
4147c478bd9Sstevel@tonic-gate return;
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate qd_cnt = ntohs(hp->qdcount);
4177c478bd9Sstevel@tonic-gate an_cnt = ntohs(hp->ancount);
4187c478bd9Sstevel@tonic-gate ns_cnt = ntohs(hp->nscount);
4197c478bd9Sstevel@tonic-gate ar_cnt = ntohs(hp->arcount);
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate * skip query entries
4237c478bd9Sstevel@tonic-gate */
4247c478bd9Sstevel@tonic-gate p = (uchar_t *)(buf + HFIXEDSZ);
4257c478bd9Sstevel@tonic-gate errno = 0;
4267c478bd9Sstevel@tonic-gate while (qd_cnt-- > 0) {
4277c478bd9Sstevel@tonic-gate n = dn_skipname(p, eom);
4287c478bd9Sstevel@tonic-gate if (n < 0) {
4298200fe25Srmesta #ifdef DEBUG
4308200fe25Srmesta syslog(LOG_ERR, "%s", strerror(errno));
4318200fe25Srmesta #endif
4327c478bd9Sstevel@tonic-gate return;
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate p += n;
4357c478bd9Sstevel@tonic-gate p += INT16SZ; /* type */
4367c478bd9Sstevel@tonic-gate p += INT16SZ; /* class */
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate #ifdef DEBUG
4407c478bd9Sstevel@tonic-gate /*
4417c478bd9Sstevel@tonic-gate * If debugging... print query only once.
4427c478bd9Sstevel@tonic-gate * NOTE: Don't advance pointer... this is done
4437c478bd9Sstevel@tonic-gate * in while() loop on a per record basis !
4447c478bd9Sstevel@tonic-gate */
4457c478bd9Sstevel@tonic-gate n = h_errno = errno = 0;
4467c478bd9Sstevel@tonic-gate n = dn_expand(buf, eom, p, (char *)name, sizeof (name));
4477c478bd9Sstevel@tonic-gate if (n < 0) {
4487c478bd9Sstevel@tonic-gate (void) resolv_error();
4497c478bd9Sstevel@tonic-gate return;
4507c478bd9Sstevel@tonic-gate }
4518200fe25Srmesta syslog(LOG_ERR, "Query:\t\t%-30s", name);
4527c478bd9Sstevel@tonic-gate #endif
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate /*
4557c478bd9Sstevel@tonic-gate * Process actual answer(s).
4567c478bd9Sstevel@tonic-gate */
4577c478bd9Sstevel@tonic-gate cnt = an_cnt;
4587c478bd9Sstevel@tonic-gate while (cnt-- > 0 && p < eom) {
4597c478bd9Sstevel@tonic-gate /* skip the name field */
4607c478bd9Sstevel@tonic-gate n = dn_expand(buf, eom, p, (char *)name, sizeof (name));
4617c478bd9Sstevel@tonic-gate if (n < 0) {
4627c478bd9Sstevel@tonic-gate (void) resolv_error();
4637c478bd9Sstevel@tonic-gate return;
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate p += n;
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate if ((p + 3 * INT16SZ + INT32SZ) > eom)
4687c478bd9Sstevel@tonic-gate return;
4697c478bd9Sstevel@tonic-gate
4708200fe25Srmesta type = ns_get16(p);
4718200fe25Srmesta p += INT16SZ;
4728200fe25Srmesta p += INT16SZ + INT32SZ; /* skip class & ttl */
4738200fe25Srmesta dlen = ns_get16(p);
4748200fe25Srmesta p += INT16SZ;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate if ((p + dlen) > eom)
4777c478bd9Sstevel@tonic-gate return;
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate switch (type) {
4807c478bd9Sstevel@tonic-gate case T_TXT:
4817c478bd9Sstevel@tonic-gate resolve_process_txt(p, dlen);
4827c478bd9Sstevel@tonic-gate break;
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate default:
4857c478bd9Sstevel@tonic-gate /*
4867c478bd9Sstevel@tonic-gate * Advance to next answer record for any
4877c478bd9Sstevel@tonic-gate * other record types. Again, this will
4887c478bd9Sstevel@tonic-gate * probably change (see block comment).
4897c478bd9Sstevel@tonic-gate */
4907c478bd9Sstevel@tonic-gate p += dlen;
4917c478bd9Sstevel@tonic-gate break;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate /*
4967c478bd9Sstevel@tonic-gate * Skip name server and additional records for now.
4977c478bd9Sstevel@tonic-gate */
4987c478bd9Sstevel@tonic-gate cnt = ns_cnt + ar_cnt;
4997c478bd9Sstevel@tonic-gate if (cnt > 0) {
5007c478bd9Sstevel@tonic-gate while (--cnt != 0 && p < eom) {
5017c478bd9Sstevel@tonic-gate p = resolv_skip_rr(p, eom);
5027c478bd9Sstevel@tonic-gate if (p == NULL)
5037c478bd9Sstevel@tonic-gate return;
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate * If a valid TXT record entry exists, s_txt_rr contains the domain
5107c478bd9Sstevel@tonic-gate * value (as set in resolv_process_txt) and we extract the value into
5117c478bd9Sstevel@tonic-gate * dns_txt_domain (the exported global). If there was _no_ valid TXT
5127c478bd9Sstevel@tonic-gate * entry, we simply return and check_domain() will default to the
5137c478bd9Sstevel@tonic-gate * DNS domain since we did resolv_txt_reset() first.
5147c478bd9Sstevel@tonic-gate */
5157c478bd9Sstevel@tonic-gate static void
resolv_get_txt_data()5167c478bd9Sstevel@tonic-gate resolv_get_txt_data()
5177c478bd9Sstevel@tonic-gate {
5187c478bd9Sstevel@tonic-gate (void) rw_rdlock(&s_dns_impl_lock);
5197c478bd9Sstevel@tonic-gate if (s_txt_rr[0] != '\0') {
5208200fe25Srmesta (void) rw_wrlock(&s_dns_data_lock);
5217c478bd9Sstevel@tonic-gate (void) snprintf(dns_txt_domain, strlen(s_txt_rr) + 1, "%s",
522bfa62c28SVallish Vaidyeshwara s_txt_rr);
5237c478bd9Sstevel@tonic-gate dns_txt_domain_len = strlen(dns_txt_domain);
5247c478bd9Sstevel@tonic-gate dns_txt_cached = 1;
5258200fe25Srmesta (void) rw_unlock(&s_dns_data_lock);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate
5308200fe25Srmesta static void
domain_sync(cb_t * argp,char * dname)5318200fe25Srmesta domain_sync(cb_t *argp, char *dname)
5328200fe25Srmesta {
5338200fe25Srmesta int dlen = 0;
5348200fe25Srmesta void *(*fcn)(void *) = NULL;
5358200fe25Srmesta int sighup = 0;
5368200fe25Srmesta int domchg = 0;
5378200fe25Srmesta
5388200fe25Srmesta /*
5398200fe25Srmesta * Make sure values passed are sane and initialize accordingly.
5408200fe25Srmesta */
5418200fe25Srmesta if (dname != NULL)
5428200fe25Srmesta dlen = strlen(dname);
5438200fe25Srmesta if (argp) {
5448200fe25Srmesta if (argp->fcn)
5458200fe25Srmesta fcn = argp->fcn;
5468200fe25Srmesta if (argp->signal)
5478200fe25Srmesta sighup = argp->signal;
5488200fe25Srmesta }
5498200fe25Srmesta
5508200fe25Srmesta /*
5518200fe25Srmesta * Update the library's mapid_domain variable if 'dname' is different.
5528200fe25Srmesta */
5538200fe25Srmesta if (dlen != 0 && strncasecmp(dname, mapid_domain, NS_MAXCDNAME)) {
5548200fe25Srmesta (void) rw_wrlock(&mapid_domain_lock);
5558200fe25Srmesta (void) strncpy(mapid_domain, dname, NS_MAXCDNAME);
5568200fe25Srmesta mapid_domain_len = dlen;
5578200fe25Srmesta (void) rw_unlock(&mapid_domain_lock);
5588200fe25Srmesta domchg++;
5598200fe25Srmesta }
5608200fe25Srmesta
5618200fe25Srmesta /*
5628200fe25Srmesta * If the caller gave us a valid callback routine, we
5638200fe25Srmesta * instantiate it to announce the domain change, but
5648200fe25Srmesta * only if either the domain changed _or_ the caller
5658200fe25Srmesta * was issued a SIGHUP.
5668200fe25Srmesta */
5678200fe25Srmesta if (fcn != NULL && (sighup || domchg))
5688200fe25Srmesta (void) fcn((void *)mapid_domain);
5698200fe25Srmesta }
5708200fe25Srmesta
5717c478bd9Sstevel@tonic-gate /*
5727c478bd9Sstevel@tonic-gate * Thread to keep pinging DNS server for TXT record if nfsmapid's
5737c478bd9Sstevel@tonic-gate * initial attempt at contact with server failed. We could potentially
5747c478bd9Sstevel@tonic-gate * have a substantial number of NFSv4 clients and having all of them
5757c478bd9Sstevel@tonic-gate * hammering on an already unresponsive DNS server would not help
5767c478bd9Sstevel@tonic-gate * things. So, we limit the number of live query threads to at most
5777c478bd9Sstevel@tonic-gate * 1 at any one time to keep things from getting out of hand.
5787c478bd9Sstevel@tonic-gate */
5797c478bd9Sstevel@tonic-gate /* ARGSUSED */
5808200fe25Srmesta static void *
resolv_query_thread(void * arg)5817c478bd9Sstevel@tonic-gate resolv_query_thread(void *arg)
5827c478bd9Sstevel@tonic-gate {
5838200fe25Srmesta unsigned int nap_time;
5848200fe25Srmesta
5858200fe25Srmesta #ifdef DEBUG
5867c478bd9Sstevel@tonic-gate char *whoami = "query_thread";
5877c478bd9Sstevel@tonic-gate
5888200fe25Srmesta syslog(LOG_ERR, "%s active !", whoami);
5898200fe25Srmesta #endif
5907c478bd9Sstevel@tonic-gate (void) rw_rdlock(&s_dns_impl_lock);
5917c478bd9Sstevel@tonic-gate nap_time = s_dns_tout;
5927c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate for (;;) {
5957c478bd9Sstevel@tonic-gate (void) sleep(nap_time);
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate resolv_txt_reset();
5986d9307f9SVallish Vaidyeshwara if (resolv_init() < 0) {
5996d9307f9SVallish Vaidyeshwara /*
6006d9307f9SVallish Vaidyeshwara * Failed to initialize resolver. Do not
6016d9307f9SVallish Vaidyeshwara * query DNS server.
6026d9307f9SVallish Vaidyeshwara */
6036d9307f9SVallish Vaidyeshwara goto thr_reset;
6046d9307f9SVallish Vaidyeshwara }
6057c478bd9Sstevel@tonic-gate switch (resolv_search()) {
6068200fe25Srmesta case NETDB_SUCCESS:
6078200fe25Srmesta resolv_decode();
6088200fe25Srmesta resolv_get_txt_data();
6097c478bd9Sstevel@tonic-gate
6108200fe25Srmesta /*
6118200fe25Srmesta * This is a bit different than what we
6128200fe25Srmesta * do in get_dns_txt_domain(), where we
6138200fe25Srmesta * simply return and let the caller
6148200fe25Srmesta * access dns_txt_domain directly.
6158200fe25Srmesta *
6168200fe25Srmesta * Here we invoke the callback routine
6178200fe25Srmesta * provided by the caller to the
6188200fe25Srmesta * mapid_reeval_domain() interface via
6198200fe25Srmesta * the cb_t's fcn param.
6208200fe25Srmesta */
6218200fe25Srmesta domain_sync((cb_t *)arg, dns_txt_domain);
6228200fe25Srmesta goto thr_okay;
6237c478bd9Sstevel@tonic-gate
6248200fe25Srmesta case NO_DATA:
6258200fe25Srmesta /*
6268200fe25Srmesta * DNS is up now, but does not have
6278200fe25Srmesta * the NFSV4IDMAPDOMAIN TXT record.
6288200fe25Srmesta */
6298200fe25Srmesta #ifdef DEBUG
6308200fe25Srmesta syslog(LOG_ERR, "%s: DNS has no TXT Record", whoami);
6318200fe25Srmesta #endif
6328200fe25Srmesta goto thr_reset;
6337c478bd9Sstevel@tonic-gate
6348200fe25Srmesta case NO_RECOVERY:
6358200fe25Srmesta /*
6368200fe25Srmesta * Non-Recoverable error occurred. No sense
6378200fe25Srmesta * in keep pinging the DNS server at this
6388200fe25Srmesta * point, so we disable any further contact.
6398200fe25Srmesta */
6408200fe25Srmesta #ifdef DEBUG
6418200fe25Srmesta syslog(LOG_ERR, EMSG_DNS_DISABLE, whoami);
6428200fe25Srmesta #endif
6438200fe25Srmesta (void) rw_wrlock(&s_dns_impl_lock);
6448200fe25Srmesta s_dns_disabled = TRUE;
6458200fe25Srmesta (void) rw_unlock(&s_dns_impl_lock);
6468200fe25Srmesta goto thr_reset;
6477c478bd9Sstevel@tonic-gate
6488200fe25Srmesta case HOST_NOT_FOUND:
6498200fe25Srmesta /*
6508200fe25Srmesta * Authoritative NS not responding...
6518200fe25Srmesta * keep trying for non-authoritative reply
6528200fe25Srmesta */
6538200fe25Srmesta /*FALLTHROUGH*/
6547c478bd9Sstevel@tonic-gate
6558200fe25Srmesta case TRY_AGAIN:
6568200fe25Srmesta /* keep trying */
6578200fe25Srmesta #ifdef DEBUG
6588200fe25Srmesta syslog(LOG_ERR, "%s: retrying...", whoami);
6598200fe25Srmesta #endif
6608200fe25Srmesta break;
6618200fe25Srmesta
6628200fe25Srmesta case NETDB_INTERNAL:
6638200fe25Srmesta default:
6648200fe25Srmesta #ifdef DEBUG
6658200fe25Srmesta syslog(LOG_ERR, "%s: Internal resolver error: %s",
6668200fe25Srmesta whoami, strerror(errno));
6678200fe25Srmesta #endif
6688200fe25Srmesta goto thr_reset;
6697c478bd9Sstevel@tonic-gate }
670bfa62c28SVallish Vaidyeshwara
671bfa62c28SVallish Vaidyeshwara resolv_destroy();
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate thr_reset:
6748200fe25Srmesta (void) rw_wrlock(&s_dns_data_lock);
6757c478bd9Sstevel@tonic-gate dns_txt_cached = 0;
6768200fe25Srmesta (void) rw_unlock(&s_dns_data_lock);
6777c478bd9Sstevel@tonic-gate resolv_txt_reset();
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate thr_okay:
680bfa62c28SVallish Vaidyeshwara resolv_destroy();
6817c478bd9Sstevel@tonic-gate /* mark thread as done */
6827c478bd9Sstevel@tonic-gate (void) rw_wrlock(&s_dns_impl_lock);
6837c478bd9Sstevel@tonic-gate s_dns_qthr_created = FALSE;
6847c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate (void) thr_exit(NULL);
6877c478bd9Sstevel@tonic-gate /*NOTREACHED*/
6887c478bd9Sstevel@tonic-gate return (NULL);
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate /*
6927c478bd9Sstevel@tonic-gate * nfsmapid's interface into the resolver for getting the TXT record.
6937c478bd9Sstevel@tonic-gate *
6947c478bd9Sstevel@tonic-gate * Key concepts:
6957c478bd9Sstevel@tonic-gate *
6967c478bd9Sstevel@tonic-gate * o If the DNS server is available and the TXT record is found, we
6977c478bd9Sstevel@tonic-gate * simply decode the output and fill the exported dns_txt_domain
6987c478bd9Sstevel@tonic-gate * global, so our caller can configure the daemon appropriately.
6997c478bd9Sstevel@tonic-gate *
7007c478bd9Sstevel@tonic-gate * o If the TXT record is not found, then having done resolv_txt_reset()
7017c478bd9Sstevel@tonic-gate * first will allow our caller to recognize that the exported globals
7027c478bd9Sstevel@tonic-gate * are empty and thus configure nfsmapid to use the default DNS domain.
7037c478bd9Sstevel@tonic-gate *
7047c478bd9Sstevel@tonic-gate * o Having no /etc/resolv.conf file is pretty much a show stopper, since
7057c478bd9Sstevel@tonic-gate * there is no name server address information. We return since we've
7067c478bd9Sstevel@tonic-gate * already have reset the TXT global state.
7077c478bd9Sstevel@tonic-gate *
7087c478bd9Sstevel@tonic-gate * o If a previous call to the DNS server resulted in an unrecoverable
7097c478bd9Sstevel@tonic-gate * error, then we disable further contact to the DNS server and return.
7107c478bd9Sstevel@tonic-gate * Having the TXT global state already reset guarantees that our caller
7117c478bd9Sstevel@tonic-gate * will fall back to the right configuration.
7127c478bd9Sstevel@tonic-gate *
7137c478bd9Sstevel@tonic-gate * o Query thread creation is throttled by s_dns_qthr_created. We mitigate
7147c478bd9Sstevel@tonic-gate * the problem of an already unresponsive DNS server by allowing at most
7157c478bd9Sstevel@tonic-gate * 1 outstanding query thread since we could potentially have a substantial
7167c478bd9Sstevel@tonic-gate * amount of clients hammering on the same DNS server attempting to get
7177c478bd9Sstevel@tonic-gate * the TXT record.
7187c478bd9Sstevel@tonic-gate */
7198200fe25Srmesta static void
get_dns_txt_domain(cb_t * argp)7208200fe25Srmesta get_dns_txt_domain(cb_t *argp)
7217c478bd9Sstevel@tonic-gate {
7227c478bd9Sstevel@tonic-gate int err;
7238200fe25Srmesta #ifdef DEBUG
7247c478bd9Sstevel@tonic-gate static uint64_t msg_done = 0;
7257c478bd9Sstevel@tonic-gate char *whoami = "get_dns_txt_domain";
7267c478bd9Sstevel@tonic-gate #endif
7277c478bd9Sstevel@tonic-gate long thr_flags = THR_DETACHED;
7287c478bd9Sstevel@tonic-gate struct stat st;
7297c478bd9Sstevel@tonic-gate
7307c478bd9Sstevel@tonic-gate /*
7317c478bd9Sstevel@tonic-gate * We reset TXT variables first in case /etc/resolv.conf
7327c478bd9Sstevel@tonic-gate * is missing or we've had unrecoverable resolver errors,
7337c478bd9Sstevel@tonic-gate * we'll default to get_dns_domain(). If a previous DNS
7347c478bd9Sstevel@tonic-gate * TXT RR was found, don't clear it until we're certain
7357c478bd9Sstevel@tonic-gate * that contact can be made to the DNS server (see block
7367c478bd9Sstevel@tonic-gate * comment atop resolv_txt_reset). If we're responding to
7377c478bd9Sstevel@tonic-gate * a SIGHUP signal, force a reset of the cached copy.
7387c478bd9Sstevel@tonic-gate */
7398200fe25Srmesta if (argp && argp->signal) {
7408200fe25Srmesta (void) rw_wrlock(&s_dns_data_lock);
7417c478bd9Sstevel@tonic-gate dns_txt_cached = 0;
7428200fe25Srmesta (void) rw_unlock(&s_dns_data_lock);
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate resolv_txt_reset();
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate errno = 0;
7477c478bd9Sstevel@tonic-gate if (stat(_PATH_RESCONF, &st) < 0 && errno == ENOENT) {
7487c478bd9Sstevel@tonic-gate /*
7497c478bd9Sstevel@tonic-gate * If /etc/resolv.conf is not there, then we'll
750*bbf21555SRichard Lowe * get the domain from domainname(8). No real
7517c478bd9Sstevel@tonic-gate * reason to query DNS or fire a thread since we
7527c478bd9Sstevel@tonic-gate * have no nameserver addresses.
7537c478bd9Sstevel@tonic-gate */
754bfa62c28SVallish Vaidyeshwara (void) rw_wrlock(&s_dns_data_lock);
755bfa62c28SVallish Vaidyeshwara dns_txt_cached = 0;
756bfa62c28SVallish Vaidyeshwara (void) rw_unlock(&s_dns_data_lock);
757bfa62c28SVallish Vaidyeshwara resolv_txt_reset();
758bfa62c28SVallish Vaidyeshwara return;
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate (void) rw_rdlock(&s_dns_impl_lock);
7627c478bd9Sstevel@tonic-gate if (s_dns_disabled) {
7637c478bd9Sstevel@tonic-gate /*
7647c478bd9Sstevel@tonic-gate * If there were non-recoverable problems with DNS,
7657c478bd9Sstevel@tonic-gate * we have stopped querying DNS entirely. See
7667c478bd9Sstevel@tonic-gate * NO_RECOVERY clause below.
7677c478bd9Sstevel@tonic-gate */
7688200fe25Srmesta #ifdef DEBUG
7698200fe25Srmesta syslog(LOG_ERR, "%s: DNS queries disabled", whoami);
7708200fe25Srmesta #endif
7717c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
7727c478bd9Sstevel@tonic-gate return;
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
7757c478bd9Sstevel@tonic-gate
7766d9307f9SVallish Vaidyeshwara if (resolv_init() < 0) {
7776d9307f9SVallish Vaidyeshwara /*
7786d9307f9SVallish Vaidyeshwara * Failed to initialize resolver. Do not
7796d9307f9SVallish Vaidyeshwara * query DNS server.
7806d9307f9SVallish Vaidyeshwara */
7816d9307f9SVallish Vaidyeshwara (void) rw_wrlock(&s_dns_data_lock);
7826d9307f9SVallish Vaidyeshwara dns_txt_cached = 0;
7836d9307f9SVallish Vaidyeshwara (void) rw_unlock(&s_dns_data_lock);
7846d9307f9SVallish Vaidyeshwara resolv_txt_reset();
7856d9307f9SVallish Vaidyeshwara return;
7866d9307f9SVallish Vaidyeshwara }
7877c478bd9Sstevel@tonic-gate switch (resolv_search()) {
7888200fe25Srmesta case NETDB_SUCCESS:
7898200fe25Srmesta /*
7908200fe25Srmesta * If there _is_ a TXT record, we let
7918200fe25Srmesta * our caller set the global state.
7928200fe25Srmesta */
7938200fe25Srmesta resolv_decode();
7948200fe25Srmesta resolv_get_txt_data();
795bfa62c28SVallish Vaidyeshwara break;
7968200fe25Srmesta
7978200fe25Srmesta case TRY_AGAIN:
7988200fe25Srmesta if (argp == NULL || argp->fcn == NULL)
7997c478bd9Sstevel@tonic-gate /*
8008200fe25Srmesta * If no valid argument was passed or
8018200fe25Srmesta * callback defined, don't fire thread
8027c478bd9Sstevel@tonic-gate */
803bfa62c28SVallish Vaidyeshwara break;
8047c478bd9Sstevel@tonic-gate
8058200fe25Srmesta (void) rw_wrlock(&s_dns_impl_lock);
8068200fe25Srmesta if (s_dns_qthr_created) {
8077c478bd9Sstevel@tonic-gate /*
8088200fe25Srmesta * We may have lots of clients, so we don't
8098200fe25Srmesta * want to bog down the DNS server with tons
8108200fe25Srmesta * of requests... lest it becomes even more
8118200fe25Srmesta * unresponsive, so limit 1 thread to query
8128200fe25Srmesta * DNS at a time.
8137c478bd9Sstevel@tonic-gate */
8148200fe25Srmesta #ifdef DEBUG
8158200fe25Srmesta syslog(LOG_ERR, "%s: query thread already active",
8168200fe25Srmesta whoami);
8177c478bd9Sstevel@tonic-gate #endif
8187c478bd9Sstevel@tonic-gate (void) rw_unlock(&s_dns_impl_lock);
819bfa62c28SVallish Vaidyeshwara break;
8208200fe25Srmesta }
8217c478bd9Sstevel@tonic-gate
8228200fe25Srmesta /*
8238200fe25Srmesta * DNS did not respond ! Set timeout and kick off
8248200fe25Srmesta * thread to try op again after s_dns_tout seconds.
8258200fe25Srmesta * We've made sure that we don't have an already
8268200fe25Srmesta * running thread above.
8278200fe25Srmesta */
8288200fe25Srmesta s_dns_tout = NFSMAPID_DNS_TOUT_SECS;
8298200fe25Srmesta err = thr_create(NULL, 0, resolv_query_thread, (void *)argp,
8308200fe25Srmesta thr_flags, &s_dns_qthread);
8318200fe25Srmesta if (!err) {
8328200fe25Srmesta s_dns_qthr_created = TRUE;
8338200fe25Srmesta }
8348200fe25Srmesta #ifdef DEBUG
8358200fe25Srmesta else {
8368200fe25Srmesta msg_done++;
8378200fe25Srmesta if (!(msg_done % NFSMAPID_SLOG_RATE))
8388200fe25Srmesta syslog(LOG_ERR, EMSG_DNS_THREAD_ERROR);
8398200fe25Srmesta }
8408200fe25Srmesta #endif
8418200fe25Srmesta (void) rw_unlock(&s_dns_impl_lock);
842bfa62c28SVallish Vaidyeshwara break;
8437c478bd9Sstevel@tonic-gate
8448200fe25Srmesta case NO_RECOVERY:
8458200fe25Srmesta #ifdef DEBUG
8468200fe25Srmesta syslog(LOG_ERR, EMSG_DNS_DISABLE, whoami);
8478200fe25Srmesta #endif
8488200fe25Srmesta (void) rw_wrlock(&s_dns_impl_lock);
8498200fe25Srmesta s_dns_disabled = TRUE;
8508200fe25Srmesta (void) rw_unlock(&s_dns_impl_lock);
8518200fe25Srmesta
8528200fe25Srmesta /*FALLTHROUGH*/
8538200fe25Srmesta
8548200fe25Srmesta default:
8558200fe25Srmesta /*
8568200fe25Srmesta * For any other errors... DNS is responding, but
8578200fe25Srmesta * either it has no data, or some other problem is
8588200fe25Srmesta * occuring. At any rate, the TXT domain should not
8598200fe25Srmesta * be used, so we default to the DNS domain.
8608200fe25Srmesta */
861bfa62c28SVallish Vaidyeshwara (void) rw_wrlock(&s_dns_data_lock);
862bfa62c28SVallish Vaidyeshwara dns_txt_cached = 0;
863bfa62c28SVallish Vaidyeshwara (void) rw_unlock(&s_dns_data_lock);
864bfa62c28SVallish Vaidyeshwara resolv_txt_reset();
8658200fe25Srmesta break;
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate
868bfa62c28SVallish Vaidyeshwara resolv_destroy();
8697c478bd9Sstevel@tonic-gate }
8708200fe25Srmesta
8718200fe25Srmesta static int
get_mtime(const char * fname,timestruc_t * mtim)8728200fe25Srmesta get_mtime(const char *fname, timestruc_t *mtim)
8738200fe25Srmesta {
8748200fe25Srmesta struct stat st;
8758200fe25Srmesta int err;
8768200fe25Srmesta
8778200fe25Srmesta if ((err = stat(fname, &st)) != 0)
8788200fe25Srmesta return (err);
8798200fe25Srmesta
8808200fe25Srmesta *mtim = st.st_mtim;
8818200fe25Srmesta return (0);
8828200fe25Srmesta }
8838200fe25Srmesta
8848200fe25Srmesta
8858200fe25Srmesta /*
8868200fe25Srmesta * trim_wspace is a destructive interface; it is up to
8878200fe25Srmesta * the caller to save off an original copy if needed.
8888200fe25Srmesta */
8898200fe25Srmesta static char *
trim_wspace(char * dp)8908200fe25Srmesta trim_wspace(char *dp)
8918200fe25Srmesta {
8928200fe25Srmesta char *r;
8938200fe25Srmesta char *ndp;
8948200fe25Srmesta
8958200fe25Srmesta /*
8968200fe25Srmesta * Any empty domain is not valid
8978200fe25Srmesta */
8988200fe25Srmesta if (dp == NULL)
8998200fe25Srmesta return (NULL);
9008200fe25Srmesta
9018200fe25Srmesta /*
9028200fe25Srmesta * Skip leading blanks
9038200fe25Srmesta */
9048200fe25Srmesta for (ndp = dp; *ndp != '\0'; ndp++) {
9058200fe25Srmesta if (!isspace(*ndp))
9068200fe25Srmesta break;
9078200fe25Srmesta }
9088200fe25Srmesta
9098200fe25Srmesta /*
9108200fe25Srmesta * If we reached the end of the string w/o
9118200fe25Srmesta * finding a non-blank char, return error
9128200fe25Srmesta */
9138200fe25Srmesta if (*ndp == '\0')
9148200fe25Srmesta return (NULL);
9158200fe25Srmesta
9168200fe25Srmesta /*
9178200fe25Srmesta * Find next blank in string
9188200fe25Srmesta */
9198200fe25Srmesta for (r = ndp; *r != '\0'; r++) {
9208200fe25Srmesta if (isspace(*r))
9218200fe25Srmesta break;
9228200fe25Srmesta }
9238200fe25Srmesta
9248200fe25Srmesta /*
9258200fe25Srmesta * No more blanks found, we are done
9268200fe25Srmesta */
9278200fe25Srmesta if (*r == '\0')
9288200fe25Srmesta return (ndp);
9298200fe25Srmesta
9308200fe25Srmesta /*
9318200fe25Srmesta * Terminate string at blank
9328200fe25Srmesta */
9338200fe25Srmesta *r++ = '\0';
9348200fe25Srmesta
9358200fe25Srmesta /*
9368200fe25Srmesta * Skip any trailing spaces
9378200fe25Srmesta */
9388200fe25Srmesta while (*r != '\0') {
9398200fe25Srmesta /*
9408200fe25Srmesta * If a non-blank is found, it is an
9418200fe25Srmesta * illegal domain (embedded blanks).
9428200fe25Srmesta */
9438200fe25Srmesta if (!isspace(*r))
9448200fe25Srmesta return (NULL);
9458200fe25Srmesta r++;
9468200fe25Srmesta }
9478200fe25Srmesta return (ndp);
9488200fe25Srmesta }
9498200fe25Srmesta
9508200fe25Srmesta static void
get_nfs_domain(void)9518200fe25Srmesta get_nfs_domain(void)
9528200fe25Srmesta {
953dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char value[NS_MAXCDNAME];
954dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States int ret, bufsz = NS_MAXCDNAME;
9558200fe25Srmesta
9568200fe25Srmesta /*
957dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Get NFSMAPID_DOMAIN property value from SMF.
9588200fe25Srmesta */
959dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States bzero(value, NS_MAXCDNAME);
960dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = nfs_smf_get_prop("nfsmapid_domain", value, DEFAULT_INSTANCE,
961dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SCF_TYPE_ASTRING, NFSMAPID, &bufsz);
962f5f1a62eSToomas Soome if (ret == SA_OK && *value != '\0') {
963dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char *dp = NULL;
964dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #ifdef DEBUG
965dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char *whoami = "get_nfs_domain";
966dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char orig[NS_MAXCDNAME] = {0};
967dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States (void) strncpy(orig, value, NS_MAXCDNAME);
9688200fe25Srmesta #endif
9698200fe25Srmesta /*
9708200fe25Srmesta * NFSMAPID_DOMAIN was set, so it's time for validation. If
9718200fe25Srmesta * it's okay, then update NFS domain and return. If not,
9728200fe25Srmesta * bail (syslog in DEBUG). We make nfsmapid more a bit
9738200fe25Srmesta * more forgiving of trailing and leading white space.
9748200fe25Srmesta */
975dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if ((dp = trim_wspace(value)) != NULL) {
9768200fe25Srmesta if (mapid_stdchk_domain(dp) > 0) {
9778200fe25Srmesta nfs_domain_len = strlen(dp);
9788200fe25Srmesta (void) strncpy(nfs_domain, dp, NS_MAXCDNAME);
9798200fe25Srmesta nfs_domain[NS_MAXCDNAME] = '\0';
9808200fe25Srmesta return;
9818200fe25Srmesta }
9828200fe25Srmesta }
9838200fe25Srmesta #ifdef DEBUG
9848200fe25Srmesta if (orig[0] != '\0') {
9858200fe25Srmesta syslog(LOG_ERR, gettext("%s: Invalid domain name \"%s\""
986dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States " found in SMF."), whoami, orig);
9878200fe25Srmesta }
9888200fe25Srmesta #endif
9898200fe25Srmesta }
9908200fe25Srmesta /*
991dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * So the NFS SMF parameter nfsmapid_domain cannot be obtained or
992dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * there is an invalid nfsmapid_domain property value.
993dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Time to zap current NFS domain info.
9948200fe25Srmesta */
9958200fe25Srmesta ZAP_DOMAIN(nfs);
9968200fe25Srmesta }
9978200fe25Srmesta
9988200fe25Srmesta static void
get_dns_domain(void)9998200fe25Srmesta get_dns_domain(void)
10008200fe25Srmesta {
10018200fe25Srmesta timestruc_t ntime = {0};
10028200fe25Srmesta
10038200fe25Srmesta /*
10048200fe25Srmesta * If we can't get stats for the config file, then
10058200fe25Srmesta * zap the DNS domain info. If mtime hasn't changed,
10068200fe25Srmesta * then there's no work to do, so just return.
10078200fe25Srmesta */
10088200fe25Srmesta errno = 0;
10098200fe25Srmesta if (get_mtime(_PATH_RESCONF, &ntime) != 0) {
10108200fe25Srmesta switch (errno) {
10118200fe25Srmesta case ENOENT:
10128200fe25Srmesta /*
10138200fe25Srmesta * The resolver defaults to obtaining the
1014*bbf21555SRichard Lowe * domain off of the NIS domainname(8) if
10158200fe25Srmesta * /etc/resolv.conf does not exist, so we
10168200fe25Srmesta * move forward.
10178200fe25Srmesta */
10188200fe25Srmesta break;
10198200fe25Srmesta
10208200fe25Srmesta default:
10218200fe25Srmesta ZAP_DOMAIN(dns);
10228200fe25Srmesta return;
10238200fe25Srmesta }
10248200fe25Srmesta } else if (TIMESTRUC_EQ(ntime, dns_mtime))
10258200fe25Srmesta return;
10268200fe25Srmesta
10278200fe25Srmesta /*
10288200fe25Srmesta * Re-initialize resolver to zap DNS domain from previous
10298200fe25Srmesta * resolv_init() calls.
10308200fe25Srmesta */
10318200fe25Srmesta (void) resolv_init();
10328200fe25Srmesta
10338200fe25Srmesta /*
10348200fe25Srmesta * Update cached DNS domain. No need for validation since
10358200fe25Srmesta * domain comes from resolver. If resolver doesn't return the
10368200fe25Srmesta * domain, then zap the DNS domain. This shouldn't ever happen,
10378200fe25Srmesta * and if it does, the machine has bigger problems (so no need
10388200fe25Srmesta * to generate a message that says DNS appears to be broken).
10398200fe25Srmesta */
10408200fe25Srmesta (void) rw_rdlock(&s_dns_data_lock);
10418200fe25Srmesta if (sysdns_domain[0] != '\0') {
10428200fe25Srmesta (void) strncpy(dns_domain, sysdns_domain, NS_MAXCDNAME);
10438200fe25Srmesta dns_domain_len = strlen(sysdns_domain);
10448200fe25Srmesta (void) rw_unlock(&s_dns_data_lock);
10458200fe25Srmesta dns_mtime = ntime;
1046bfa62c28SVallish Vaidyeshwara resolv_destroy();
10478200fe25Srmesta return;
10488200fe25Srmesta }
10498200fe25Srmesta (void) rw_unlock(&s_dns_data_lock);
10508200fe25Srmesta
10518200fe25Srmesta ZAP_DOMAIN(dns);
1052bfa62c28SVallish Vaidyeshwara
1053bfa62c28SVallish Vaidyeshwara resolv_destroy();
1054bfa62c28SVallish Vaidyeshwara
10558200fe25Srmesta }
10568200fe25Srmesta
10578200fe25Srmesta /*
10588200fe25Srmesta * PSARC 2005/487 Contracted Sun Private Interface
10598200fe25Srmesta * mapid_stdchk_domain()
10608200fe25Srmesta * Changes must be reviewed by Solaris File Sharing
10618200fe25Srmesta * Changes must be communicated to contract-2005-487-01@sun.com
10628200fe25Srmesta *
10638200fe25Srmesta * Based on the recommendations from RFC1033 and RFC1035, check
10648200fe25Srmesta * if a given domain name string is valid. Return values are:
10658200fe25Srmesta *
10668200fe25Srmesta * 1 = valid domain name
10678200fe25Srmesta * 0 = invalid domain name (or invalid embedded character)
10688200fe25Srmesta * -1 = domain length > NS_MAXCDNAME
10698200fe25Srmesta */
10708200fe25Srmesta int
mapid_stdchk_domain(const char * ds)10718200fe25Srmesta mapid_stdchk_domain(const char *ds)
10728200fe25Srmesta {
10738200fe25Srmesta int i;
10748200fe25Srmesta size_t len;
10758200fe25Srmesta
10768200fe25Srmesta if (ds[0] == '\0')
10778200fe25Srmesta return (0);
10788200fe25Srmesta else
10798200fe25Srmesta len = strlen(ds) - 1;
10808200fe25Srmesta
10818200fe25Srmesta /*
10827bcac252Sevanl * 1st _AND_ last char _must_ be alphanumeric.
10837bcac252Sevanl * We check for other valid chars below.
10848200fe25Srmesta */
10857bcac252Sevanl if ((!isalpha(ds[0]) && !isdigit(ds[0])) ||
10867bcac252Sevanl (!isalpha(ds[len]) && !isdigit(ds[len])))
10878200fe25Srmesta return (0);
10888200fe25Srmesta
10898200fe25Srmesta for (i = 0; *ds && i <= NS_MAXCDNAME; i++, ds++) {
10908200fe25Srmesta if (!isalpha(*ds) && !isdigit(*ds) &&
10918200fe25Srmesta (*ds != '.') && (*ds != '-') && (*ds != '_'))
10928200fe25Srmesta return (0);
10938200fe25Srmesta }
10948200fe25Srmesta return (i == (NS_MAXCDNAME + 1) ? -1 : 1);
10958200fe25Srmesta }
10968200fe25Srmesta
10978200fe25Srmesta /*
10988200fe25Srmesta * PSARC 2005/487 Consolidation Private
10998200fe25Srmesta * mapid_reeval_domain()
11008200fe25Srmesta * Changes must be reviewed by Solaris File Sharing
11018200fe25Srmesta */
11028200fe25Srmesta void
mapid_reeval_domain(cb_t * arg)11038200fe25Srmesta mapid_reeval_domain(cb_t *arg)
11048200fe25Srmesta {
11058200fe25Srmesta char *domain = NULL;
11068200fe25Srmesta
11078200fe25Srmesta get_nfs_domain();
11088200fe25Srmesta if (nfs_domain_len != 0) {
11098200fe25Srmesta domain = nfs_domain;
11108200fe25Srmesta goto dsync;
11118200fe25Srmesta }
11128200fe25Srmesta
11138200fe25Srmesta get_dns_txt_domain(arg);
11148200fe25Srmesta if (dns_txt_domain_len != 0)
11158200fe25Srmesta domain = dns_txt_domain;
11168200fe25Srmesta else {
11178200fe25Srmesta /*
11188200fe25Srmesta * We're either here because:
11198200fe25Srmesta *
11208200fe25Srmesta * . NFSMAPID_DOMAIN was not set in /etc/default/nfs
11218200fe25Srmesta * . No suitable DNS TXT resource record exists
11228200fe25Srmesta * . DNS server is not responding to requests
11238200fe25Srmesta *
11248200fe25Srmesta * in either case, we want to default to using the
11258200fe25Srmesta * system configured DNS domain. If this fails, then
11268200fe25Srmesta * dns_domain will be empty and dns_domain_len will
11278200fe25Srmesta * be 0.
11288200fe25Srmesta */
11298200fe25Srmesta get_dns_domain();
11308200fe25Srmesta domain = dns_domain;
11318200fe25Srmesta }
11328200fe25Srmesta
11338200fe25Srmesta dsync:
11348200fe25Srmesta domain_sync(arg, domain);
11358200fe25Srmesta }
11368200fe25Srmesta
11378200fe25Srmesta /*
11388200fe25Srmesta * PSARC 2005/487 Consolidation Private
11398200fe25Srmesta * mapid_get_domain()
11408200fe25Srmesta * Changes must be reviewed by Solaris File Sharing
11418200fe25Srmesta *
11428200fe25Srmesta * The use of TSD in mapid_get_domain() diverges slightly from the typical
11438200fe25Srmesta * TSD use, since here, the benefit of doing TSD is mostly to allocate
11448200fe25Srmesta * a per-thread buffer that will be utilized by other up-calls to the
11458200fe25Srmesta * daemon.
11468200fe25Srmesta *
11478200fe25Srmesta * In doors, the thread used for the upcall never really exits, hence
11488200fe25Srmesta * the typical destructor function defined via thr_keycreate() will
11498200fe25Srmesta * never be called. Thus, we only use TSD to allocate the per-thread
11508200fe25Srmesta * buffer and fill it up w/the configured 'mapid_domain' on each call.
11518200fe25Srmesta * This still alleviates the problem of having the caller free any
11528200fe25Srmesta * malloc'd space.
11538200fe25Srmesta */
11548200fe25Srmesta char *
mapid_get_domain(void)11558200fe25Srmesta mapid_get_domain(void)
11568200fe25Srmesta {
11578200fe25Srmesta void *tsd = NULL;
11588200fe25Srmesta
11598200fe25Srmesta (void) thr_getspecific(s_thr_key, &tsd);
11608200fe25Srmesta if (tsd == NULL) {
11618200fe25Srmesta tsd = malloc(NS_MAXCDNAME+1);
11628200fe25Srmesta if (tsd != NULL) {
11638200fe25Srmesta (void) rw_rdlock(&mapid_domain_lock);
11648200fe25Srmesta (void) strncpy((char *)tsd, mapid_domain, NS_MAXCDNAME);
11658200fe25Srmesta (void) rw_unlock(&mapid_domain_lock);
11668200fe25Srmesta (void) thr_setspecific(s_thr_key, tsd);
11678200fe25Srmesta }
11688200fe25Srmesta } else {
11698200fe25Srmesta (void) rw_rdlock(&mapid_domain_lock);
11708200fe25Srmesta (void) strncpy((char *)tsd, mapid_domain, NS_MAXCDNAME);
11718200fe25Srmesta (void) rw_unlock(&mapid_domain_lock);
11728200fe25Srmesta }
11738200fe25Srmesta return ((char *)tsd);
11748200fe25Srmesta }
11758200fe25Srmesta
11768200fe25Srmesta /*
11778200fe25Srmesta * PSARC 2005/487 Contracted Sun Private Interface
11788200fe25Srmesta * mapid_derive_domain()
11798200fe25Srmesta * Changes must be reviewed by Solaris File Sharing
11808200fe25Srmesta * Changes must be communicated to contract-2005-487-01@sun.com
11818200fe25Srmesta *
11828200fe25Srmesta * This interface is called solely via sysidnfs4 iff no
11838200fe25Srmesta * NFSMAPID_DOMAIN was found. So, there is no ill effect
11848200fe25Srmesta * of having the reeval function call get_nfs_domain().
11858200fe25Srmesta */
11868200fe25Srmesta char *
mapid_derive_domain(void)11878200fe25Srmesta mapid_derive_domain(void)
11888200fe25Srmesta {
11898200fe25Srmesta cb_t cb = {0};
11908200fe25Srmesta
11918200fe25Srmesta _lib_init();
11928200fe25Srmesta mapid_reeval_domain(&cb);
11938200fe25Srmesta return (mapid_get_domain());
11948200fe25Srmesta }
11958200fe25Srmesta
11968200fe25Srmesta void
_lib_init(void)11978200fe25Srmesta _lib_init(void)
11988200fe25Srmesta {
11996d9307f9SVallish Vaidyeshwara (void) resolv_init(); /* May fail! */
12008200fe25Srmesta (void) rwlock_init(&mapid_domain_lock, USYNC_THREAD, NULL);
12018200fe25Srmesta (void) thr_keycreate(&s_thr_key, NULL);
12028200fe25Srmesta lib_init_done++;
1203bfa62c28SVallish Vaidyeshwara resolv_destroy();
12048200fe25Srmesta }
12056d9307f9SVallish Vaidyeshwara
12066d9307f9SVallish Vaidyeshwara void
_lib_fini(void)12076d9307f9SVallish Vaidyeshwara _lib_fini(void)
12086d9307f9SVallish Vaidyeshwara {
12096d9307f9SVallish Vaidyeshwara resolv_destroy();
12106d9307f9SVallish Vaidyeshwara }
1211