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
5004388ebScasper * Common Development and Distribution License (the "License").
6004388ebScasper * 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 */
2161961e0fSrobinson
227c478bd9Sstevel@tonic-gate /*
23*36e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * This module contains the subroutines used by the server to manipulate
307c478bd9Sstevel@tonic-gate * objects and names.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate #include "mt.h"
337c478bd9Sstevel@tonic-gate #include <pwd.h>
347c478bd9Sstevel@tonic-gate #include <grp.h>
357c478bd9Sstevel@tonic-gate #include <syslog.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <ctype.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <unistd.h>
417c478bd9Sstevel@tonic-gate #include <sys/time.h>
427c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
437c478bd9Sstevel@tonic-gate #include <netinet/in.h>
447c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> /* Must be ahead of rpcb_clnt.h */
457c478bd9Sstevel@tonic-gate #include <rpc/svc.h>
467c478bd9Sstevel@tonic-gate #include <tiuser.h>
477c478bd9Sstevel@tonic-gate #include <netconfig.h>
487c478bd9Sstevel@tonic-gate #include <netdir.h>
497c478bd9Sstevel@tonic-gate #include <rpc/rpcb_clnt.h>
507c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
517c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
527c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
537c478bd9Sstevel@tonic-gate #include "nis_clnt.h"
547c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
557c478bd9Sstevel@tonic-gate #include <nsswitch.h>
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate #define MAXIPRINT (11) /* max length of printed integer */
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate * send and receive buffer size used for clnt_tli_create if not specified.
607c478bd9Sstevel@tonic-gate * This is only used for "UDP" connection.
617c478bd9Sstevel@tonic-gate * This limit can be changed from the application if this value is too
627c478bd9Sstevel@tonic-gate * small for the application. To use the maximum value for the transport,
637c478bd9Sstevel@tonic-gate * set this value to 0.
647c478bd9Sstevel@tonic-gate */
657c478bd9Sstevel@tonic-gate int __nisipbufsize = 8192;
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate * Static function prototypes.
707c478bd9Sstevel@tonic-gate */
717c478bd9Sstevel@tonic-gate static struct local_names *__get_local_names(void);
727c478bd9Sstevel@tonic-gate static char *__map_addr(struct netconfig *, char *, rpcprog_t, rpcvers_t);
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate * nis_dir_cmp() -- the results can be read as:
767c478bd9Sstevel@tonic-gate * "Name 'n1' is a $result than name 'n2'"
777c478bd9Sstevel@tonic-gate */
787c478bd9Sstevel@tonic-gate name_pos
nis_dir_cmp(nis_name n1,nis_name n2)797c478bd9Sstevel@tonic-gate nis_dir_cmp(
807c478bd9Sstevel@tonic-gate nis_name n1,
817c478bd9Sstevel@tonic-gate nis_name n2) /* See if these are the same domain */
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate size_t l1, l2;
847c478bd9Sstevel@tonic-gate name_pos result;
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate if ((n1 == NULL) || (n2 == NULL))
877c478bd9Sstevel@tonic-gate return (BAD_NAME);
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate l1 = strlen(n1);
907c478bd9Sstevel@tonic-gate l2 = strlen(n2);
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate /* In this routine we're lenient and don't require a trailing '.' */
937c478bd9Sstevel@tonic-gate /* so we need to ignore it if it does appear. */
947c478bd9Sstevel@tonic-gate /* ==== That's what the previous version did so this one does */
957c478bd9Sstevel@tonic-gate /* too, but why? Is this inconsistent with rest of system? */
967c478bd9Sstevel@tonic-gate if (l1 != 0 && n1[l1 - 1] == '.') {
977c478bd9Sstevel@tonic-gate --l1;
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate if (l2 != 0 && n2[l2 - 1] == '.') {
1007c478bd9Sstevel@tonic-gate --l2;
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate if (l1 > l2) {
1047c478bd9Sstevel@tonic-gate result = LOWER_NAME;
1057c478bd9Sstevel@tonic-gate } else if (l1 == l2) {
1067c478bd9Sstevel@tonic-gate result = SAME_NAME;
1077c478bd9Sstevel@tonic-gate } else /* (l1 < l2); swap l1/l2 and n1/n2 */ {
1087c478bd9Sstevel@tonic-gate nis_name ntmp;
1097c478bd9Sstevel@tonic-gate size_t ltmp;
1107c478bd9Sstevel@tonic-gate ntmp = n1; n1 = n2; n2 = ntmp;
1117c478bd9Sstevel@tonic-gate ltmp = l1; l1 = l2; l2 = ltmp;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate result = HIGHER_NAME;
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate /* Now l1 >= l2 in all cases */
1177c478bd9Sstevel@tonic-gate if (l2 == 0) {
1187c478bd9Sstevel@tonic-gate /* Special case for n2 == "." or "" */
1197c478bd9Sstevel@tonic-gate return (result);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate if (l1 > l2) {
1227c478bd9Sstevel@tonic-gate n1 += l1 - l2;
1237c478bd9Sstevel@tonic-gate if (n1[-1] != '.') {
1247c478bd9Sstevel@tonic-gate return (NOT_SEQUENTIAL);
1257c478bd9Sstevel@tonic-gate }
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate if (strncasecmp(n1, n2, l2) == 0) {
1287c478bd9Sstevel@tonic-gate return (result);
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate return (NOT_SEQUENTIAL);
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate #define LN_BUFSIZE (size_t)1024
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate struct principal_list {
1367c478bd9Sstevel@tonic-gate uid_t uid;
1377c478bd9Sstevel@tonic-gate char principal[LN_BUFSIZE];
1387c478bd9Sstevel@tonic-gate struct principal_list *next;
1397c478bd9Sstevel@tonic-gate };
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate struct local_names {
1437c478bd9Sstevel@tonic-gate char domain[LN_BUFSIZE];
1447c478bd9Sstevel@tonic-gate char host[LN_BUFSIZE];
1457c478bd9Sstevel@tonic-gate char *rpcdomain;
1467c478bd9Sstevel@tonic-gate struct principal_list *principal_map;
1477c478bd9Sstevel@tonic-gate char group[LN_BUFSIZE];
1487c478bd9Sstevel@tonic-gate };
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate static mutex_t ln_lock = DEFAULTMUTEX; /* lock level 2 */
1517c478bd9Sstevel@tonic-gate static struct local_names *ln = NULL;
1527c478bd9Sstevel@tonic-gate static struct local_names *__get_local_names1();
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate static struct local_names *
__get_local_names(void)1557c478bd9Sstevel@tonic-gate __get_local_names(void)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate struct local_names *names;
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate sig_mutex_lock(&ln_lock);
1607c478bd9Sstevel@tonic-gate names = __get_local_names1();
1617c478bd9Sstevel@tonic-gate sig_mutex_unlock(&ln_lock);
1627c478bd9Sstevel@tonic-gate return (names);
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate static struct local_names *
__get_local_names1(void)1677c478bd9Sstevel@tonic-gate __get_local_names1(void)
1687c478bd9Sstevel@tonic-gate {
1697c478bd9Sstevel@tonic-gate char *t;
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate if (ln != NULL) {
1727c478bd9Sstevel@tonic-gate /* Second and subsequent calls go this way */
1737c478bd9Sstevel@tonic-gate return (ln);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate /* First call goes this way */
17661961e0fSrobinson ln = calloc(1, sizeof (*ln));
1777c478bd9Sstevel@tonic-gate if (ln == NULL) {
1787c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "__get_local_names: Out of heap.");
1797c478bd9Sstevel@tonic-gate return (NULL);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate ln->principal_map = NULL;
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate if (sysinfo(SI_SRPC_DOMAIN, ln->domain, LN_BUFSIZE) < 0)
1847c478bd9Sstevel@tonic-gate return (ln);
1857c478bd9Sstevel@tonic-gate /* If no dot exists, add one. */
1867c478bd9Sstevel@tonic-gate if (ln->domain[strlen(ln->domain)-1] != '.')
1877c478bd9Sstevel@tonic-gate (void) strcat(ln->domain, ".");
1887c478bd9Sstevel@tonic-gate if (sysinfo(SI_HOSTNAME, ln->host, LN_BUFSIZE) < 0)
1897c478bd9Sstevel@tonic-gate return (ln);
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate * Check for fully qualified hostname. If it's a fully qualified
1937c478bd9Sstevel@tonic-gate * hostname, strip off the domain part. We always use the local
1947c478bd9Sstevel@tonic-gate * domainname for the host principal name.
1957c478bd9Sstevel@tonic-gate */
1967c478bd9Sstevel@tonic-gate t = strchr(ln->host, '.');
1977c478bd9Sstevel@tonic-gate if (t)
1987c478bd9Sstevel@tonic-gate *t = 0;
1997c478bd9Sstevel@tonic-gate if (ln->domain[0] != '.')
2007c478bd9Sstevel@tonic-gate (void) strcat(ln->host, ".");
2017c478bd9Sstevel@tonic-gate ln->rpcdomain = strdup(ln->domain);
20261961e0fSrobinson (void) strcat(ln->host, ln->domain);
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate t = getenv("NIS_GROUP");
2057c478bd9Sstevel@tonic-gate if (t == NULL) {
2067c478bd9Sstevel@tonic-gate ln->group[0] = '\0';
2077c478bd9Sstevel@tonic-gate } else {
2087c478bd9Sstevel@tonic-gate size_t maxlen = LN_BUFSIZE-1; /* max chars to copy */
2097c478bd9Sstevel@tonic-gate char *temp; /* temp marker */
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate /*
2127c478bd9Sstevel@tonic-gate * Copy <= maximum characters from NIS_GROUP; strncpy()
2137c478bd9Sstevel@tonic-gate * doesn't terminate, so we do that manually. #1223323
2147c478bd9Sstevel@tonic-gate * Also check to see if it's "". If it's the null string,
2157c478bd9Sstevel@tonic-gate * we return because we don't want to add ".domain".
2167c478bd9Sstevel@tonic-gate */
2177c478bd9Sstevel@tonic-gate (void) strncpy(ln->group, t, maxlen);
2187c478bd9Sstevel@tonic-gate if (strcmp(ln->group, "") == 0) {
2197c478bd9Sstevel@tonic-gate return (ln);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate ln->group[maxlen] = '\0';
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate /* Is the group name somewhat fully-qualified? */
2247c478bd9Sstevel@tonic-gate temp = strrchr(ln->group, '.');
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /* If not, we need to add ".domain" to the group */
2277c478bd9Sstevel@tonic-gate if ((temp == NULL) || (temp[1] != '\0')) {
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate /* truncate to make room for ".domain" */
2307c478bd9Sstevel@tonic-gate ln->group[maxlen - (strlen(ln->domain)+1)] = '\0';
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate /* concat '.' if domain doesn't already have it */
2337c478bd9Sstevel@tonic-gate if (ln->domain[0] != '.') {
2347c478bd9Sstevel@tonic-gate (void) strcat(ln->group, ".");
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate (void) strcat(ln->group, ln->domain);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate return (ln);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate * nis_local_group()
2447c478bd9Sstevel@tonic-gate *
2457c478bd9Sstevel@tonic-gate * Return's the group name of the current user.
2467c478bd9Sstevel@tonic-gate */
2477c478bd9Sstevel@tonic-gate nis_name
nis_local_group(void)2487c478bd9Sstevel@tonic-gate nis_local_group(void)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate struct local_names *ln = __get_local_names();
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /* LOCK NOTE: Warning, after initialization, "ln" is expected */
2537c478bd9Sstevel@tonic-gate /* to stay constant, So no need to lock here. If this assumption */
2547c478bd9Sstevel@tonic-gate /* is changed, this code must be protected. */
2557c478bd9Sstevel@tonic-gate if (!ln)
2567c478bd9Sstevel@tonic-gate return (NULL);
2577c478bd9Sstevel@tonic-gate return (ln->group);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate /*
2617c478bd9Sstevel@tonic-gate * __nis_nextsep_of()
2627c478bd9Sstevel@tonic-gate *
2637c478bd9Sstevel@tonic-gate * This internal funtion will accept a pointer to a NIS name string and
2647c478bd9Sstevel@tonic-gate * return a pointer to the next separator occurring in it (it will point
2657c478bd9Sstevel@tonic-gate * just past the first label). It allows for labels to be "quoted" to
2667c478bd9Sstevel@tonic-gate * prevent the the dot character within them to be interpreted as a
2677c478bd9Sstevel@tonic-gate * separator, also the quote character itself can be quoted by using
2687c478bd9Sstevel@tonic-gate * it twice. If the the name contains only one label and no trailing
2697c478bd9Sstevel@tonic-gate * dot character, a pointer to the terminating NULL is returned.
2707c478bd9Sstevel@tonic-gate */
2717c478bd9Sstevel@tonic-gate nis_name
__nis_nextsep_of(char * s)2727c478bd9Sstevel@tonic-gate __nis_nextsep_of(char *s)
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate char *d;
275*36e852a1SRaja Andra int in_quotes = FALSE, quote_quote = FALSE;
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate if (!s)
2787c478bd9Sstevel@tonic-gate return (NULL);
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate for (d = s; (in_quotes && (*d != '\0')) ||
2817c478bd9Sstevel@tonic-gate (!in_quotes && (*d != '.') && (*d != '\0')); d++) {
2827c478bd9Sstevel@tonic-gate if (quote_quote && in_quotes && (*d != '"')) {
2837c478bd9Sstevel@tonic-gate quote_quote = FALSE;
2847c478bd9Sstevel@tonic-gate in_quotes = FALSE;
2857c478bd9Sstevel@tonic-gate if (*d == '.')
2867c478bd9Sstevel@tonic-gate break;
2877c478bd9Sstevel@tonic-gate } else if (quote_quote && in_quotes && (*d == '"')) {
2887c478bd9Sstevel@tonic-gate quote_quote = FALSE;
2897c478bd9Sstevel@tonic-gate } else if (quote_quote && (*d != '"')) {
2907c478bd9Sstevel@tonic-gate quote_quote = FALSE;
2917c478bd9Sstevel@tonic-gate in_quotes = TRUE;
2927c478bd9Sstevel@tonic-gate } else if (quote_quote && (*d == '"')) {
2937c478bd9Sstevel@tonic-gate quote_quote = FALSE;
2947c478bd9Sstevel@tonic-gate } else if (in_quotes && (*d == '"')) {
2957c478bd9Sstevel@tonic-gate quote_quote = TRUE;
2967c478bd9Sstevel@tonic-gate } else if (!in_quotes && (*d == '"')) {
2977c478bd9Sstevel@tonic-gate quote_quote = TRUE;
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate if (quote_quote || in_quotes) {
3027c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "__nis_nextsep_of: "
3037c478bd9Sstevel@tonic-gate "Mismatched quotes in %s", s);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate return (d);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /*
3107c478bd9Sstevel@tonic-gate * nis_domain_of()
3117c478bd9Sstevel@tonic-gate *
3127c478bd9Sstevel@tonic-gate * This internal funtion will accept a pointer to a NIS name string and
3137c478bd9Sstevel@tonic-gate * return a pointer to the "domain" part of it.
3147c478bd9Sstevel@tonic-gate *
3157c478bd9Sstevel@tonic-gate * ==== We don't need nis_domain_of_r(), but should we provide one for
3167c478bd9Sstevel@tonic-gate * uniformity?
3177c478bd9Sstevel@tonic-gate */
3187c478bd9Sstevel@tonic-gate nis_name
nis_domain_of(char * s)3197c478bd9Sstevel@tonic-gate nis_domain_of(char *s)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate char *d;
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate d = __nis_nextsep_of(s);
3247c478bd9Sstevel@tonic-gate if (d == NULL)
3257c478bd9Sstevel@tonic-gate return (NULL);
3267c478bd9Sstevel@tonic-gate if (*d == '.')
3277c478bd9Sstevel@tonic-gate d++;
3287c478bd9Sstevel@tonic-gate if (*d == '\0') /* Don't return a zero length string */
3297c478bd9Sstevel@tonic-gate return ("."); /* return root domain instead */
3307c478bd9Sstevel@tonic-gate return (d);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate * nis_leaf_of()
3367c478bd9Sstevel@tonic-gate *
3377c478bd9Sstevel@tonic-gate * Returns the first label of a name. (other half of __domain_of)
3387c478bd9Sstevel@tonic-gate */
3397c478bd9Sstevel@tonic-gate nis_name
nis_leaf_of_r(const nis_name s,char * buf,size_t bufsize)3407c478bd9Sstevel@tonic-gate nis_leaf_of_r(
3417c478bd9Sstevel@tonic-gate const nis_name s,
3427c478bd9Sstevel@tonic-gate char *buf,
3437c478bd9Sstevel@tonic-gate size_t bufsize)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate size_t nchars;
3467c478bd9Sstevel@tonic-gate const char *d = __nis_nextsep_of((char *)s);
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate if (d == 0) {
3497c478bd9Sstevel@tonic-gate return (0);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate nchars = d - s;
3527c478bd9Sstevel@tonic-gate if (bufsize < nchars + 1) {
3537c478bd9Sstevel@tonic-gate return (0);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate (void) strncpy(buf, s, nchars);
3567c478bd9Sstevel@tonic-gate buf[nchars] = '\0';
3577c478bd9Sstevel@tonic-gate return (buf);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
360cb620785Sraf static pthread_key_t buf_key = PTHREAD_ONCE_KEY_NP;
3617c478bd9Sstevel@tonic-gate static char buf_main[LN_BUFSIZE];
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate nis_name
nis_leaf_of(char * s)3647c478bd9Sstevel@tonic-gate nis_leaf_of(char *s)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate char *buf = thr_main()? buf_main :
3677c478bd9Sstevel@tonic-gate thr_get_storage(&buf_key, LN_BUFSIZE, free);
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate if (buf == NULL)
3707c478bd9Sstevel@tonic-gate return (NULL);
3717c478bd9Sstevel@tonic-gate return (nis_leaf_of_r(s, buf, LN_BUFSIZE));
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate * nis_name_of()
3767c478bd9Sstevel@tonic-gate * This internal function will remove from the NIS name, the domain
3777c478bd9Sstevel@tonic-gate * name of the current server, this will leave the unique part in
3787c478bd9Sstevel@tonic-gate * the name this becomes the "internal" version of the name. If this
3797c478bd9Sstevel@tonic-gate * function returns NULL then the name we were given to resolve is
3807c478bd9Sstevel@tonic-gate * bad somehow.
3817c478bd9Sstevel@tonic-gate * NB: Uses static storage and this is a no-no with threads. XXX
3827c478bd9Sstevel@tonic-gate */
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate nis_name
nis_name_of_r(char * s,char * buf,size_t bufsize)3857c478bd9Sstevel@tonic-gate nis_name_of_r(
3867c478bd9Sstevel@tonic-gate char *s, /* string with the name in it. */
3877c478bd9Sstevel@tonic-gate char *buf,
3887c478bd9Sstevel@tonic-gate size_t bufsize)
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate char *d;
3917c478bd9Sstevel@tonic-gate struct local_names *ln = __get_local_names();
3927c478bd9Sstevel@tonic-gate size_t dl, sl;
3937c478bd9Sstevel@tonic-gate name_pos p;
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate #ifdef lint
3967c478bd9Sstevel@tonic-gate bufsize = bufsize;
3977c478bd9Sstevel@tonic-gate #endif /* lint */
3987c478bd9Sstevel@tonic-gate if ((!s) || (!ln))
3997c478bd9Sstevel@tonic-gate return (NULL); /* No string, this can't continue */
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate d = &(ln->domain[0]);
4027c478bd9Sstevel@tonic-gate dl = strlen(ln->domain); /* _always dot terminated_ */
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate sl = strlen(s);
4057c478bd9Sstevel@tonic-gate if (sl >= bufsize || (s[sl-1] != '.' && sl >= bufsize-1))
4067c478bd9Sstevel@tonic-gate return (NULL);
4077c478bd9Sstevel@tonic-gate (void) strcpy(buf, s); /* Make a private copy of 's' */
4087c478bd9Sstevel@tonic-gate if (buf[sl-1] != '.') { /* Add a dot if necessary. */
4097c478bd9Sstevel@tonic-gate (void) strcat(buf, ".");
4107c478bd9Sstevel@tonic-gate sl++;
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate if (dl == 1) { /* We're the '.' directory */
4147c478bd9Sstevel@tonic-gate buf[sl-1] = '\0'; /* Lose the 'dot' */
4157c478bd9Sstevel@tonic-gate return (buf);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate p = nis_dir_cmp(buf, d);
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate /* 's' is above 'd' in the tree */
4217c478bd9Sstevel@tonic-gate if ((p == HIGHER_NAME) || (p == NOT_SEQUENTIAL) || (p == SAME_NAME))
4227c478bd9Sstevel@tonic-gate return (NULL);
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate /* Insert a NUL where the domain name starts in the string */
4257c478bd9Sstevel@tonic-gate buf[(sl - dl) - 1] = '\0';
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate /* Don't return a zero length name */
4287c478bd9Sstevel@tonic-gate if (buf[0] == '\0')
4297c478bd9Sstevel@tonic-gate return (NULL);
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate return (buf);
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate nis_name
nis_name_of(char * s)4357c478bd9Sstevel@tonic-gate nis_name_of(
4367c478bd9Sstevel@tonic-gate char *s) /* string with the name in it. */
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate char *buf = thr_main()? buf_main :
4397c478bd9Sstevel@tonic-gate thr_get_storage(&buf_key, LN_BUFSIZE, free);
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate if (!buf)
4427c478bd9Sstevel@tonic-gate return (NULL);
4437c478bd9Sstevel@tonic-gate return (nis_name_of_r(s, buf, LN_BUFSIZE));
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate * nis_local_directory()
4507c478bd9Sstevel@tonic-gate *
4517c478bd9Sstevel@tonic-gate * Return a pointer to a string with the local directory name in it.
4527c478bd9Sstevel@tonic-gate */
4537c478bd9Sstevel@tonic-gate nis_name
nis_local_directory(void)4547c478bd9Sstevel@tonic-gate nis_local_directory(void)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate struct local_names *ln = __get_local_names();
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate /* LOCK NOTE: Warning, after initialization, "ln" is expected */
4597c478bd9Sstevel@tonic-gate /* to stay constant, So no need to lock here. If this assumption */
4607c478bd9Sstevel@tonic-gate /* is changed, this code must be protected. */
4617c478bd9Sstevel@tonic-gate if (ln == NULL)
4627c478bd9Sstevel@tonic-gate return (NULL);
4637c478bd9Sstevel@tonic-gate return (ln->domain);
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate * __nis_rpc_domain()
4687c478bd9Sstevel@tonic-gate *
4697c478bd9Sstevel@tonic-gate * Return a pointer to a string with the rpc domain name in it.
4707c478bd9Sstevel@tonic-gate */
4717c478bd9Sstevel@tonic-gate nis_name
__nis_rpc_domain()4727c478bd9Sstevel@tonic-gate __nis_rpc_domain()
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate struct local_names *ln = __get_local_names();
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate /* LOCK NOTE: Warning, after initialization, "ln" is expected */
4777c478bd9Sstevel@tonic-gate /* to stay constant, So no need to lock here. If this assumption */
4787c478bd9Sstevel@tonic-gate /* is changed, this code must be protected. */
4797c478bd9Sstevel@tonic-gate if (ln == NULL)
4807c478bd9Sstevel@tonic-gate return (NULL);
4817c478bd9Sstevel@tonic-gate return (ln->rpcdomain);
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate /*
4867c478bd9Sstevel@tonic-gate * nis_local_host()
4877c478bd9Sstevel@tonic-gate * Generate the principal name for this host, "hostname"+"domainname"
4887c478bd9Sstevel@tonic-gate * unless the hostname already has "dots" in its name.
4897c478bd9Sstevel@tonic-gate */
4907c478bd9Sstevel@tonic-gate nis_name
nis_local_host(void)4917c478bd9Sstevel@tonic-gate nis_local_host(void)
4927c478bd9Sstevel@tonic-gate {
4937c478bd9Sstevel@tonic-gate struct local_names *ln = __get_local_names();
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate /* LOCK NOTE: Warning, after initialization, "ln" is expected */
4967c478bd9Sstevel@tonic-gate /* to stay constant, So no need to lock here. If this assumption */
4977c478bd9Sstevel@tonic-gate /* is changed, this code must be protected. */
4987c478bd9Sstevel@tonic-gate if (ln == NULL)
4997c478bd9Sstevel@tonic-gate return (NULL);
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate return (ln->host);
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate /*
5057c478bd9Sstevel@tonic-gate * nis_destroy_object()
5067c478bd9Sstevel@tonic-gate * This function takes a pointer to a NIS object and deallocates it. This
5077c478bd9Sstevel@tonic-gate * is the inverse of __clone_object below. It must be able to correctly
5087c478bd9Sstevel@tonic-gate * deallocate partially allocated objects because __clone_object will call
5097c478bd9Sstevel@tonic-gate * it if it runs out of memory and has to abort. Everything is freed,
5107c478bd9Sstevel@tonic-gate * INCLUDING the pointer that is passed.
5117c478bd9Sstevel@tonic-gate */
5127c478bd9Sstevel@tonic-gate void
nis_destroy_object(nis_object * obj)5137c478bd9Sstevel@tonic-gate nis_destroy_object(nis_object *obj) /* The object to clone */
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate if (obj == 0)
5167c478bd9Sstevel@tonic-gate return;
5177c478bd9Sstevel@tonic-gate xdr_free(xdr_nis_object, (char *)obj);
5187c478bd9Sstevel@tonic-gate free(obj);
5197c478bd9Sstevel@tonic-gate } /* nis_destroy_object */
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate static void
destroy_nis_sdata(void * p)5227c478bd9Sstevel@tonic-gate destroy_nis_sdata(void *p)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate struct nis_sdata *ns = p;
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate if (ns->buf != 0)
5277c478bd9Sstevel@tonic-gate free(ns->buf);
5287c478bd9Sstevel@tonic-gate free(ns);
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate
5317c478bd9Sstevel@tonic-gate /* XXX Why are these static ? */
5327c478bd9Sstevel@tonic-gate /* static XDR in_xdrs, out_xdrs; */
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate /*
5367c478bd9Sstevel@tonic-gate * __clone_object_r()
5377c478bd9Sstevel@tonic-gate * This function takes a pointer to a NIS object and clones it. This
5387c478bd9Sstevel@tonic-gate * duplicate object is now available for use in the local context.
5397c478bd9Sstevel@tonic-gate */
5407c478bd9Sstevel@tonic-gate nis_object *
nis_clone_object_r(nis_object * obj,nis_object * dest,struct nis_sdata * clone_buf_ptr)5417c478bd9Sstevel@tonic-gate nis_clone_object_r(
5427c478bd9Sstevel@tonic-gate nis_object *obj, /* The object to clone */
5437c478bd9Sstevel@tonic-gate nis_object *dest, /* Use this pointer if non-null */
5447c478bd9Sstevel@tonic-gate struct nis_sdata *clone_buf_ptr)
5457c478bd9Sstevel@tonic-gate {
5467c478bd9Sstevel@tonic-gate nis_object *result; /* The clone itself */
5477c478bd9Sstevel@tonic-gate int status; /* a counter variable */
5487c478bd9Sstevel@tonic-gate XDR in_xdrs, out_xdrs;
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate if (!nis_get_static_storage(clone_buf_ptr, 1,
5517c478bd9Sstevel@tonic-gate xdr_sizeof(xdr_nis_object, obj)))
5527c478bd9Sstevel@tonic-gate return (NULL);
5537c478bd9Sstevel@tonic-gate
55461961e0fSrobinson (void) memset(&in_xdrs, 0, sizeof (in_xdrs));
55561961e0fSrobinson (void) memset(&out_xdrs, 0, sizeof (out_xdrs));
5567c478bd9Sstevel@tonic-gate xdrmem_create(&in_xdrs, clone_buf_ptr->buf, clone_buf_ptr->size,
5577c478bd9Sstevel@tonic-gate XDR_ENCODE);
5587c478bd9Sstevel@tonic-gate xdrmem_create(&out_xdrs, clone_buf_ptr->buf, clone_buf_ptr->size,
5597c478bd9Sstevel@tonic-gate XDR_DECODE);
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate /* Allocate a basic NIS object structure */
5627c478bd9Sstevel@tonic-gate if (dest) {
56361961e0fSrobinson (void) memset(dest, 0, sizeof (nis_object));
5647c478bd9Sstevel@tonic-gate result = dest;
5657c478bd9Sstevel@tonic-gate } else
56661961e0fSrobinson result = calloc(1, sizeof (nis_object));
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate if (result == NULL)
5697c478bd9Sstevel@tonic-gate return (NULL);
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate /* Encode our object into the clone buffer */
5727c478bd9Sstevel@tonic-gate (void) xdr_setpos(&in_xdrs, 0);
5737c478bd9Sstevel@tonic-gate status = xdr_nis_object(&in_xdrs, obj);
5747c478bd9Sstevel@tonic-gate if (status == FALSE)
5757c478bd9Sstevel@tonic-gate return (NULL);
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate /* Now decode the buffer into our result pointer ... */
5787c478bd9Sstevel@tonic-gate (void) xdr_setpos(&out_xdrs, 0);
5797c478bd9Sstevel@tonic-gate status = xdr_nis_object(&out_xdrs, result);
5807c478bd9Sstevel@tonic-gate if (status == FALSE)
5817c478bd9Sstevel@tonic-gate return (NULL);
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate /* presto changeo, a new object */
5847c478bd9Sstevel@tonic-gate return (result);
5857c478bd9Sstevel@tonic-gate } /* __clone_object_r */
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate nis_object *
nis_clone_object(nis_object * obj,nis_object * dest)5897c478bd9Sstevel@tonic-gate nis_clone_object(
5907c478bd9Sstevel@tonic-gate nis_object *obj, /* The object to clone */
5917c478bd9Sstevel@tonic-gate nis_object *dest) /* Use this pointer if non-null */
5927c478bd9Sstevel@tonic-gate {
593cb620785Sraf static pthread_key_t clone_buf_key = PTHREAD_ONCE_KEY_NP;
5947c478bd9Sstevel@tonic-gate static struct nis_sdata clone_buf_main;
5957c478bd9Sstevel@tonic-gate struct nis_sdata *clone_buf_ptr;
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate clone_buf_ptr = thr_main()? &clone_buf_main :
5987c478bd9Sstevel@tonic-gate thr_get_storage(&clone_buf_key, sizeof (struct nis_sdata),
5997c478bd9Sstevel@tonic-gate destroy_nis_sdata);
6007c478bd9Sstevel@tonic-gate return (nis_clone_object_r(obj, dest, clone_buf_ptr));
6017c478bd9Sstevel@tonic-gate } /* __clone_object */
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate /* Various subroutines used by the server code */
6047c478bd9Sstevel@tonic-gate nis_object *
nis_read_obj(char * f)6057c478bd9Sstevel@tonic-gate nis_read_obj(char *f) /* name of the object to read */
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate FILE *rootfile;
6087c478bd9Sstevel@tonic-gate int status; /* Status of the XDR decoding */
6097c478bd9Sstevel@tonic-gate XDR xdrs; /* An xdr stream handle */
6107c478bd9Sstevel@tonic-gate nis_object *res;
6117c478bd9Sstevel@tonic-gate
61261961e0fSrobinson res = calloc(1, sizeof (nis_object));
6137c478bd9Sstevel@tonic-gate if (!res)
6147c478bd9Sstevel@tonic-gate return (NULL);
6157c478bd9Sstevel@tonic-gate
616004388ebScasper rootfile = fopen(f, "rF");
6177c478bd9Sstevel@tonic-gate if (rootfile == NULL) {
6187c478bd9Sstevel@tonic-gate /* This is ok if we are the root of roots. */
6197c478bd9Sstevel@tonic-gate free(res);
6207c478bd9Sstevel@tonic-gate return (NULL);
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate /* Now read in the object */
6237c478bd9Sstevel@tonic-gate xdrstdio_create(&xdrs, rootfile, XDR_DECODE);
6247c478bd9Sstevel@tonic-gate status = xdr_nis_object(&xdrs, res);
6257c478bd9Sstevel@tonic-gate xdr_destroy(&xdrs);
6267c478bd9Sstevel@tonic-gate (void) fclose(rootfile);
6277c478bd9Sstevel@tonic-gate if (!status) {
6287c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Object file %s is corrupt!", f);
6297c478bd9Sstevel@tonic-gate xdr_free(xdr_nis_object, (char *)res);
6307c478bd9Sstevel@tonic-gate free(res);
6317c478bd9Sstevel@tonic-gate return (NULL);
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate return (res);
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate int
nis_write_obj(char * f,nis_object * o)6377c478bd9Sstevel@tonic-gate nis_write_obj(
6387c478bd9Sstevel@tonic-gate char *f, /* name of the object to read */
6397c478bd9Sstevel@tonic-gate nis_object *o) /* The object to write */
6407c478bd9Sstevel@tonic-gate {
6417c478bd9Sstevel@tonic-gate FILE *rootfile;
6427c478bd9Sstevel@tonic-gate int status; /* Status of the XDR decoding */
6437c478bd9Sstevel@tonic-gate XDR xdrs; /* An xdr stream handle */
6447c478bd9Sstevel@tonic-gate
645004388ebScasper rootfile = fopen(f, "wF");
6467c478bd9Sstevel@tonic-gate if (rootfile == NULL) {
6477c478bd9Sstevel@tonic-gate return (0);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate /* Now encode the object */
6507c478bd9Sstevel@tonic-gate xdrstdio_create(&xdrs, rootfile, XDR_ENCODE);
6517c478bd9Sstevel@tonic-gate status = xdr_nis_object(&xdrs, o);
6527c478bd9Sstevel@tonic-gate xdr_destroy(&xdrs);
6537c478bd9Sstevel@tonic-gate (void) fclose(rootfile);
6547c478bd9Sstevel@tonic-gate return (status);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate /*
6587c478bd9Sstevel@tonic-gate * Transport INDEPENDENT RPC code. This code assumes you
6597c478bd9Sstevel@tonic-gate * are using the new RPC/tli code and will build
6607c478bd9Sstevel@tonic-gate * a ping handle on top of a datagram transport.
6617c478bd9Sstevel@tonic-gate */
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate /*
6647c478bd9Sstevel@tonic-gate * __map_addr()
6657c478bd9Sstevel@tonic-gate *
6667c478bd9Sstevel@tonic-gate * This is our internal function that replaces rpcb_getaddr(). We
6677c478bd9Sstevel@tonic-gate * build our own to prevent calling netdir_getbyname() which could
6687c478bd9Sstevel@tonic-gate * recurse to the nameservice.
6697c478bd9Sstevel@tonic-gate */
6707c478bd9Sstevel@tonic-gate static char *
__map_addr(struct netconfig * nc,char * uaddr,rpcprog_t prog,rpcvers_t ver)6717c478bd9Sstevel@tonic-gate __map_addr(
6727c478bd9Sstevel@tonic-gate struct netconfig *nc, /* Our transport */
6737c478bd9Sstevel@tonic-gate char *uaddr, /* RPCBIND address */
6747c478bd9Sstevel@tonic-gate rpcprog_t prog, /* Name service Prog */
6757c478bd9Sstevel@tonic-gate rpcvers_t ver)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate CLIENT *client;
6787c478bd9Sstevel@tonic-gate RPCB parms; /* Parameters for RPC binder */
6797c478bd9Sstevel@tonic-gate enum clnt_stat clnt_st; /* Result from the rpc call */
6807c478bd9Sstevel@tonic-gate char *ua = NULL; /* Universal address of service */
6817c478bd9Sstevel@tonic-gate char *res = NULL; /* Our result to the parent */
6827c478bd9Sstevel@tonic-gate struct timeval tv; /* Timeout for our rpcb call */
6837c478bd9Sstevel@tonic-gate int ilen, olen; /* buffer length for clnt_tli_create */
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate * If using "udp", use __nisipbufsize if inbuf and outbuf are set to 0.
6877c478bd9Sstevel@tonic-gate */
6887c478bd9Sstevel@tonic-gate if (strcmp(NC_UDP, nc->nc_proto) == 0) {
6897c478bd9Sstevel@tonic-gate /* for udp only */
6907c478bd9Sstevel@tonic-gate ilen = olen = __nisipbufsize;
6917c478bd9Sstevel@tonic-gate } else {
6927c478bd9Sstevel@tonic-gate ilen = olen = 0;
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate client = __nis_clnt_create(RPC_ANYFD, nc, uaddr, 0, 0,
6957c478bd9Sstevel@tonic-gate RPCBPROG, RPCBVERS, ilen, olen);
69661961e0fSrobinson if (!client)
6977c478bd9Sstevel@tonic-gate return (NULL);
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate (void) clnt_control(client, CLSET_FD_CLOSE, NULL);
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate /*
7027c478bd9Sstevel@tonic-gate * Now make the call to get the NIS service address.
7037c478bd9Sstevel@tonic-gate * We set the retry timeout to 3 seconds so that we
7047c478bd9Sstevel@tonic-gate * will retry a few times. Retries should be rare
7057c478bd9Sstevel@tonic-gate * because we are usually only called when we know
7067c478bd9Sstevel@tonic-gate * a server is available.
7077c478bd9Sstevel@tonic-gate */
7087c478bd9Sstevel@tonic-gate tv.tv_sec = 3;
7097c478bd9Sstevel@tonic-gate tv.tv_usec = 0;
7107c478bd9Sstevel@tonic-gate (void) clnt_control(client, CLSET_RETRY_TIMEOUT, (char *)&tv);
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate tv.tv_sec = 10;
7137c478bd9Sstevel@tonic-gate tv.tv_usec = 0;
7147c478bd9Sstevel@tonic-gate parms.r_prog = prog;
7157c478bd9Sstevel@tonic-gate parms.r_vers = ver;
7167c478bd9Sstevel@tonic-gate parms.r_netid = nc->nc_netid; /* not needed */
7177c478bd9Sstevel@tonic-gate parms.r_addr = ""; /* not needed; just for xdring */
7187c478bd9Sstevel@tonic-gate parms.r_owner = ""; /* not needed; just for xdring */
7197c478bd9Sstevel@tonic-gate clnt_st = clnt_call(client, RPCBPROC_GETADDR, xdr_rpcb, (char *)&parms,
7207c478bd9Sstevel@tonic-gate xdr_wrapstring, (char *)&ua, tv);
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate if (clnt_st == RPC_SUCCESS) {
7237c478bd9Sstevel@tonic-gate clnt_destroy(client);
7247c478bd9Sstevel@tonic-gate if (*ua == '\0') {
72561961e0fSrobinson free(ua);
7267c478bd9Sstevel@tonic-gate return (NULL);
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate res = strdup(ua);
7297c478bd9Sstevel@tonic-gate xdr_free(xdr_wrapstring, (char *)&ua);
7307c478bd9Sstevel@tonic-gate return (res);
7317c478bd9Sstevel@tonic-gate } else if (((clnt_st == RPC_PROGVERSMISMATCH) ||
7327c478bd9Sstevel@tonic-gate (clnt_st == RPC_PROGUNAVAIL)) &&
7337c478bd9Sstevel@tonic-gate (strcmp(nc->nc_protofmly, NC_INET) == 0)) {
7347c478bd9Sstevel@tonic-gate /*
7357c478bd9Sstevel@tonic-gate * version 3 not available. Try version 2
7367c478bd9Sstevel@tonic-gate * The assumption here is that the netbuf
7377c478bd9Sstevel@tonic-gate * is arranged in the sockaddr_in
7387c478bd9Sstevel@tonic-gate * style for IP cases.
7397c478bd9Sstevel@tonic-gate *
7407c478bd9Sstevel@tonic-gate * Note: If the remote host doesn't support version 3,
7417c478bd9Sstevel@tonic-gate * we assume it doesn't know IPv6 either.
7427c478bd9Sstevel@tonic-gate */
7437c478bd9Sstevel@tonic-gate ushort_t port;
7447c478bd9Sstevel@tonic-gate struct sockaddr_in *sa;
7457c478bd9Sstevel@tonic-gate struct netbuf remote;
7467c478bd9Sstevel@tonic-gate int protocol;
7477c478bd9Sstevel@tonic-gate char buf[32];
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate (void) clnt_control(client, CLGET_SVC_ADDR, (char *)&remote);
75061961e0fSrobinson /* LINTED pointer cast */
7517c478bd9Sstevel@tonic-gate sa = (struct sockaddr_in *)(remote.buf);
7527c478bd9Sstevel@tonic-gate protocol = strcmp(nc->nc_proto, NC_TCP) ?
7537c478bd9Sstevel@tonic-gate IPPROTO_UDP : IPPROTO_TCP;
7547c478bd9Sstevel@tonic-gate port = (ushort_t)pmap_getport(sa, prog, ver, protocol);
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate if (port != 0) {
7577c478bd9Sstevel@tonic-gate port = htons(port);
7587c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%d.%d.%d.%d.%d.%d",
7597c478bd9Sstevel@tonic-gate (sa->sin_addr.s_addr >> 24) & 0xff,
7607c478bd9Sstevel@tonic-gate (sa->sin_addr.s_addr >> 16) & 0xff,
7617c478bd9Sstevel@tonic-gate (sa->sin_addr.s_addr >> 8) & 0xff,
7627c478bd9Sstevel@tonic-gate (sa->sin_addr.s_addr) & 0xff,
7637c478bd9Sstevel@tonic-gate (port >> 8) & 0xff,
7647c478bd9Sstevel@tonic-gate port & 0xff);
7657c478bd9Sstevel@tonic-gate res = strdup(buf);
7667c478bd9Sstevel@tonic-gate } else
7677c478bd9Sstevel@tonic-gate res = NULL;
7687c478bd9Sstevel@tonic-gate clnt_destroy(client);
7697c478bd9Sstevel@tonic-gate return (res);
7707c478bd9Sstevel@tonic-gate }
7717c478bd9Sstevel@tonic-gate if (clnt_st == RPC_TIMEDOUT)
7727c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "NIS+ server not responding");
7737c478bd9Sstevel@tonic-gate else
7747c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "NIS+ server could not be contacted: %s",
7757c478bd9Sstevel@tonic-gate clnt_sperrno(clnt_st));
7767c478bd9Sstevel@tonic-gate clnt_destroy(client);
7777c478bd9Sstevel@tonic-gate return (NULL);
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate #define MAX_EP (20)
7827c478bd9Sstevel@tonic-gate
7837c478bd9Sstevel@tonic-gate extern int __can_use_af(sa_family_t af);
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate CLIENT *
__nis_clnt_create(int fd,struct netconfig * nc,char * uaddr,struct netbuf * addr,int domapaddr,int prog,int ver,int inbuf,int outbuf)7867c478bd9Sstevel@tonic-gate __nis_clnt_create(int fd, struct netconfig *nc, char *uaddr,
7877c478bd9Sstevel@tonic-gate struct netbuf *addr, int domapaddr,
7887c478bd9Sstevel@tonic-gate int prog, int ver, int inbuf, int outbuf) {
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate char *svc_addr;
7917c478bd9Sstevel@tonic-gate CLIENT *clnt;
7927c478bd9Sstevel@tonic-gate int freeaddr = 0;
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate /* Sanity check */
7957c478bd9Sstevel@tonic-gate if (nc == 0 || (addr == 0 && uaddr == 0)) {
7967c478bd9Sstevel@tonic-gate return (0);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate /*
8007c478bd9Sstevel@tonic-gate * Check if we have a useable interface for this address family.
8017c478bd9Sstevel@tonic-gate * This check properly belongs in RPC (or even further down),
8027c478bd9Sstevel@tonic-gate * but until they provide it, we roll our own.
8037c478bd9Sstevel@tonic-gate */
8047c478bd9Sstevel@tonic-gate if (__can_use_af((strcmp(nc->nc_protofmly, NC_INET6) == 0) ?
8057c478bd9Sstevel@tonic-gate AF_INET6 : AF_INET) == 0) {
8067c478bd9Sstevel@tonic-gate return (0);
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate
8097c478bd9Sstevel@tonic-gate if (domapaddr) {
8107c478bd9Sstevel@tonic-gate svc_addr = __map_addr(nc, uaddr, prog, ver);
8117c478bd9Sstevel@tonic-gate if (svc_addr == 0)
8127c478bd9Sstevel@tonic-gate return (0);
8137c478bd9Sstevel@tonic-gate addr = uaddr2taddr(nc, svc_addr);
8147c478bd9Sstevel@tonic-gate freeaddr = 1;
8157c478bd9Sstevel@tonic-gate free(svc_addr);
8167c478bd9Sstevel@tonic-gate } else if (addr == 0) {
8177c478bd9Sstevel@tonic-gate addr = uaddr2taddr(nc, uaddr);
8187c478bd9Sstevel@tonic-gate freeaddr = 1;
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate if (addr == 0) {
8227c478bd9Sstevel@tonic-gate return (0);
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate
8257c478bd9Sstevel@tonic-gate clnt = clnt_tli_create(fd, nc, addr, prog, ver, outbuf, inbuf);
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate if (clnt) {
8287c478bd9Sstevel@tonic-gate if (clnt_control(clnt, CLGET_FD, (char *)&fd))
8297c478bd9Sstevel@tonic-gate /* make it "close on exec" */
830e8031f0aSraf (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
8317c478bd9Sstevel@tonic-gate (void) clnt_control(clnt, CLSET_FD_CLOSE, NULL);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate
8347c478bd9Sstevel@tonic-gate if (freeaddr)
8357c478bd9Sstevel@tonic-gate netdir_free(addr, ND_ADDR);
8367c478bd9Sstevel@tonic-gate
8377c478bd9Sstevel@tonic-gate return (clnt);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate static mutex_t __nis_ss_used_lock = DEFAULTMUTEX; /* lock level 3 */
8417c478bd9Sstevel@tonic-gate int __nis_ss_used = 0;
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate /*
8447c478bd9Sstevel@tonic-gate * nis_get_static_storage()
8457c478bd9Sstevel@tonic-gate *
8467c478bd9Sstevel@tonic-gate * This function is used by various functions in their effort to minimize the
8477c478bd9Sstevel@tonic-gate * hassles of memory management in an RPC daemon. Because the service doesn't
8487c478bd9Sstevel@tonic-gate * implement any hard limits, this function allows people to get automatically
8497c478bd9Sstevel@tonic-gate * growing buffers that meet their storage requirements. It returns the
8507c478bd9Sstevel@tonic-gate * pointer in the nis_sdata structure.
8517c478bd9Sstevel@tonic-gate *
8527c478bd9Sstevel@tonic-gate */
8537c478bd9Sstevel@tonic-gate void *
nis_get_static_storage(struct nis_sdata * bs,uint_t el,uint_t nel)8547c478bd9Sstevel@tonic-gate nis_get_static_storage(
8557c478bd9Sstevel@tonic-gate struct nis_sdata *bs, /* User buffer structure */
8567c478bd9Sstevel@tonic-gate uint_t el, /* Sizeof elements */
8577c478bd9Sstevel@tonic-gate uint_t nel) /* Number of elements */
8587c478bd9Sstevel@tonic-gate {
8597c478bd9Sstevel@tonic-gate uint_t sz;
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate sz = nel * el;
8627c478bd9Sstevel@tonic-gate if (!bs)
8637c478bd9Sstevel@tonic-gate return (NULL);
8647c478bd9Sstevel@tonic-gate
8657c478bd9Sstevel@tonic-gate if (!bs->buf) {
86661961e0fSrobinson bs->buf = malloc(sz);
8677c478bd9Sstevel@tonic-gate if (!bs->buf)
8687c478bd9Sstevel@tonic-gate return (NULL);
8697c478bd9Sstevel@tonic-gate bs->size = sz;
8707c478bd9Sstevel@tonic-gate sig_mutex_lock(&__nis_ss_used_lock);
8717c478bd9Sstevel@tonic-gate __nis_ss_used += sz;
8727c478bd9Sstevel@tonic-gate sig_mutex_unlock(&__nis_ss_used_lock);
8737c478bd9Sstevel@tonic-gate } else if (bs->size < sz) {
8747c478bd9Sstevel@tonic-gate int size_delta;
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate free(bs->buf);
8777c478bd9Sstevel@tonic-gate size_delta = - (bs->size);
87861961e0fSrobinson bs->buf = malloc(sz);
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate /* check the result of malloc() first */
8817c478bd9Sstevel@tonic-gate /* then update the statistic. */
8827c478bd9Sstevel@tonic-gate if (!bs->buf)
8837c478bd9Sstevel@tonic-gate return (NULL);
8847c478bd9Sstevel@tonic-gate bs->size = sz;
8857c478bd9Sstevel@tonic-gate size_delta += sz;
8867c478bd9Sstevel@tonic-gate sig_mutex_lock(&__nis_ss_used_lock);
8877c478bd9Sstevel@tonic-gate __nis_ss_used += size_delta;
8887c478bd9Sstevel@tonic-gate sig_mutex_unlock(&__nis_ss_used_lock);
8897c478bd9Sstevel@tonic-gate }
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate (void) memset(bs->buf, 0, sz); /* SYSV version of bzero() */
8927c478bd9Sstevel@tonic-gate return (bs->buf);
8937c478bd9Sstevel@tonic-gate }
894