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  */
216935f61bSMarcel Telka 
226935f61bSMarcel Telka /*
236935f61bSMarcel Telka  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
246935f61bSMarcel Telka  */
256935f61bSMarcel Telka 
267c478bd9Sstevel@tonic-gate /*
27004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
287c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
327c478bd9Sstevel@tonic-gate /*	 All Rights Reserved 	*/
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include <ctype.h>
357c478bd9Sstevel@tonic-gate #include <stdio.h>
367c478bd9Sstevel@tonic-gate #include <tiuser.h>
377c478bd9Sstevel@tonic-gate #include <netdir.h>
387c478bd9Sstevel@tonic-gate #include <netconfig.h>
397c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
407c478bd9Sstevel@tonic-gate #include <sys/param.h>
417c478bd9Sstevel@tonic-gate #include <string.h>
427c478bd9Sstevel@tonic-gate #include <stdlib.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  *	The generic name to address mappings for any transport that
467c478bd9Sstevel@tonic-gate  *	has strings for address (e.g., ISO Starlan).
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  *	Address in ISO Starlan consist of arbitrary strings of
497c478bd9Sstevel@tonic-gate  *	characters.  Because of this, the following routines
507c478bd9Sstevel@tonic-gate  *	create an "address" based on two strings, one gotten
517c478bd9Sstevel@tonic-gate  *	from a "host" file and one gotten from a "services" file.
527c478bd9Sstevel@tonic-gate  *	The two strings are catenated together (with a "." between
537c478bd9Sstevel@tonic-gate  *	them).  The hosts file is /etc/net/starlan/hosts and
547c478bd9Sstevel@tonic-gate  *	contain lines of the form:
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  *		arbitrary_string	machname
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  *	To make things simple, the "arbitrary string" should be the
597c478bd9Sstevel@tonic-gate  *	machine name.
607c478bd9Sstevel@tonic-gate  *
617c478bd9Sstevel@tonic-gate  *	The services file is /etc/net/starlan/services and has lines
627c478bd9Sstevel@tonic-gate  *	of the form:
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  *		service_name	arbitrary_string
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  *	Again, to make things easer, the "arbitrary name" should be the
677c478bd9Sstevel@tonic-gate  *	service name.
687c478bd9Sstevel@tonic-gate  */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #define	HOSTFILE	"/etc/net/%s/hosts"
717c478bd9Sstevel@tonic-gate #define	SERVICEFILE	"/etc/net/%s/services"
727c478bd9Sstevel@tonic-gate #define	FIELD1		1
737c478bd9Sstevel@tonic-gate #define	FIELD2		2
746935f61bSMarcel Telka #define	LOCALHOST	"localhost"
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static int searchhost(struct netconfig *, char *, int, char *);
777c478bd9Sstevel@tonic-gate static int searchserv(struct netconfig *, char *, int, char *);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  *	_netdir_getbyname() returns all of the addresses for
817c478bd9Sstevel@tonic-gate  *	a specified host and service.
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate struct nd_addrlist *
_netdir_getbyname(struct netconfig * netconfigp,struct nd_hostserv * nd_hostservp)857c478bd9Sstevel@tonic-gate _netdir_getbyname(struct netconfig *netconfigp,
867c478bd9Sstevel@tonic-gate     struct nd_hostserv *nd_hostservp)
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate 	char   fulladdr[BUFSIZ];   /* holds the full address string	   */
897c478bd9Sstevel@tonic-gate 	struct nd_addrlist *retp;  /* the return structure		   */
907c478bd9Sstevel@tonic-gate 	struct netbuf *netbufp;    /* indexes through the addresses	   */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	/*
937c478bd9Sstevel@tonic-gate 	 *	HOST_BROADCAST is not supported.
947c478bd9Sstevel@tonic-gate 	 */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	if (strcmp(nd_hostservp->h_host, HOST_BROADCAST) == 0) {
977c478bd9Sstevel@tonic-gate 		_nderror = ND_NOHOST;
987c478bd9Sstevel@tonic-gate 		return (NULL);
997c478bd9Sstevel@tonic-gate 	}
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	if (searchhost(netconfigp, nd_hostservp->h_host, FIELD2,
1027c478bd9Sstevel@tonic-gate 	    fulladdr) == 0) {
1037c478bd9Sstevel@tonic-gate 		_nderror = ND_NOHOST;
1047c478bd9Sstevel@tonic-gate 		return (NULL);
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	/*
1087c478bd9Sstevel@tonic-gate 	 *	Now simply fill in the address by forming strings of the
1097c478bd9Sstevel@tonic-gate 	 *	form "string_from_hosts.string_from_services"
1107c478bd9Sstevel@tonic-gate 	 */
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	if (nd_hostservp->h_serv &&
1137c478bd9Sstevel@tonic-gate 	    (strcmp(nd_hostservp->h_serv, "rpcbind") == 0)) {
1147c478bd9Sstevel@tonic-gate 		(void) strcat(fulladdr, ".");
1157c478bd9Sstevel@tonic-gate 		(void) strcat(fulladdr, "rpc");	/* hard coded */
1167c478bd9Sstevel@tonic-gate 	} else {
1177c478bd9Sstevel@tonic-gate 		/*
1187c478bd9Sstevel@tonic-gate 		 *	Get the address from the services file
1197c478bd9Sstevel@tonic-gate 		 */
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 		if (nd_hostservp->h_serv && (nd_hostservp->h_serv[0] != '\0')) {
1227c478bd9Sstevel@tonic-gate 			(void) strcat(fulladdr, ".");
1237c478bd9Sstevel@tonic-gate 			if (searchserv(netconfigp, nd_hostservp->h_serv, FIELD1,
1247c478bd9Sstevel@tonic-gate 			    fulladdr + strlen(fulladdr)) == 0) {
1257c478bd9Sstevel@tonic-gate 				_nderror = ND_NOSERV;
1267c478bd9Sstevel@tonic-gate 				return (NULL);
1277c478bd9Sstevel@tonic-gate 			}
1287c478bd9Sstevel@tonic-gate 		}
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	if ((retp = malloc(sizeof (struct nd_addrlist))) == NULL) {
1327c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
1337c478bd9Sstevel@tonic-gate 		return (NULL);
1347c478bd9Sstevel@tonic-gate 	}
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	/*
1377c478bd9Sstevel@tonic-gate 	 *	We do not worry about multiple addresses here.  Loopbacks
1387c478bd9Sstevel@tonic-gate 	 *	have only one interface.
1397c478bd9Sstevel@tonic-gate 	 */
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	retp->n_cnt = 1;
1427c478bd9Sstevel@tonic-gate 	if ((retp->n_addrs = malloc(sizeof (struct netbuf))) == NULL) {
1437c478bd9Sstevel@tonic-gate 		free(retp);
1447c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
1457c478bd9Sstevel@tonic-gate 		return (NULL);
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	netbufp = retp->n_addrs;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	/*
1517c478bd9Sstevel@tonic-gate 	 *	Don't include the terminating NULL character in the
1527c478bd9Sstevel@tonic-gate 	 *	length.
1537c478bd9Sstevel@tonic-gate 	 */
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	netbufp->len = netbufp->maxlen = (int)strlen(fulladdr);
1567c478bd9Sstevel@tonic-gate 	if ((netbufp->buf = strdup(fulladdr)) == NULL) {
1577c478bd9Sstevel@tonic-gate 		free(netbufp);
1587c478bd9Sstevel@tonic-gate 		free(retp);
1597c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
1607c478bd9Sstevel@tonic-gate 		return (NULL);
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 	_nderror = ND_OK;
1637c478bd9Sstevel@tonic-gate 	return (retp);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate  *	_netdir_getbyaddr() takes an address (hopefully obtained from
1687c478bd9Sstevel@tonic-gate  *	someone doing a _netdir_getbyname()) and returns all hosts with
1697c478bd9Sstevel@tonic-gate  *	that address.
1707c478bd9Sstevel@tonic-gate  */
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate struct nd_hostservlist *
_netdir_getbyaddr(struct netconfig * netconfigp,struct netbuf * netbufp)1737c478bd9Sstevel@tonic-gate _netdir_getbyaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	char   fulladdr[BUFSIZ];	  /* a copy of the address string   */
1767c478bd9Sstevel@tonic-gate 	char   servbuf[BUFSIZ];		  /* a buffer for service string    */
1777c478bd9Sstevel@tonic-gate 	char   hostbuf[BUFSIZ];		  /* points to list of host names   */
1787c478bd9Sstevel@tonic-gate 	char   *hostname;		  /* the "first" path of the string */
1797c478bd9Sstevel@tonic-gate 	char   *servname;		  /* the "second" part of string    */
1807c478bd9Sstevel@tonic-gate 	struct nd_hostservlist *retp;	  /* the return structure	    */
1817c478bd9Sstevel@tonic-gate 	char   *serv;			  /* resultant service name obtained */
1827c478bd9Sstevel@tonic-gate 	int    nhost;			  /* the number of hosts in hostpp  */
1837c478bd9Sstevel@tonic-gate 	struct nd_hostserv *nd_hostservp; /* traverses the host structures  */
1847c478bd9Sstevel@tonic-gate 	char   *nexttok;		  /* next token to process	    */
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	/*
1877c478bd9Sstevel@tonic-gate 	 *	Separate the two parts of the address string.
1887c478bd9Sstevel@tonic-gate 	 */
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	(void) strlcpy(fulladdr, netbufp->buf, sizeof (fulladdr));
1917c478bd9Sstevel@tonic-gate 	hostname = strtok_r(fulladdr, ".", &nexttok);
1927c478bd9Sstevel@tonic-gate 	if (hostname == NULL) {
1937c478bd9Sstevel@tonic-gate 		_nderror = ND_NOHOST;
1947c478bd9Sstevel@tonic-gate 		return (NULL);
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 	servname = strtok_r(NULL, " \n\t", &nexttok);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	/*
1997c478bd9Sstevel@tonic-gate 	 *	Search for all the hosts associated with the
2007c478bd9Sstevel@tonic-gate 	 *	first part of the address string.
2017c478bd9Sstevel@tonic-gate 	 */
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	nhost = searchhost(netconfigp, hostname, FIELD1, hostbuf);
2047c478bd9Sstevel@tonic-gate 	if (nhost == 0) {
2057c478bd9Sstevel@tonic-gate 		_nderror = ND_NOHOST;
2067c478bd9Sstevel@tonic-gate 		return (NULL);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	/*
2107c478bd9Sstevel@tonic-gate 	 *	Search for the service associated with the second
2117c478bd9Sstevel@tonic-gate 	 *	path of the address string.
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	if (servname == NULL) {
2157c478bd9Sstevel@tonic-gate 		_nderror = ND_NOSERV;
2167c478bd9Sstevel@tonic-gate 		return (NULL);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	servbuf[0] = '\0';
2207c478bd9Sstevel@tonic-gate 	serv = servbuf;
2217c478bd9Sstevel@tonic-gate 	if (searchserv(netconfigp, servname, FIELD2, servbuf) == 0) {
2227c478bd9Sstevel@tonic-gate 		serv = _taddr2uaddr(netconfigp, netbufp);
2237c478bd9Sstevel@tonic-gate 		(void) strcpy(servbuf, serv);
2247c478bd9Sstevel@tonic-gate 		free(serv);
2257c478bd9Sstevel@tonic-gate 		serv = servbuf;
2267c478bd9Sstevel@tonic-gate 		while (*serv != '.')
2277c478bd9Sstevel@tonic-gate 			serv++;
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/*
2317c478bd9Sstevel@tonic-gate 	 *	Allocate space to hold the return structure, set the number
2327c478bd9Sstevel@tonic-gate 	 *	of hosts, and allocate space to hold them.
2337c478bd9Sstevel@tonic-gate 	 */
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	if ((retp = malloc(sizeof (struct nd_hostservlist))) == NULL) {
2367c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
2377c478bd9Sstevel@tonic-gate 		return (NULL);
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	retp->h_cnt = nhost;
2417c478bd9Sstevel@tonic-gate 	retp->h_hostservs = calloc(nhost, sizeof (struct nd_hostserv));
2427c478bd9Sstevel@tonic-gate 	if (retp->h_hostservs == NULL) {
2437c478bd9Sstevel@tonic-gate 		free(retp);
2447c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
2457c478bd9Sstevel@tonic-gate 		return (NULL);
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	/*
2497c478bd9Sstevel@tonic-gate 	 *	Loop through the host structues and fill them in with
2507c478bd9Sstevel@tonic-gate 	 *	each host name (and service name).
2517c478bd9Sstevel@tonic-gate 	 */
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	nd_hostservp = retp->h_hostservs;
2547c478bd9Sstevel@tonic-gate 	hostname = strtok_r(hostbuf, ",", &nexttok);
2557c478bd9Sstevel@tonic-gate 	while (hostname && nhost--) {
2567c478bd9Sstevel@tonic-gate 		if (((nd_hostservp->h_host = strdup(hostname)) == NULL) ||
2577c478bd9Sstevel@tonic-gate 		    ((nd_hostservp->h_serv = strdup(serv)) == NULL)) {
2587c478bd9Sstevel@tonic-gate 			netdir_free(retp, ND_HOSTSERVLIST);
2597c478bd9Sstevel@tonic-gate 			_nderror = ND_NOMEM;
2607c478bd9Sstevel@tonic-gate 			return (NULL);
2617c478bd9Sstevel@tonic-gate 		}
2627c478bd9Sstevel@tonic-gate 		nd_hostservp++;
2637c478bd9Sstevel@tonic-gate 		hostname = strtok_r(NULL, ",", &nexttok);
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	_nderror = ND_OK;
2677c478bd9Sstevel@tonic-gate 	return (retp);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate  *	_taddr2uaddr() translates a address into a "universal" address.
2727c478bd9Sstevel@tonic-gate  *	Since the address is a string, simply return the string as the
2737c478bd9Sstevel@tonic-gate  *	universal address (but replace all non-printable characters with
2747c478bd9Sstevel@tonic-gate  *	the \ddd form, where ddd is three octal digits).  The '\n' character
2757c478bd9Sstevel@tonic-gate  *	is also replace by \ddd and the '\' character is placed as two
2767c478bd9Sstevel@tonic-gate  *	'\' characters.
2777c478bd9Sstevel@tonic-gate  */
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /* ARGSUSED */
2807c478bd9Sstevel@tonic-gate char *
_taddr2uaddr(struct netconfig * netconfigp,struct netbuf * netbufp)2817c478bd9Sstevel@tonic-gate _taddr2uaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate 	char *retp;	/* pointer the return string			*/
2847c478bd9Sstevel@tonic-gate 	char *to;	/* traverses and populates the return string	*/
2857c478bd9Sstevel@tonic-gate 	char *from;	/* traverses the string to be converted		*/
2867c478bd9Sstevel@tonic-gate 	int i;		/* indexes through the given string		*/
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	/*
2897c478bd9Sstevel@tonic-gate 	 * BUFSIZ is perhaps too big for this one and there is a better
2907c478bd9Sstevel@tonic-gate 	 * way to optimize it, but for now we will just assume BUFSIZ
2917c478bd9Sstevel@tonic-gate 	 */
2927c478bd9Sstevel@tonic-gate 	if ((retp = malloc(BUFSIZ)) == NULL) {
2937c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
2947c478bd9Sstevel@tonic-gate 		return (NULL);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 	to = retp;
2977c478bd9Sstevel@tonic-gate 	from = netbufp->buf;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	for (i = 0; i < netbufp->len; i++) {
3007c478bd9Sstevel@tonic-gate 		if (*from == '\\') {
3017c478bd9Sstevel@tonic-gate 			*to++ = '\\';
3027c478bd9Sstevel@tonic-gate 			*to++ = '\\';
3037c478bd9Sstevel@tonic-gate 		} else {
3047c478bd9Sstevel@tonic-gate 			if (*from == '\n' || !isprint((unsigned char)*from)) {
3057c478bd9Sstevel@tonic-gate 				(void) sprintf(to, "\\%.3o", *from & 0xff);
3067c478bd9Sstevel@tonic-gate 				to += 4;
3077c478bd9Sstevel@tonic-gate 			} else {
3087c478bd9Sstevel@tonic-gate 				*to++ = *from;
3097c478bd9Sstevel@tonic-gate 			}
3107c478bd9Sstevel@tonic-gate 		}
3117c478bd9Sstevel@tonic-gate 		from++;
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 	*to = '\0';
3147c478bd9Sstevel@tonic-gate 	return (retp);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate  *	_uaddr2taddr() translates a universal address back into a
3197c478bd9Sstevel@tonic-gate  *	netaddr structure.  Since the universal address is a string,
3207c478bd9Sstevel@tonic-gate  *	put that into the TLI buffer (making sure to change all \ddd
3217c478bd9Sstevel@tonic-gate  *	characters back and strip off the trailing \0 character).
3227c478bd9Sstevel@tonic-gate  */
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate /* ARGSUSED */
3257c478bd9Sstevel@tonic-gate struct netbuf *
_uaddr2taddr(struct netconfig * netconfigp,char * uaddr)3267c478bd9Sstevel@tonic-gate _uaddr2taddr(struct netconfig *netconfigp, char *uaddr)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate 	struct netbuf *retp;	/* the return structure			   */
3297c478bd9Sstevel@tonic-gate 	char *holdp;		/* holds the converted address		   */
3307c478bd9Sstevel@tonic-gate 	char *to;		/* traverses and populates the new address */
3317c478bd9Sstevel@tonic-gate 	char *from;		/* traverses the universal address	   */
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	holdp = malloc(strlen(uaddr) + 1);
3347c478bd9Sstevel@tonic-gate 	if (holdp == NULL) {
3357c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
3367c478bd9Sstevel@tonic-gate 		return (NULL);
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 	from = uaddr;
3397c478bd9Sstevel@tonic-gate 	to = holdp;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	while (*from) {
3427c478bd9Sstevel@tonic-gate 		if (*from == '\\') {
3437c478bd9Sstevel@tonic-gate 			if (*(from+1) == '\\') {
3447c478bd9Sstevel@tonic-gate 				*to = '\\';
3457c478bd9Sstevel@tonic-gate 				from += 2;
3467c478bd9Sstevel@tonic-gate 			} else {
3477c478bd9Sstevel@tonic-gate 				*to = ((*(from+1) - '0') << 6) +
3486935f61bSMarcel Telka 				    ((*(from+2) - '0') << 3) +
3496935f61bSMarcel Telka 				    (*(from+3) - '0');
3507c478bd9Sstevel@tonic-gate 				from += 4;
3517c478bd9Sstevel@tonic-gate 			}
3527c478bd9Sstevel@tonic-gate 		} else {
3537c478bd9Sstevel@tonic-gate 			*to = *from++;
3547c478bd9Sstevel@tonic-gate 		}
3557c478bd9Sstevel@tonic-gate 		to++;
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 	*to = '\0';
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	if ((retp = malloc(sizeof (struct netbuf))) == NULL) {
3607c478bd9Sstevel@tonic-gate 		free(holdp);
3617c478bd9Sstevel@tonic-gate 		_nderror = ND_NOMEM;
3627c478bd9Sstevel@tonic-gate 		return (NULL);
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 	retp->maxlen = retp->len = (int)(to - holdp);
3657c478bd9Sstevel@tonic-gate 	retp->buf = holdp;
3667c478bd9Sstevel@tonic-gate 	return (retp);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate  *	_netdir_options() is a "catch-all" routine that does
3717c478bd9Sstevel@tonic-gate  *	transport specific things.  The only thing that these
3727c478bd9Sstevel@tonic-gate  *	routines have to worry about is ND_MERGEADDR.
3737c478bd9Sstevel@tonic-gate  */
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /* ARGSUSED */
3767c478bd9Sstevel@tonic-gate int
_netdir_options(struct netconfig * netconfigp,int option,int fd,void * par)3777c478bd9Sstevel@tonic-gate _netdir_options(struct netconfig *netconfigp, int option, int fd, void *par)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 	struct nd_mergearg *argp;  /* the argument for mergeaddr */
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	switch (option) {
3827c478bd9Sstevel@tonic-gate 	case ND_MERGEADDR:
3837c478bd9Sstevel@tonic-gate 		/*
3847c478bd9Sstevel@tonic-gate 		 *	Translate the universal address into something that
3857c478bd9Sstevel@tonic-gate 		 *	makes sense to the caller.  This is a no-op in
3867c478bd9Sstevel@tonic-gate 		 *	loopback's case, so just return the universal address.
3877c478bd9Sstevel@tonic-gate 		 */
3887c478bd9Sstevel@tonic-gate 		argp = (struct nd_mergearg *)par;
3897c478bd9Sstevel@tonic-gate 		argp->m_uaddr = strdup(argp->s_uaddr);
390*9d4de077SMarcel Telka 		if (argp->m_uaddr == NULL) {
391*9d4de077SMarcel Telka 			_nderror = ND_NOMEM;
392*9d4de077SMarcel Telka 			return (-1);
393*9d4de077SMarcel Telka 		}
394*9d4de077SMarcel Telka 		return (0);
3957c478bd9Sstevel@tonic-gate 	default:
3967c478bd9Sstevel@tonic-gate 		_nderror = ND_NOCTRL;
3977c478bd9Sstevel@tonic-gate 		return (-1);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate  *	searchhost() looks for the specified token in the host file.
4037c478bd9Sstevel@tonic-gate  *	The "field" parameter signifies which field to compare the token
4047c478bd9Sstevel@tonic-gate  *	on, and returns all comma separated values associated with the token.
4057c478bd9Sstevel@tonic-gate  */
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate static int
searchhost(struct netconfig * netconfigp,char * token,int field,char * hostbuf)4087c478bd9Sstevel@tonic-gate searchhost(struct netconfig *netconfigp, char *token, int field, char *hostbuf)
4097c478bd9Sstevel@tonic-gate {
4107c478bd9Sstevel@tonic-gate 	char searchfile[MAXPATHLEN];  /* the name of file to be opened	    */
4117c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];	/* holds each line of the file		    */
4127c478bd9Sstevel@tonic-gate 	char *fileaddr;		/* the first token in each line		    */
4137c478bd9Sstevel@tonic-gate 	char *filehost;		/* the second token in each line	    */
4147c478bd9Sstevel@tonic-gate 	char *cmpstr;		/* the string to compare token to	    */
4157c478bd9Sstevel@tonic-gate 	char *retstr;		/* the string to return if compare succeeds */
4167c478bd9Sstevel@tonic-gate 	char *nexttok;		/* next token to process		    */
4177c478bd9Sstevel@tonic-gate 	FILE *fp;		/* the opened searchfile		    */
4187c478bd9Sstevel@tonic-gate 	int   nelements = 0;	/* total number of elements found	    */
4196935f61bSMarcel Telka 	struct utsname utsname;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/*
4226935f61bSMarcel Telka 	 *	Unless /etc/netconfig has been altered, the only transport that
4236935f61bSMarcel Telka 	 *	will use straddr.so is loopback.  In this case, we always
4246935f61bSMarcel Telka 	 *	return "localhost" if either our nodename, or "localhost", or
4256935f61bSMarcel Telka 	 *	some of special-case host names were passed, or we fail.
4267c478bd9Sstevel@tonic-gate 	 */
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	if ((strcmp(token, HOST_SELF_BIND) == 0) ||
4297c478bd9Sstevel@tonic-gate 	    (strcmp(token, HOST_SELF_CONNECT) == 0) ||
4307c478bd9Sstevel@tonic-gate 	    (strcmp(token, HOST_ANY) == 0) ||
4316935f61bSMarcel Telka 	    (strcmp(token, LOCALHOST) == 0) ||
4326935f61bSMarcel Telka 	    (uname(&utsname) >= 0 && strcmp(token, utsname.nodename) == 0)) {
4336935f61bSMarcel Telka 		(void) strcpy(hostbuf, LOCALHOST);
4347c478bd9Sstevel@tonic-gate 		return (1);
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	if (strcmp(netconfigp->nc_protofmly, NC_LOOPBACK) == 0)
4387c478bd9Sstevel@tonic-gate 		return (0);
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	/*
4417c478bd9Sstevel@tonic-gate 	 * 	We only get here if an administrator has modified
4427c478bd9Sstevel@tonic-gate 	 * 	/etc/netconfig to use straddr.so for a transport other than
4437c478bd9Sstevel@tonic-gate 	 * 	loopback (which is questionable but something we'll need to
4447c478bd9Sstevel@tonic-gate 	 * 	EOL at a later point in time).  In this case, we fallback to
4457c478bd9Sstevel@tonic-gate 	 * 	searching for the associated key in the appropriate hosts
4467c478bd9Sstevel@tonic-gate 	 * 	file (based on nc_netid).
4477c478bd9Sstevel@tonic-gate 	 */
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	(void) snprintf(searchfile, sizeof (searchfile), HOSTFILE,
4507c478bd9Sstevel@tonic-gate 	    netconfigp->nc_netid);
4517c478bd9Sstevel@tonic-gate 
452004388ebScasper 	fp = fopen(searchfile, "rF");
4537c478bd9Sstevel@tonic-gate 	if (fp == NULL)
4547c478bd9Sstevel@tonic-gate 		return (0);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	/*
4577c478bd9Sstevel@tonic-gate 	 *	Loop through the file looking for the tokens and creating
4587c478bd9Sstevel@tonic-gate 	 *	the list of strings to be returned.
4597c478bd9Sstevel@tonic-gate 	 */
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, fp) != NULL) {
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 		/*
4647c478bd9Sstevel@tonic-gate 		 *	Ignore comments and bad lines.
4657c478bd9Sstevel@tonic-gate 		 */
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 		fileaddr = strtok_r(buf, " \t\n", &nexttok);
4687c478bd9Sstevel@tonic-gate 		if (fileaddr == NULL || *fileaddr == '#')
4697c478bd9Sstevel@tonic-gate 			continue;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		if ((filehost = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
4727c478bd9Sstevel@tonic-gate 			continue;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 		/*
4757c478bd9Sstevel@tonic-gate 		 *	determine which to compare the token to, then
4767c478bd9Sstevel@tonic-gate 		 *	compare it, and if they match, add the return
4777c478bd9Sstevel@tonic-gate 		 *	string to the list.
4787c478bd9Sstevel@tonic-gate 		 */
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 		cmpstr = (field == FIELD1)? fileaddr : filehost;
4817c478bd9Sstevel@tonic-gate 		retstr = (field == FIELD1)? filehost : fileaddr;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 		if (strcmp(token, cmpstr) == 0) {
4847c478bd9Sstevel@tonic-gate 			nelements++;
4857c478bd9Sstevel@tonic-gate 			if (field == FIELD2) {
4867c478bd9Sstevel@tonic-gate 				/*
4877c478bd9Sstevel@tonic-gate 				 * called by _netdir_getbyname
4887c478bd9Sstevel@tonic-gate 				 */
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 				(void) strcpy(hostbuf, retstr);
4917c478bd9Sstevel@tonic-gate 				break;
4927c478bd9Sstevel@tonic-gate 			}
4937c478bd9Sstevel@tonic-gate 			if (nelements > 1) {
4947c478bd9Sstevel@tonic-gate 				/*
4957c478bd9Sstevel@tonic-gate 				 * Assuming that "," will never be a part
4967c478bd9Sstevel@tonic-gate 				 * of any host name.
4977c478bd9Sstevel@tonic-gate 				 */
4987c478bd9Sstevel@tonic-gate 				(void) strcat(hostbuf, ",");
4997c478bd9Sstevel@tonic-gate 			}
5007c478bd9Sstevel@tonic-gate 			(void) strcat(hostbuf, retstr);
5017c478bd9Sstevel@tonic-gate 		}
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
5057c478bd9Sstevel@tonic-gate 	return (nelements);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate  *	searchserv() looks for the specified token in the service file.
5107c478bd9Sstevel@tonic-gate  *	The "field" parameter signifies which field to compare the token
5117c478bd9Sstevel@tonic-gate  *	on, and returns the string associated with the token in servname.
5127c478bd9Sstevel@tonic-gate  */
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate static int
searchserv(struct netconfig * netconfigp,char * token,int field,char * servname)5157c478bd9Sstevel@tonic-gate searchserv(struct netconfig *netconfigp, char *token, int field, char *servname)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate 	char searchfile[MAXPATHLEN];  /* the name of file to be opened  */
5187c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];	/* buffer space for lines in file	*/
5197c478bd9Sstevel@tonic-gate 	char *fileservice;	/* the first token in each line		*/
5207c478bd9Sstevel@tonic-gate 	char *fileport;		/* the second token in each line	*/
5217c478bd9Sstevel@tonic-gate 	char *cmpstr;		/* the string to compare the token to	*/
5227c478bd9Sstevel@tonic-gate 	char *retstr;		/* temporarily hold token in line of file */
5237c478bd9Sstevel@tonic-gate 	char *nexttok;		/* next token to process		*/
5247c478bd9Sstevel@tonic-gate 	FILE *fp;		/* the opened searchfile		*/
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	(void) snprintf(searchfile, sizeof (searchfile), SERVICEFILE,
5277c478bd9Sstevel@tonic-gate 	    netconfigp->nc_netid);
5287c478bd9Sstevel@tonic-gate 
529004388ebScasper 	fp = fopen(searchfile, "rF");
5307c478bd9Sstevel@tonic-gate 	if (fp == NULL)
5317c478bd9Sstevel@tonic-gate 		return (0);
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	/*
5347c478bd9Sstevel@tonic-gate 	 *	Loop through the services file looking for the token.
5357c478bd9Sstevel@tonic-gate 	 */
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, fp) != NULL) {
5387c478bd9Sstevel@tonic-gate 		/*
5397c478bd9Sstevel@tonic-gate 		 *	If comment or bad line, continue.
5407c478bd9Sstevel@tonic-gate 		 */
5417c478bd9Sstevel@tonic-gate 		fileservice = strtok_r(buf, " \t\n", &nexttok);
5427c478bd9Sstevel@tonic-gate 		if (fileservice == NULL || *fileservice == '#')
5437c478bd9Sstevel@tonic-gate 			continue;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 		if ((fileport = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
5467c478bd9Sstevel@tonic-gate 			continue;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		cmpstr = (field == FIELD1)? fileservice : fileport;
5497c478bd9Sstevel@tonic-gate 		retstr = (field == FIELD1)? fileport : fileservice;
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 		if (strcmp(token, cmpstr) == 0) {
5527c478bd9Sstevel@tonic-gate 			(void) strcpy(servname, retstr);
5537c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
5547c478bd9Sstevel@tonic-gate 			return (1);
5557c478bd9Sstevel@tonic-gate 		}
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
5597c478bd9Sstevel@tonic-gate 	return (0);
5607c478bd9Sstevel@tonic-gate }
561