xref: /onnv-gate/usr/src/lib/nametoaddr/straddr/common/straddr.c (revision 1914:8a8c5f225b1b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*1914Scasper  * Common Development and Distribution License (the "License").
6*1914Scasper  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*1914Scasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	 All Rights Reserved 	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <ctype.h>
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <tiuser.h>
350Sstevel@tonic-gate #include <netdir.h>
360Sstevel@tonic-gate #include <netconfig.h>
370Sstevel@tonic-gate #include <sys/utsname.h>
380Sstevel@tonic-gate #include <sys/param.h>
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate #include <stdlib.h>
410Sstevel@tonic-gate #include <synch.h>
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate  *	The generic name to address mappings for any transport that
450Sstevel@tonic-gate  *	has strings for address (e.g., ISO Starlan).
460Sstevel@tonic-gate  *
470Sstevel@tonic-gate  *	Address in ISO Starlan consist of arbitrary strings of
480Sstevel@tonic-gate  *	characters.  Because of this, the following routines
490Sstevel@tonic-gate  *	create an "address" based on two strings, one gotten
500Sstevel@tonic-gate  *	from a "host" file and one gotten from a "services" file.
510Sstevel@tonic-gate  *	The two strings are catenated together (with a "." between
520Sstevel@tonic-gate  *	them).  The hosts file is /etc/net/starlan/hosts and
530Sstevel@tonic-gate  *	contain lines of the form:
540Sstevel@tonic-gate  *
550Sstevel@tonic-gate  *		arbitrary_string	machname
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  *	To make things simple, the "arbitrary string" should be the
580Sstevel@tonic-gate  *	machine name.
590Sstevel@tonic-gate  *
600Sstevel@tonic-gate  *	The services file is /etc/net/starlan/services and has lines
610Sstevel@tonic-gate  *	of the form:
620Sstevel@tonic-gate  *
630Sstevel@tonic-gate  *		service_name	arbitrary_string
640Sstevel@tonic-gate  *
650Sstevel@tonic-gate  *	Again, to make things easer, the "arbitrary name" should be the
660Sstevel@tonic-gate  *	service name.
670Sstevel@tonic-gate  */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate #define	HOSTFILE	"/etc/net/%s/hosts"
700Sstevel@tonic-gate #define	SERVICEFILE	"/etc/net/%s/services"
710Sstevel@tonic-gate #define	FIELD1		1
720Sstevel@tonic-gate #define	FIELD2		2
730Sstevel@tonic-gate 
740Sstevel@tonic-gate static int searchhost(struct netconfig *, char *, int, char *);
750Sstevel@tonic-gate static int searchserv(struct netconfig *, char *, int, char *);
760Sstevel@tonic-gate static const char *nodename(void);
770Sstevel@tonic-gate 
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate  *	_netdir_getbyname() returns all of the addresses for
800Sstevel@tonic-gate  *	a specified host and service.
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate 
830Sstevel@tonic-gate struct nd_addrlist *
_netdir_getbyname(struct netconfig * netconfigp,struct nd_hostserv * nd_hostservp)840Sstevel@tonic-gate _netdir_getbyname(struct netconfig *netconfigp,
850Sstevel@tonic-gate     struct nd_hostserv *nd_hostservp)
860Sstevel@tonic-gate {
870Sstevel@tonic-gate 	char   fulladdr[BUFSIZ];   /* holds the full address string	   */
880Sstevel@tonic-gate 	struct nd_addrlist *retp;  /* the return structure		   */
890Sstevel@tonic-gate 	struct netbuf *netbufp;    /* indexes through the addresses	   */
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	/*
920Sstevel@tonic-gate 	 *	HOST_BROADCAST is not supported.
930Sstevel@tonic-gate 	 */
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	if (strcmp(nd_hostservp->h_host, HOST_BROADCAST) == 0) {
960Sstevel@tonic-gate 		_nderror = ND_NOHOST;
970Sstevel@tonic-gate 		return (NULL);
980Sstevel@tonic-gate 	}
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	if (searchhost(netconfigp, nd_hostservp->h_host, FIELD2,
1010Sstevel@tonic-gate 	    fulladdr) == 0) {
1020Sstevel@tonic-gate 		_nderror = ND_NOHOST;
1030Sstevel@tonic-gate 		return (NULL);
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	/*
1070Sstevel@tonic-gate 	 *	Now simply fill in the address by forming strings of the
1080Sstevel@tonic-gate 	 *	form "string_from_hosts.string_from_services"
1090Sstevel@tonic-gate 	 */
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	if (nd_hostservp->h_serv &&
1120Sstevel@tonic-gate 	    (strcmp(nd_hostservp->h_serv, "rpcbind") == 0)) {
1130Sstevel@tonic-gate 		(void) strcat(fulladdr, ".");
1140Sstevel@tonic-gate 		(void) strcat(fulladdr, "rpc");	/* hard coded */
1150Sstevel@tonic-gate 	} else {
1160Sstevel@tonic-gate 		/*
1170Sstevel@tonic-gate 		 *	Get the address from the services file
1180Sstevel@tonic-gate 		 */
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 		if (nd_hostservp->h_serv && (nd_hostservp->h_serv[0] != '\0')) {
1210Sstevel@tonic-gate 			(void) strcat(fulladdr, ".");
1220Sstevel@tonic-gate 			if (searchserv(netconfigp, nd_hostservp->h_serv, FIELD1,
1230Sstevel@tonic-gate 			    fulladdr + strlen(fulladdr)) == 0) {
1240Sstevel@tonic-gate 				_nderror = ND_NOSERV;
1250Sstevel@tonic-gate 				return (NULL);
1260Sstevel@tonic-gate 			}
1270Sstevel@tonic-gate 		}
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	if ((retp = malloc(sizeof (struct nd_addrlist))) == NULL) {
1310Sstevel@tonic-gate 		_nderror = ND_NOMEM;
1320Sstevel@tonic-gate 		return (NULL);
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	/*
1360Sstevel@tonic-gate 	 *	We do not worry about multiple addresses here.  Loopbacks
1370Sstevel@tonic-gate 	 *	have only one interface.
1380Sstevel@tonic-gate 	 */
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	retp->n_cnt = 1;
1410Sstevel@tonic-gate 	if ((retp->n_addrs = malloc(sizeof (struct netbuf))) == NULL) {
1420Sstevel@tonic-gate 		free(retp);
1430Sstevel@tonic-gate 		_nderror = ND_NOMEM;
1440Sstevel@tonic-gate 		return (NULL);
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	netbufp = retp->n_addrs;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/*
1500Sstevel@tonic-gate 	 *	Don't include the terminating NULL character in the
1510Sstevel@tonic-gate 	 *	length.
1520Sstevel@tonic-gate 	 */
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	netbufp->len = netbufp->maxlen = (int)strlen(fulladdr);
1550Sstevel@tonic-gate 	if ((netbufp->buf = strdup(fulladdr)) == NULL) {
1560Sstevel@tonic-gate 		free(netbufp);
1570Sstevel@tonic-gate 		free(retp);
1580Sstevel@tonic-gate 		_nderror = ND_NOMEM;
1590Sstevel@tonic-gate 		return (NULL);
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate 	_nderror = ND_OK;
1620Sstevel@tonic-gate 	return (retp);
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate  *	_netdir_getbyaddr() takes an address (hopefully obtained from
1670Sstevel@tonic-gate  *	someone doing a _netdir_getbyname()) and returns all hosts with
1680Sstevel@tonic-gate  *	that address.
1690Sstevel@tonic-gate  */
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate struct nd_hostservlist *
_netdir_getbyaddr(struct netconfig * netconfigp,struct netbuf * netbufp)1720Sstevel@tonic-gate _netdir_getbyaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate 	char   fulladdr[BUFSIZ];	  /* a copy of the address string   */
1750Sstevel@tonic-gate 	char   servbuf[BUFSIZ];		  /* a buffer for service string    */
1760Sstevel@tonic-gate 	char   hostbuf[BUFSIZ];		  /* points to list of host names   */
1770Sstevel@tonic-gate 	char   *hostname;		  /* the "first" path of the string */
1780Sstevel@tonic-gate 	char   *servname;		  /* the "second" part of string    */
1790Sstevel@tonic-gate 	struct nd_hostservlist *retp;	  /* the return structure	    */
1800Sstevel@tonic-gate 	char   *serv;			  /* resultant service name obtained */
1810Sstevel@tonic-gate 	int    nhost;			  /* the number of hosts in hostpp  */
1820Sstevel@tonic-gate 	struct nd_hostserv *nd_hostservp; /* traverses the host structures  */
1830Sstevel@tonic-gate 	char   *nexttok;		  /* next token to process	    */
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	/*
1860Sstevel@tonic-gate 	 *	Separate the two parts of the address string.
1870Sstevel@tonic-gate 	 */
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	(void) strlcpy(fulladdr, netbufp->buf, sizeof (fulladdr));
1900Sstevel@tonic-gate 	hostname = strtok_r(fulladdr, ".", &nexttok);
1910Sstevel@tonic-gate 	if (hostname == NULL) {
1920Sstevel@tonic-gate 		_nderror = ND_NOHOST;
1930Sstevel@tonic-gate 		return (NULL);
1940Sstevel@tonic-gate 	}
1950Sstevel@tonic-gate 	servname = strtok_r(NULL, " \n\t", &nexttok);
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	/*
1980Sstevel@tonic-gate 	 *	Search for all the hosts associated with the
1990Sstevel@tonic-gate 	 *	first part of the address string.
2000Sstevel@tonic-gate 	 */
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	nhost = searchhost(netconfigp, hostname, FIELD1, hostbuf);
2030Sstevel@tonic-gate 	if (nhost == 0) {
2040Sstevel@tonic-gate 		_nderror = ND_NOHOST;
2050Sstevel@tonic-gate 		return (NULL);
2060Sstevel@tonic-gate 	}
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	/*
2090Sstevel@tonic-gate 	 *	Search for the service associated with the second
2100Sstevel@tonic-gate 	 *	path of the address string.
2110Sstevel@tonic-gate 	 */
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	if (servname == NULL) {
2140Sstevel@tonic-gate 		_nderror = ND_NOSERV;
2150Sstevel@tonic-gate 		return (NULL);
2160Sstevel@tonic-gate 	}
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	servbuf[0] = '\0';
2190Sstevel@tonic-gate 	serv = servbuf;
2200Sstevel@tonic-gate 	if (searchserv(netconfigp, servname, FIELD2, servbuf) == 0) {
2210Sstevel@tonic-gate 		serv = _taddr2uaddr(netconfigp, netbufp);
2220Sstevel@tonic-gate 		(void) strcpy(servbuf, serv);
2230Sstevel@tonic-gate 		free(serv);
2240Sstevel@tonic-gate 		serv = servbuf;
2250Sstevel@tonic-gate 		while (*serv != '.')
2260Sstevel@tonic-gate 			serv++;
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	/*
2300Sstevel@tonic-gate 	 *	Allocate space to hold the return structure, set the number
2310Sstevel@tonic-gate 	 *	of hosts, and allocate space to hold them.
2320Sstevel@tonic-gate 	 */
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	if ((retp = malloc(sizeof (struct nd_hostservlist))) == NULL) {
2350Sstevel@tonic-gate 		_nderror = ND_NOMEM;
2360Sstevel@tonic-gate 		return (NULL);
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	retp->h_cnt = nhost;
2400Sstevel@tonic-gate 	retp->h_hostservs = calloc(nhost, sizeof (struct nd_hostserv));
2410Sstevel@tonic-gate 	if (retp->h_hostservs == NULL) {
2420Sstevel@tonic-gate 		free(retp);
2430Sstevel@tonic-gate 		_nderror = ND_NOMEM;
2440Sstevel@tonic-gate 		return (NULL);
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	/*
2480Sstevel@tonic-gate 	 *	Loop through the host structues and fill them in with
2490Sstevel@tonic-gate 	 *	each host name (and service name).
2500Sstevel@tonic-gate 	 */
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	nd_hostservp = retp->h_hostservs;
2530Sstevel@tonic-gate 	hostname = strtok_r(hostbuf, ",", &nexttok);
2540Sstevel@tonic-gate 	while (hostname && nhost--) {
2550Sstevel@tonic-gate 		if (((nd_hostservp->h_host = strdup(hostname)) == NULL) ||
2560Sstevel@tonic-gate 		    ((nd_hostservp->h_serv = strdup(serv)) == NULL)) {
2570Sstevel@tonic-gate 			netdir_free(retp, ND_HOSTSERVLIST);
2580Sstevel@tonic-gate 			_nderror = ND_NOMEM;
2590Sstevel@tonic-gate 			return (NULL);
2600Sstevel@tonic-gate 		}
2610Sstevel@tonic-gate 		nd_hostservp++;
2620Sstevel@tonic-gate 		hostname = strtok_r(NULL, ",", &nexttok);
2630Sstevel@tonic-gate 	}
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	_nderror = ND_OK;
2660Sstevel@tonic-gate 	return (retp);
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate /*
2700Sstevel@tonic-gate  *	_taddr2uaddr() translates a address into a "universal" address.
2710Sstevel@tonic-gate  *	Since the address is a string, simply return the string as the
2720Sstevel@tonic-gate  *	universal address (but replace all non-printable characters with
2730Sstevel@tonic-gate  *	the \ddd form, where ddd is three octal digits).  The '\n' character
2740Sstevel@tonic-gate  *	is also replace by \ddd and the '\' character is placed as two
2750Sstevel@tonic-gate  *	'\' characters.
2760Sstevel@tonic-gate  */
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate /* ARGSUSED */
2790Sstevel@tonic-gate char *
_taddr2uaddr(struct netconfig * netconfigp,struct netbuf * netbufp)2800Sstevel@tonic-gate _taddr2uaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate 	char *retp;	/* pointer the return string			*/
2830Sstevel@tonic-gate 	char *to;	/* traverses and populates the return string	*/
2840Sstevel@tonic-gate 	char *from;	/* traverses the string to be converted		*/
2850Sstevel@tonic-gate 	int i;		/* indexes through the given string		*/
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	/*
2880Sstevel@tonic-gate 	 * BUFSIZ is perhaps too big for this one and there is a better
2890Sstevel@tonic-gate 	 * way to optimize it, but for now we will just assume BUFSIZ
2900Sstevel@tonic-gate 	 */
2910Sstevel@tonic-gate 	if ((retp = malloc(BUFSIZ)) == NULL) {
2920Sstevel@tonic-gate 		_nderror = ND_NOMEM;
2930Sstevel@tonic-gate 		return (NULL);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 	to = retp;
2960Sstevel@tonic-gate 	from = netbufp->buf;
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	for (i = 0; i < netbufp->len; i++) {
2990Sstevel@tonic-gate 		if (*from == '\\') {
3000Sstevel@tonic-gate 			*to++ = '\\';
3010Sstevel@tonic-gate 			*to++ = '\\';
3020Sstevel@tonic-gate 		} else {
3030Sstevel@tonic-gate 			if (*from == '\n' || !isprint((unsigned char)*from)) {
3040Sstevel@tonic-gate 				(void) sprintf(to, "\\%.3o", *from & 0xff);
3050Sstevel@tonic-gate 				to += 4;
3060Sstevel@tonic-gate 			} else {
3070Sstevel@tonic-gate 				*to++ = *from;
3080Sstevel@tonic-gate 			}
3090Sstevel@tonic-gate 		}
3100Sstevel@tonic-gate 		from++;
3110Sstevel@tonic-gate 	}
3120Sstevel@tonic-gate 	*to = '\0';
3130Sstevel@tonic-gate 	return (retp);
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate /*
3170Sstevel@tonic-gate  *	_uaddr2taddr() translates a universal address back into a
3180Sstevel@tonic-gate  *	netaddr structure.  Since the universal address is a string,
3190Sstevel@tonic-gate  *	put that into the TLI buffer (making sure to change all \ddd
3200Sstevel@tonic-gate  *	characters back and strip off the trailing \0 character).
3210Sstevel@tonic-gate  */
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate /* ARGSUSED */
3240Sstevel@tonic-gate struct netbuf *
_uaddr2taddr(struct netconfig * netconfigp,char * uaddr)3250Sstevel@tonic-gate _uaddr2taddr(struct netconfig *netconfigp, char *uaddr)
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate 	struct netbuf *retp;	/* the return structure			   */
3280Sstevel@tonic-gate 	char *holdp;		/* holds the converted address		   */
3290Sstevel@tonic-gate 	char *to;		/* traverses and populates the new address */
3300Sstevel@tonic-gate 	char *from;		/* traverses the universal address	   */
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	holdp = malloc(strlen(uaddr) + 1);
3330Sstevel@tonic-gate 	if (holdp == NULL) {
3340Sstevel@tonic-gate 		_nderror = ND_NOMEM;
3350Sstevel@tonic-gate 		return (NULL);
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate 	from = uaddr;
3380Sstevel@tonic-gate 	to = holdp;
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	while (*from) {
3410Sstevel@tonic-gate 		if (*from == '\\') {
3420Sstevel@tonic-gate 			if (*(from+1) == '\\') {
3430Sstevel@tonic-gate 				*to = '\\';
3440Sstevel@tonic-gate 				from += 2;
3450Sstevel@tonic-gate 			} else {
3460Sstevel@tonic-gate 				*to = ((*(from+1) - '0') << 6) +
3470Sstevel@tonic-gate 					((*(from+2) - '0') << 3) +
3480Sstevel@tonic-gate 					(*(from+3) - '0');
3490Sstevel@tonic-gate 				from += 4;
3500Sstevel@tonic-gate 			}
3510Sstevel@tonic-gate 		} else {
3520Sstevel@tonic-gate 			*to = *from++;
3530Sstevel@tonic-gate 		}
3540Sstevel@tonic-gate 		to++;
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate 	*to = '\0';
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	if ((retp = malloc(sizeof (struct netbuf))) == NULL) {
3590Sstevel@tonic-gate 		free(holdp);
3600Sstevel@tonic-gate 		_nderror = ND_NOMEM;
3610Sstevel@tonic-gate 		return (NULL);
3620Sstevel@tonic-gate 	}
3630Sstevel@tonic-gate 	retp->maxlen = retp->len = (int)(to - holdp);
3640Sstevel@tonic-gate 	retp->buf = holdp;
3650Sstevel@tonic-gate 	return (retp);
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate  *	_netdir_options() is a "catch-all" routine that does
3700Sstevel@tonic-gate  *	transport specific things.  The only thing that these
3710Sstevel@tonic-gate  *	routines have to worry about is ND_MERGEADDR.
3720Sstevel@tonic-gate  */
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate /* ARGSUSED */
3750Sstevel@tonic-gate int
_netdir_options(struct netconfig * netconfigp,int option,int fd,void * par)3760Sstevel@tonic-gate _netdir_options(struct netconfig *netconfigp, int option, int fd, void *par)
3770Sstevel@tonic-gate {
3780Sstevel@tonic-gate 	struct nd_mergearg *argp;  /* the argument for mergeaddr */
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	switch (option) {
3810Sstevel@tonic-gate 	case ND_MERGEADDR:
3820Sstevel@tonic-gate 		/*
3830Sstevel@tonic-gate 		 *	Translate the universal address into something that
3840Sstevel@tonic-gate 		 *	makes sense to the caller.  This is a no-op in
3850Sstevel@tonic-gate 		 *	loopback's case, so just return the universal address.
3860Sstevel@tonic-gate 		 */
3870Sstevel@tonic-gate 		argp = (struct nd_mergearg *)par;
3880Sstevel@tonic-gate 		argp->m_uaddr = strdup(argp->s_uaddr);
3890Sstevel@tonic-gate 		return (argp->m_uaddr == NULL? -1 : 0);
3900Sstevel@tonic-gate 	default:
3910Sstevel@tonic-gate 		_nderror = ND_NOCTRL;
3920Sstevel@tonic-gate 		return (-1);
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate /*
3970Sstevel@tonic-gate  *	searchhost() looks for the specified token in the host file.
3980Sstevel@tonic-gate  *	The "field" parameter signifies which field to compare the token
3990Sstevel@tonic-gate  *	on, and returns all comma separated values associated with the token.
4000Sstevel@tonic-gate  */
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate static int
searchhost(struct netconfig * netconfigp,char * token,int field,char * hostbuf)4030Sstevel@tonic-gate searchhost(struct netconfig *netconfigp, char *token, int field, char *hostbuf)
4040Sstevel@tonic-gate {
4050Sstevel@tonic-gate 	char searchfile[MAXPATHLEN];  /* the name of file to be opened	    */
4060Sstevel@tonic-gate 	char buf[BUFSIZ];	/* holds each line of the file		    */
4070Sstevel@tonic-gate 	char *fileaddr;		/* the first token in each line		    */
4080Sstevel@tonic-gate 	char *filehost;		/* the second token in each line	    */
4090Sstevel@tonic-gate 	char *cmpstr;		/* the string to compare token to	    */
4100Sstevel@tonic-gate 	char *retstr;		/* the string to return if compare succeeds */
4110Sstevel@tonic-gate 	char *nexttok;		/* next token to process		    */
4120Sstevel@tonic-gate 	FILE *fp;		/* the opened searchfile		    */
4130Sstevel@tonic-gate 	int   nelements = 0;	/* total number of elements found	    */
4140Sstevel@tonic-gate 	const char *myname;	/* my own nodename			    */
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	myname = nodename();
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	/*
4190Sstevel@tonic-gate 	 *	Unless /etc/netconfig has been altered, the only transport
4200Sstevel@tonic-gate 	 *	that will use straddr.so is loopback.  In this case, we
4210Sstevel@tonic-gate 	 *	always return our nodename if that's what we were passed,
4220Sstevel@tonic-gate 	 *	or we fail (note that we'd like to return a constant like
4230Sstevel@tonic-gate 	 *	"localhost" so that changes to the machine name won't cause
4240Sstevel@tonic-gate 	 *	problems, but things like autofs actually assume that we're
4250Sstevel@tonic-gate 	 *	using our nodename).
4260Sstevel@tonic-gate 	 */
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	if ((strcmp(token, HOST_SELF_BIND) == 0) ||
4290Sstevel@tonic-gate 	    (strcmp(token, HOST_SELF_CONNECT) == 0) ||
4300Sstevel@tonic-gate 	    (strcmp(token, HOST_ANY) == 0) ||
4310Sstevel@tonic-gate 	    (myname != NULL && (strcmp(token, myname) == 0))) {
4320Sstevel@tonic-gate 		if (myname == NULL)
4330Sstevel@tonic-gate 			return (0);
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 		(void) strcpy(hostbuf, myname);
4360Sstevel@tonic-gate 		return (1);
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	if (strcmp(netconfigp->nc_protofmly, NC_LOOPBACK) == 0)
4400Sstevel@tonic-gate 		return (0);
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	/*
4430Sstevel@tonic-gate 	 * 	We only get here if an administrator has modified
4440Sstevel@tonic-gate 	 * 	/etc/netconfig to use straddr.so for a transport other than
4450Sstevel@tonic-gate 	 * 	loopback (which is questionable but something we'll need to
4460Sstevel@tonic-gate 	 * 	EOL at a later point in time).  In this case, we fallback to
4470Sstevel@tonic-gate 	 * 	searching for the associated key in the appropriate hosts
4480Sstevel@tonic-gate 	 * 	file (based on nc_netid).
4490Sstevel@tonic-gate 	 */
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	(void) snprintf(searchfile, sizeof (searchfile), HOSTFILE,
4520Sstevel@tonic-gate 	    netconfigp->nc_netid);
4530Sstevel@tonic-gate 
454*1914Scasper 	fp = fopen(searchfile, "rF");
4550Sstevel@tonic-gate 	if (fp == NULL)
4560Sstevel@tonic-gate 		return (0);
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	/*
4590Sstevel@tonic-gate 	 *	Loop through the file looking for the tokens and creating
4600Sstevel@tonic-gate 	 *	the list of strings to be returned.
4610Sstevel@tonic-gate 	 */
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, fp) != NULL) {
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 		/*
4660Sstevel@tonic-gate 		 *	Ignore comments and bad lines.
4670Sstevel@tonic-gate 		 */
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 		fileaddr = strtok_r(buf, " \t\n", &nexttok);
4700Sstevel@tonic-gate 		if (fileaddr == NULL || *fileaddr == '#')
4710Sstevel@tonic-gate 			continue;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 		if ((filehost = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
4740Sstevel@tonic-gate 			continue;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 		/*
4770Sstevel@tonic-gate 		 *	determine which to compare the token to, then
4780Sstevel@tonic-gate 		 *	compare it, and if they match, add the return
4790Sstevel@tonic-gate 		 *	string to the list.
4800Sstevel@tonic-gate 		 */
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 		cmpstr = (field == FIELD1)? fileaddr : filehost;
4830Sstevel@tonic-gate 		retstr = (field == FIELD1)? filehost : fileaddr;
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 		if (strcmp(token, cmpstr) == 0) {
4860Sstevel@tonic-gate 			nelements++;
4870Sstevel@tonic-gate 			if (field == FIELD2) {
4880Sstevel@tonic-gate 				/*
4890Sstevel@tonic-gate 				 * called by _netdir_getbyname
4900Sstevel@tonic-gate 				 */
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 				(void) strcpy(hostbuf, retstr);
4930Sstevel@tonic-gate 				break;
4940Sstevel@tonic-gate 			}
4950Sstevel@tonic-gate 			if (nelements > 1) {
4960Sstevel@tonic-gate 				/*
4970Sstevel@tonic-gate 				 * Assuming that "," will never be a part
4980Sstevel@tonic-gate 				 * of any host name.
4990Sstevel@tonic-gate 				 */
5000Sstevel@tonic-gate 				(void) strcat(hostbuf, ",");
5010Sstevel@tonic-gate 			}
5020Sstevel@tonic-gate 			(void) strcat(hostbuf, retstr);
5030Sstevel@tonic-gate 		}
5040Sstevel@tonic-gate 	}
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	(void) fclose(fp);
5070Sstevel@tonic-gate 	return (nelements);
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate  *	searchserv() looks for the specified token in the service file.
5120Sstevel@tonic-gate  *	The "field" parameter signifies which field to compare the token
5130Sstevel@tonic-gate  *	on, and returns the string associated with the token in servname.
5140Sstevel@tonic-gate  */
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate static int
searchserv(struct netconfig * netconfigp,char * token,int field,char * servname)5170Sstevel@tonic-gate searchserv(struct netconfig *netconfigp, char *token, int field, char *servname)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate 	char searchfile[MAXPATHLEN];  /* the name of file to be opened  */
5200Sstevel@tonic-gate 	char buf[BUFSIZ];	/* buffer space for lines in file	*/
5210Sstevel@tonic-gate 	char *fileservice;	/* the first token in each line		*/
5220Sstevel@tonic-gate 	char *fileport;		/* the second token in each line	*/
5230Sstevel@tonic-gate 	char *cmpstr;		/* the string to compare the token to	*/
5240Sstevel@tonic-gate 	char *retstr;		/* temporarily hold token in line of file */
5250Sstevel@tonic-gate 	char *nexttok;		/* next token to process		*/
5260Sstevel@tonic-gate 	FILE *fp;		/* the opened searchfile		*/
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 	(void) snprintf(searchfile, sizeof (searchfile), SERVICEFILE,
5290Sstevel@tonic-gate 	    netconfigp->nc_netid);
5300Sstevel@tonic-gate 
531*1914Scasper 	fp = fopen(searchfile, "rF");
5320Sstevel@tonic-gate 	if (fp == NULL)
5330Sstevel@tonic-gate 		return (0);
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	/*
5360Sstevel@tonic-gate 	 *	Loop through the services file looking for the token.
5370Sstevel@tonic-gate 	 */
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, fp) != NULL) {
5400Sstevel@tonic-gate 		/*
5410Sstevel@tonic-gate 		 *	If comment or bad line, continue.
5420Sstevel@tonic-gate 		 */
5430Sstevel@tonic-gate 		fileservice = strtok_r(buf, " \t\n", &nexttok);
5440Sstevel@tonic-gate 		if (fileservice == NULL || *fileservice == '#')
5450Sstevel@tonic-gate 			continue;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 		if ((fileport = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
5480Sstevel@tonic-gate 			continue;
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 		cmpstr = (field == FIELD1)? fileservice : fileport;
5510Sstevel@tonic-gate 		retstr = (field == FIELD1)? fileport : fileservice;
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 		if (strcmp(token, cmpstr) == 0) {
5540Sstevel@tonic-gate 			(void) strcpy(servname, retstr);
5550Sstevel@tonic-gate 			(void) fclose(fp);
5560Sstevel@tonic-gate 			return (1);
5570Sstevel@tonic-gate 		}
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	(void) fclose(fp);
5610Sstevel@tonic-gate 	return (0);
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate static const char *
nodename(void)5650Sstevel@tonic-gate nodename(void)
5660Sstevel@tonic-gate {
5670Sstevel@tonic-gate 	static mutex_t	nodename_lock = DEFAULTMUTEX;
5680Sstevel@tonic-gate 	static const char *myname;
5690Sstevel@tonic-gate 	struct utsname utsname;
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 	(void) mutex_lock(&nodename_lock);
5720Sstevel@tonic-gate 	if (myname != NULL) {
5730Sstevel@tonic-gate 		(void) mutex_unlock(&nodename_lock);
5740Sstevel@tonic-gate 		return (myname);
5750Sstevel@tonic-gate 	}
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	if (uname(&utsname) == -1) {
5780Sstevel@tonic-gate 		(void) mutex_unlock(&nodename_lock);
5790Sstevel@tonic-gate 		_nderror = ND_SYSTEM;
5800Sstevel@tonic-gate 		return (NULL);
5810Sstevel@tonic-gate 	}
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	myname = strdup(utsname.nodename);
5840Sstevel@tonic-gate 	if (myname == NULL)
5850Sstevel@tonic-gate 		_nderror = ND_NOMEM;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	(void) mutex_unlock(&nodename_lock);
5880Sstevel@tonic-gate 	return (myname);
5890Sstevel@tonic-gate }
590