rcmd.c revision 9978
11573Srgrimes/*
21573Srgrimes * Copyright (c) 1983, 1993, 1994
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 3. All advertising materials mentioning features or use of this software
141573Srgrimes *    must display the following acknowledgement:
151573Srgrimes *	This product includes software developed by the University of
161573Srgrimes *	California, Berkeley and its contributors.
171573Srgrimes * 4. Neither the name of the University nor the names of its contributors
181573Srgrimes *    may be used to endorse or promote products derived from this software
191573Srgrimes *    without specific prior written permission.
201573Srgrimes *
211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311573Srgrimes * SUCH DAMAGE.
321573Srgrimes */
331573Srgrimes
341573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
351573Srgrimesstatic char sccsid[] = "@(#)rcmd.c	8.3 (Berkeley) 3/26/94";
361573Srgrimes#endif /* LIBC_SCCS and not lint */
371573Srgrimes
381573Srgrimes#include <sys/param.h>
391573Srgrimes#include <sys/socket.h>
401573Srgrimes#include <sys/stat.h>
411573Srgrimes
421573Srgrimes#include <netinet/in.h>
431573Srgrimes#include <arpa/inet.h>
441573Srgrimes
451573Srgrimes#include <signal.h>
461573Srgrimes#include <fcntl.h>
471573Srgrimes#include <netdb.h>
481573Srgrimes#include <unistd.h>
491573Srgrimes#include <pwd.h>
501573Srgrimes#include <errno.h>
511573Srgrimes#include <stdio.h>
521573Srgrimes#include <ctype.h>
531573Srgrimes#include <string.h>
549978Swpaul#ifdef YP
559978Swpaul#include <rpc/rpc.h>
569978Swpaul#include <rpcsvc/yp_prot.h>
579978Swpaul#include <rpcsvc/ypclnt.h>
589978Swpaul#endif
591573Srgrimes
602592Scsgr#define max(a, b)	((a > b) ? a : b)
612592Scsgr
621573Srgrimesint	__ivaliduser __P((FILE *, u_long, const char *, const char *));
631573Srgrimesstatic int __icheckhost __P((u_long, char *));
641573Srgrimes
651573Srgrimesint
661573Srgrimesrcmd(ahost, rport, locuser, remuser, cmd, fd2p)
671573Srgrimes	char **ahost;
681573Srgrimes	u_short rport;
691573Srgrimes	const char *locuser, *remuser, *cmd;
701573Srgrimes	int *fd2p;
711573Srgrimes{
721573Srgrimes	struct hostent *hp;
731573Srgrimes	struct sockaddr_in sin, from;
741573Srgrimes	fd_set reads;
751573Srgrimes	long oldmask;
761573Srgrimes	pid_t pid;
771573Srgrimes	int s, lport, timo;
781573Srgrimes	char c;
791573Srgrimes
801573Srgrimes	pid = getpid();
811573Srgrimes	hp = gethostbyname(*ahost);
821573Srgrimes	if (hp == NULL) {
831573Srgrimes		herror(*ahost);
841573Srgrimes		return (-1);
851573Srgrimes	}
861573Srgrimes	*ahost = hp->h_name;
871573Srgrimes	oldmask = sigblock(sigmask(SIGURG));
881573Srgrimes	for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
891573Srgrimes		s = rresvport(&lport);
901573Srgrimes		if (s < 0) {
911573Srgrimes			if (errno == EAGAIN)
921573Srgrimes				(void)fprintf(stderr,
931573Srgrimes				    "rcmd: socket: All ports in use\n");
941573Srgrimes			else
951573Srgrimes				(void)fprintf(stderr, "rcmd: socket: %s\n",
961573Srgrimes				    strerror(errno));
971573Srgrimes			sigsetmask(oldmask);
981573Srgrimes			return (-1);
991573Srgrimes		}
1001573Srgrimes		fcntl(s, F_SETOWN, pid);
1011573Srgrimes		sin.sin_family = hp->h_addrtype;
1021573Srgrimes		bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
1031573Srgrimes		sin.sin_port = rport;
1041573Srgrimes		if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
1051573Srgrimes			break;
1061573Srgrimes		(void)close(s);
1071573Srgrimes		if (errno == EADDRINUSE) {
1081573Srgrimes			lport--;
1091573Srgrimes			continue;
1101573Srgrimes		}
1111573Srgrimes		if (errno == ECONNREFUSED && timo <= 16) {
1121573Srgrimes			(void)sleep(timo);
1131573Srgrimes			timo *= 2;
1141573Srgrimes			continue;
1151573Srgrimes		}
1161573Srgrimes		if (hp->h_addr_list[1] != NULL) {
1171573Srgrimes			int oerrno = errno;
1181573Srgrimes
1191573Srgrimes			(void)fprintf(stderr, "connect to address %s: ",
1201573Srgrimes			    inet_ntoa(sin.sin_addr));
1211573Srgrimes			errno = oerrno;
1221573Srgrimes			perror(0);
1231573Srgrimes			hp->h_addr_list++;
1241573Srgrimes			bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
1251573Srgrimes			(void)fprintf(stderr, "Trying %s...\n",
1261573Srgrimes			    inet_ntoa(sin.sin_addr));
1271573Srgrimes			continue;
1281573Srgrimes		}
1291573Srgrimes		(void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno));
1301573Srgrimes		sigsetmask(oldmask);
1311573Srgrimes		return (-1);
1321573Srgrimes	}
1331573Srgrimes	lport--;
1341573Srgrimes	if (fd2p == 0) {
1351573Srgrimes		write(s, "", 1);
1361573Srgrimes		lport = 0;
1371573Srgrimes	} else {
1381573Srgrimes		char num[8];
1391573Srgrimes		int s2 = rresvport(&lport), s3;
1401573Srgrimes		int len = sizeof(from);
1412592Scsgr		int nfds;
1421573Srgrimes
1431573Srgrimes		if (s2 < 0)
1441573Srgrimes			goto bad;
1451573Srgrimes		listen(s2, 1);
1461573Srgrimes		(void)snprintf(num, sizeof(num), "%d", lport);
1471573Srgrimes		if (write(s, num, strlen(num)+1) != strlen(num)+1) {
1481573Srgrimes			(void)fprintf(stderr,
1491573Srgrimes			    "rcmd: write (setting up stderr): %s\n",
1501573Srgrimes			    strerror(errno));
1511573Srgrimes			(void)close(s2);
1521573Srgrimes			goto bad;
1531573Srgrimes		}
1542592Scsgr		nfds = max(s, s2)+1;
1552592Scsgr		if(nfds > FD_SETSIZE) {
1562592Scsgr			fprintf(stderr, "rcmd: too many files\n");
1572592Scsgr			(void)close(s2);
1582592Scsgr			goto bad;
1592592Scsgr		}
1601573Srgrimes		FD_ZERO(&reads);
1611573Srgrimes		FD_SET(s, &reads);
1621573Srgrimes		FD_SET(s2, &reads);
1631573Srgrimes		errno = 0;
1642592Scsgr		if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
1651573Srgrimes			if (errno != 0)
1661573Srgrimes				(void)fprintf(stderr,
1671573Srgrimes				    "rcmd: select (setting up stderr): %s\n",
1681573Srgrimes				    strerror(errno));
1691573Srgrimes			else
1701573Srgrimes				(void)fprintf(stderr,
1711573Srgrimes				"select: protocol failure in circuit setup\n");
1721573Srgrimes			(void)close(s2);
1731573Srgrimes			goto bad;
1741573Srgrimes		}
1751573Srgrimes		s3 = accept(s2, (struct sockaddr *)&from, &len);
1761573Srgrimes		(void)close(s2);
1771573Srgrimes		if (s3 < 0) {
1781573Srgrimes			(void)fprintf(stderr,
1791573Srgrimes			    "rcmd: accept: %s\n", strerror(errno));
1801573Srgrimes			lport = 0;
1811573Srgrimes			goto bad;
1821573Srgrimes		}
1831573Srgrimes		*fd2p = s3;
1841573Srgrimes		from.sin_port = ntohs((u_short)from.sin_port);
1851573Srgrimes		if (from.sin_family != AF_INET ||
1861573Srgrimes		    from.sin_port >= IPPORT_RESERVED ||
1871573Srgrimes		    from.sin_port < IPPORT_RESERVED / 2) {
1881573Srgrimes			(void)fprintf(stderr,
1891573Srgrimes			    "socket: protocol failure in circuit setup.\n");
1901573Srgrimes			goto bad2;
1911573Srgrimes		}
1921573Srgrimes	}
1931573Srgrimes	(void)write(s, locuser, strlen(locuser)+1);
1941573Srgrimes	(void)write(s, remuser, strlen(remuser)+1);
1951573Srgrimes	(void)write(s, cmd, strlen(cmd)+1);
1961573Srgrimes	if (read(s, &c, 1) != 1) {
1971573Srgrimes		(void)fprintf(stderr,
1981573Srgrimes		    "rcmd: %s: %s\n", *ahost, strerror(errno));
1991573Srgrimes		goto bad2;
2001573Srgrimes	}
2011573Srgrimes	if (c != 0) {
2021573Srgrimes		while (read(s, &c, 1) == 1) {
2031573Srgrimes			(void)write(STDERR_FILENO, &c, 1);
2041573Srgrimes			if (c == '\n')
2051573Srgrimes				break;
2061573Srgrimes		}
2071573Srgrimes		goto bad2;
2081573Srgrimes	}
2091573Srgrimes	sigsetmask(oldmask);
2101573Srgrimes	return (s);
2111573Srgrimesbad2:
2121573Srgrimes	if (lport)
2131573Srgrimes		(void)close(*fd2p);
2141573Srgrimesbad:
2151573Srgrimes	(void)close(s);
2161573Srgrimes	sigsetmask(oldmask);
2171573Srgrimes	return (-1);
2181573Srgrimes}
2191573Srgrimes
2201573Srgrimesint
2211573Srgrimesrresvport(alport)
2221573Srgrimes	int *alport;
2231573Srgrimes{
2241573Srgrimes	struct sockaddr_in sin;
2251573Srgrimes	int s;
2261573Srgrimes
2271573Srgrimes	sin.sin_family = AF_INET;
2281573Srgrimes	sin.sin_addr.s_addr = INADDR_ANY;
2291573Srgrimes	s = socket(AF_INET, SOCK_STREAM, 0);
2301573Srgrimes	if (s < 0)
2311573Srgrimes		return (-1);
2321573Srgrimes	for (;;) {
2331573Srgrimes		sin.sin_port = htons((u_short)*alport);
2341573Srgrimes		if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
2351573Srgrimes			return (s);
2361573Srgrimes		if (errno != EADDRINUSE) {
2371573Srgrimes			(void)close(s);
2381573Srgrimes			return (-1);
2391573Srgrimes		}
2401573Srgrimes		(*alport)--;
2411573Srgrimes		if (*alport == IPPORT_RESERVED/2) {
2421573Srgrimes			(void)close(s);
2431573Srgrimes			errno = EAGAIN;		/* close */
2441573Srgrimes			return (-1);
2451573Srgrimes		}
2461573Srgrimes	}
2471573Srgrimes}
2481573Srgrimes
2491573Srgrimesint	__check_rhosts_file = 1;
2501573Srgrimeschar	*__rcmd_errstr;
2511573Srgrimes
2521573Srgrimesint
2531573Srgrimesruserok(rhost, superuser, ruser, luser)
2541573Srgrimes	const char *rhost, *ruser, *luser;
2551573Srgrimes	int superuser;
2561573Srgrimes{
2571573Srgrimes	struct hostent *hp;
2581573Srgrimes	u_long addr;
2591573Srgrimes	char **ap;
2601573Srgrimes
2611573Srgrimes	if ((hp = gethostbyname(rhost)) == NULL)
2621573Srgrimes		return (-1);
2631573Srgrimes	for (ap = hp->h_addr_list; *ap; ++ap) {
2641573Srgrimes		bcopy(*ap, &addr, sizeof(addr));
2651573Srgrimes		if (iruserok(addr, superuser, ruser, luser) == 0)
2661573Srgrimes			return (0);
2671573Srgrimes	}
2681573Srgrimes	return (-1);
2691573Srgrimes}
2701573Srgrimes
2711573Srgrimes/*
2721573Srgrimes * New .rhosts strategy: We are passed an ip address. We spin through
2731573Srgrimes * hosts.equiv and .rhosts looking for a match. When the .rhosts only
2741573Srgrimes * has ip addresses, we don't have to trust a nameserver.  When it
2751573Srgrimes * contains hostnames, we spin through the list of addresses the nameserver
2761573Srgrimes * gives us and look for a match.
2771573Srgrimes *
2781573Srgrimes * Returns 0 if ok, -1 if not ok.
2791573Srgrimes */
2801573Srgrimesint
2811573Srgrimesiruserok(raddr, superuser, ruser, luser)
2821573Srgrimes	u_long raddr;
2831573Srgrimes	int superuser;
2841573Srgrimes	const char *ruser, *luser;
2851573Srgrimes{
2861573Srgrimes	register char *cp;
2871573Srgrimes	struct stat sbuf;
2881573Srgrimes	struct passwd *pwd;
2891573Srgrimes	FILE *hostf;
2901573Srgrimes	uid_t uid;
2911573Srgrimes	int first;
2921573Srgrimes	char pbuf[MAXPATHLEN];
2931573Srgrimes
2941573Srgrimes	first = 1;
2951573Srgrimes	hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
2961573Srgrimesagain:
2971573Srgrimes	if (hostf) {
2981573Srgrimes		if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
2991573Srgrimes			(void)fclose(hostf);
3001573Srgrimes			return (0);
3011573Srgrimes		}
3021573Srgrimes		(void)fclose(hostf);
3031573Srgrimes	}
3041573Srgrimes	if (first == 1 && (__check_rhosts_file || superuser)) {
3051573Srgrimes		first = 0;
3061573Srgrimes		if ((pwd = getpwnam(luser)) == NULL)
3071573Srgrimes			return (-1);
3081573Srgrimes		(void)strcpy(pbuf, pwd->pw_dir);
3091573Srgrimes		(void)strcat(pbuf, "/.rhosts");
3101573Srgrimes
3111573Srgrimes		/*
3121573Srgrimes		 * Change effective uid while opening .rhosts.  If root and
3131573Srgrimes		 * reading an NFS mounted file system, can't read files that
3141573Srgrimes		 * are protected read/write owner only.
3151573Srgrimes		 */
3161573Srgrimes		uid = geteuid();
3171573Srgrimes		(void)seteuid(pwd->pw_uid);
3181573Srgrimes		hostf = fopen(pbuf, "r");
3191573Srgrimes		(void)seteuid(uid);
3201573Srgrimes
3211573Srgrimes		if (hostf == NULL)
3221573Srgrimes			return (-1);
3231573Srgrimes		/*
3241573Srgrimes		 * If not a regular file, or is owned by someone other than
3251573Srgrimes		 * user or root or if writeable by anyone but the owner, quit.
3261573Srgrimes		 */
3271573Srgrimes		cp = NULL;
3281573Srgrimes		if (lstat(pbuf, &sbuf) < 0)
3291573Srgrimes			cp = ".rhosts lstat failed";
3301573Srgrimes		else if (!S_ISREG(sbuf.st_mode))
3311573Srgrimes			cp = ".rhosts not regular file";
3321573Srgrimes		else if (fstat(fileno(hostf), &sbuf) < 0)
3331573Srgrimes			cp = ".rhosts fstat failed";
3341573Srgrimes		else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
3351573Srgrimes			cp = "bad .rhosts owner";
3361573Srgrimes		else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
3371573Srgrimes			cp = ".rhosts writeable by other than owner";
3381573Srgrimes		/* If there were any problems, quit. */
3391573Srgrimes		if (cp) {
3401573Srgrimes			__rcmd_errstr = cp;
3411573Srgrimes			(void)fclose(hostf);
3421573Srgrimes			return (-1);
3431573Srgrimes		}
3441573Srgrimes		goto again;
3451573Srgrimes	}
3461573Srgrimes	return (-1);
3471573Srgrimes}
3481573Srgrimes
3491573Srgrimes/*
3501573Srgrimes * XXX
3511573Srgrimes * Don't make static, used by lpd(8).
3521573Srgrimes *
3531573Srgrimes * Returns 0 if ok, -1 if not ok.
3541573Srgrimes */
3551573Srgrimesint
3561573Srgrimes__ivaliduser(hostf, raddr, luser, ruser)
3571573Srgrimes	FILE *hostf;
3581573Srgrimes	u_long raddr;
3591573Srgrimes	const char *luser, *ruser;
3601573Srgrimes{
3611573Srgrimes	register char *user, *p;
3621573Srgrimes	int ch;
3631573Srgrimes	char buf[MAXHOSTNAMELEN + 128];		/* host + login */
3647183Swpaul	struct hostent *hp;
3657183Swpaul	/* Presumed guilty until proven innocent. */
3667183Swpaul	int userok = 0, hostok = 0;
3679978Swpaul#ifdef YP
3689978Swpaul	char *ypdomain;
3691573Srgrimes
3709978Swpaul	if (yp_get_default_domain(&ypdomain))
3719978Swpaul		ypdomain = NULL;
3729978Swpaul#else
3739978Swpaul#define	ypdomain NULL
3749978Swpaul#endif
3757183Swpaul	/* We need to get the damn hostname back for netgroup matching. */
3767183Swpaul	if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long),
3777183Swpaul							AF_INET)) == NULL)
3787183Swpaul		return (-1);
3797183Swpaul
3801573Srgrimes	while (fgets(buf, sizeof(buf), hostf)) {
3811573Srgrimes		p = buf;
3821573Srgrimes		/* Skip lines that are too long. */
3831573Srgrimes		if (strchr(p, '\n') == NULL) {
3841573Srgrimes			while ((ch = getc(hostf)) != '\n' && ch != EOF);
3851573Srgrimes			continue;
3861573Srgrimes		}
3879552Speter		if (*p == '\n' || *p == '#') {
3889552Speter			/* comment... */
3899552Speter			continue;
3909552Speter		}
3911573Srgrimes		while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
3921573Srgrimes			*p = isupper(*p) ? tolower(*p) : *p;
3931573Srgrimes			p++;
3941573Srgrimes		}
3951573Srgrimes		if (*p == ' ' || *p == '\t') {
3961573Srgrimes			*p++ = '\0';
3971573Srgrimes			while (*p == ' ' || *p == '\t')
3981573Srgrimes				p++;
3991573Srgrimes			user = p;
4001573Srgrimes			while (*p != '\n' && *p != ' ' &&
4011573Srgrimes			    *p != '\t' && *p != '\0')
4021573Srgrimes				p++;
4031573Srgrimes		} else
4041573Srgrimes			user = p;
4051573Srgrimes		*p = '\0';
4067183Swpaul		/*
4077183Swpaul		 * Do +/- and +@/-@ checking. This looks really nasty,
4087183Swpaul		 * but it matches SunOS's behavior so far as I can tell.
4097183Swpaul		 */
4107183Swpaul		switch(buf[0]) {
4117183Swpaul		case '+':
4127183Swpaul			if (!buf[1]) {     /* '+' matches all hosts */
4137183Swpaul				hostok = 1;
4147183Swpaul				break;
4157183Swpaul			}
4167183Swpaul			if (buf[1] == '@')  /* match a host by netgroup */
4177183Swpaul				hostok = innetgr((char *)&buf[2], hp->h_name,
4189978Swpaul						NULL, ypdomain);
4197183Swpaul			else		/* match a host by addr */
4207183Swpaul				hostok = __icheckhost(raddr,(char *)&buf[1]);
4217183Swpaul			break;
4227183Swpaul		case '-':     /* reject '-' hosts and all their users */
4237183Swpaul			if (buf[1] == '@') {
4247183Swpaul				if (innetgr((char *)&buf[2],
4259978Swpaul					      hp->h_name, NULL, ypdomain))
4267183Swpaul					return(-1);
4277183Swpaul			} else {
4287183Swpaul				if (__icheckhost(raddr,(char *)&buf[1]))
4297183Swpaul					return(-1);
4307183Swpaul			}
4317183Swpaul			break;
4327183Swpaul		default:  /* if no '+' or '-', do a simple match */
4337183Swpaul			hostok = __icheckhost(raddr, buf);
4347183Swpaul			break;
4351573Srgrimes		}
4367183Swpaul		switch(*user) {
4377183Swpaul		case '+':
4387183Swpaul			if (!*(user+1)) {      /* '+' matches all users */
4397183Swpaul				userok = 1;
4407183Swpaul				break;
4417183Swpaul			}
4427183Swpaul			if (*(user+1) == '@')  /* match a user by netgroup */
4439978Swpaul				userok = innetgr(user+2, NULL, ruser, ypdomain);
4447183Swpaul			else	   /* match a user by direct specification */
4457183Swpaul				userok = !(strcmp(ruser, user+1));
4467183Swpaul			break;
4477183Swpaul		case '-': 		/* if we matched a hostname, */
4487183Swpaul			if (hostok) {   /* check for user field rejections */
4497183Swpaul				if (!*(user+1))
4507183Swpaul					return(-1);
4517183Swpaul				if (*(user+1) == '@') {
4527183Swpaul					if (innetgr(user+2, NULL,
4539978Swpaul							ruser, ypdomain))
4547183Swpaul						return(-1);
4557183Swpaul				} else {
4567183Swpaul					if (!strcmp(ruser, user+1))
4577183Swpaul						return(-1);
4587183Swpaul				}
4597183Swpaul			}
4607183Swpaul			break;
4617183Swpaul		default:	/* no rejections: try to match the user */
4627183Swpaul			if (hostok)
4637183Swpaul				userok = !(strcmp(ruser,*user ? user : luser));
4647183Swpaul			break;
4657183Swpaul		}
4667183Swpaul		if (hostok && userok)
4677183Swpaul			return(0);
4681573Srgrimes	}
4691573Srgrimes	return (-1);
4701573Srgrimes}
4711573Srgrimes
4721573Srgrimes/*
4731573Srgrimes * Returns "true" if match, 0 if no match.
4741573Srgrimes */
4751573Srgrimesstatic int
4761573Srgrimes__icheckhost(raddr, lhost)
4771573Srgrimes	u_long raddr;
4781573Srgrimes	register char *lhost;
4791573Srgrimes{
4801573Srgrimes	register struct hostent *hp;
4811573Srgrimes	register u_long laddr;
4821573Srgrimes	register char **pp;
4831573Srgrimes
4841573Srgrimes	/* Try for raw ip address first. */
4851573Srgrimes	if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
4861573Srgrimes		return (raddr == laddr);
4871573Srgrimes
4881573Srgrimes	/* Better be a hostname. */
4891573Srgrimes	if ((hp = gethostbyname(lhost)) == NULL)
4901573Srgrimes		return (0);
4911573Srgrimes
4921573Srgrimes	/* Spin through ip addresses. */
4931573Srgrimes	for (pp = hp->h_addr_list; *pp; ++pp)
4941573Srgrimes		if (!bcmp(&raddr, *pp, sizeof(u_long)))
4951573Srgrimes			return (1);
4961573Srgrimes
4971573Srgrimes	/* No match. */
4981573Srgrimes	return (0);
4991573Srgrimes}
500