Home | History | Annotate | Line # | Download | only in rpcinfo
rpcinfo.c revision 1.8
      1 /*	$NetBSD: rpcinfo.c,v 1.8 1998/02/10 07:15:34 lukem Exp $	*/
      2 
      3 #include <sys/cdefs.h>
      4 #ifndef lint
      5 #if 0
      6 static char sccsid[] = "from: @(#)rpcinfo.c 1.22 87/08/12 SMI";
      7 static char sccsid[] = "from: @(#)rpcinfo.c	2.2 88/08/11 4.0 RPCSRC";
      8 #else
      9 __RCSID("$NetBSD: rpcinfo.c,v 1.8 1998/02/10 07:15:34 lukem Exp $");
     10 #endif
     11 #endif
     12 
     13 /*
     14  * Copyright (C) 1986, Sun Microsystems, Inc.
     15  */
     16 
     17 /*
     18  * rpcinfo: ping a particular rpc program
     19  *     or dump the portmapper
     20  */
     21 
     22 /*
     23  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
     24  * unrestricted use provided that this legend is included on all tape
     25  * media and as a part of the software program in whole or part.  Users
     26  * may copy or modify Sun RPC without charge, but are not authorized
     27  * to license or distribute it to anyone else except as part of a product or
     28  * program developed by the user.
     29  *
     30  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
     31  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
     32  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
     33  *
     34  * Sun RPC is provided with no support and without any obligation on the
     35  * part of Sun Microsystems, Inc. to assist in its use, correction,
     36  * modification or enhancement.
     37  *
     38  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
     39  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
     40  * OR ANY PART THEREOF.
     41  *
     42  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
     43  * or profits or other special, indirect and consequential damages, even if
     44  * Sun has been advised of the possibility of such damages.
     45  *
     46  * Sun Microsystems, Inc.
     47  * 2550 Garcia Avenue
     48  * Mountain View, California  94043
     49  */
     50 
     51 #include <sys/types.h>
     52 #include <sys/socket.h>
     53 #include <netinet/in.h>
     54 #include <arpa/inet.h>
     55 #include <ctype.h>
     56 #include <err.h>
     57 #include <netdb.h>
     58 #include <signal.h>
     59 #include <stdio.h>
     60 #include <stdlib.h>
     61 #include <string.h>
     62 #include <unistd.h>
     63 #include <rpc/rpc.h>
     64 #include <rpc/pmap_clnt.h>
     65 #include <rpc/pmap_prot.h>
     66 
     67 
     68 #define MAXHOSTLEN 256
     69 
     70 #define	MIN_VERS	((u_long) 0)
     71 #define	MAX_VERS	((u_long) 4294967295UL)
     72 
     73 static	void	brdcst __P((int, char **));
     74 static	void	deletereg __P((int, char **));
     75 static	void	get_inet_address __P((struct sockaddr_in *, char *));
     76 static	u_long	getprognum __P((char *));
     77 static	u_long	getvers __P((char *));
     78 	int	main __P((int, char **));
     79 static	void	pmapdump __P((int, char **));
     80 static	int	pstatus __P((CLIENT *, u_long, u_long));
     81 static	bool_t	reply_proc __P((caddr_t, struct sockaddr_in *));
     82 static	void	tcpping __P((u_short, int, char **));
     83 static	void	udpping __P((u_short, int, char **));
     84 static	void	usage __P((void));
     85 
     86 /*
     87  * Functions to be performed.
     88  */
     89 #define	NONE		0	/* no function */
     90 #define	PMAPDUMP	1	/* dump portmapper registrations */
     91 #define	TCPPING		2	/* ping TCP service */
     92 #define	UDPPING		3	/* ping UDP service */
     93 #define	BRDCST		4	/* ping broadcast UDP service */
     94 #define DELETES		5	/* delete registration for the service */
     95 
     96 int
     97 main(argc, argv)
     98 	int argc;
     99 	char **argv;
    100 {
    101 	int c;
    102 	int errflg;
    103 	int function;
    104 	u_short portnum;
    105 
    106 	function = NONE;
    107 	portnum = 0;
    108 	errflg = 0;
    109 	while ((c = getopt(argc, argv, "ptubdn:")) != -1) {
    110 		switch (c) {
    111 
    112 		case 'p':
    113 			if (function != NONE)
    114 				errflg = 1;
    115 			else
    116 				function = PMAPDUMP;
    117 			break;
    118 
    119 		case 't':
    120 			if (function != NONE)
    121 				errflg = 1;
    122 			else
    123 				function = TCPPING;
    124 			break;
    125 
    126 		case 'u':
    127 			if (function != NONE)
    128 				errflg = 1;
    129 			else
    130 				function = UDPPING;
    131 			break;
    132 
    133 		case 'b':
    134 			if (function != NONE)
    135 				errflg = 1;
    136 			else
    137 				function = BRDCST;
    138 			break;
    139 
    140 		case 'n':
    141 			portnum = (u_short) atoi(optarg);   /* hope we don't get bogus # */
    142 			break;
    143 
    144 		case 'd':
    145 			if (function != NONE)
    146 				errflg = 1;
    147 			else
    148 				function = DELETES;
    149 			break;
    150 
    151 		case '?':
    152 			errflg = 1;
    153 		}
    154 	}
    155 
    156 	if (errflg || function == NONE) {
    157 		usage();
    158 		return (1);
    159 	}
    160 
    161 	switch (function) {
    162 
    163 	case PMAPDUMP:
    164 		if (portnum != 0) {
    165 			usage();
    166 			return (1);
    167 		}
    168 		pmapdump(argc - optind, argv + optind);
    169 		break;
    170 
    171 	case UDPPING:
    172 		udpping(portnum, argc - optind, argv + optind);
    173 		break;
    174 
    175 	case TCPPING:
    176 		tcpping(portnum, argc - optind, argv + optind);
    177 		break;
    178 
    179 	case BRDCST:
    180 		if (portnum != 0) {
    181 			usage();
    182 			return (1);
    183 		}
    184 		brdcst(argc - optind, argv + optind);
    185 		break;
    186 
    187 	case DELETES:
    188 		deletereg(argc - optind, argv + optind);
    189 		break;
    190 	}
    191 
    192 	return (0);
    193 }
    194 
    195 static void
    196 udpping(portnum, argc, argv)
    197 	u_short portnum;
    198 	int argc;
    199 	char **argv;
    200 {
    201 	struct timeval to;
    202 	struct sockaddr_in addr;
    203 	enum clnt_stat rpc_stat;
    204 	CLIENT *client;
    205 	u_long prognum, vers, minvers, maxvers;
    206 	int sock = RPC_ANYSOCK;
    207 	struct rpc_err rpcerr;
    208 	int failure;
    209 
    210 	if (argc < 2 || argc > 3) {
    211 		usage();
    212 		exit(1);
    213 	}
    214 	prognum = getprognum(argv[1]);
    215 	get_inet_address(&addr, argv[0]);
    216 	/* Open the socket here so it will survive calls to clnt_destroy */
    217 	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    218 	if (sock < 0) {
    219 		perror("rpcinfo: socket");
    220 		exit(1);
    221 	}
    222 	failure = 0;
    223 	if (argc == 2) {
    224 		/*
    225 		 * A call to version 0 should fail with a program/version
    226 		 * mismatch, and give us the range of versions supported.
    227 		 */
    228 		addr.sin_port = htons(portnum);
    229 		to.tv_sec = 5;
    230 		to.tv_usec = 0;
    231 		if ((client = clntudp_create(&addr, prognum, (u_long)0,
    232 		    to, &sock)) == NULL) {
    233 			clnt_pcreateerror("rpcinfo");
    234 			printf("program %lu is not available\n",
    235 			    prognum);
    236 			exit(1);
    237 		}
    238 		to.tv_sec = 10;
    239 		to.tv_usec = 0;
    240 		rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
    241 		    xdr_void, (char *)NULL, to);
    242 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
    243 			clnt_geterr(client, &rpcerr);
    244 			minvers = rpcerr.re_vers.low;
    245 			maxvers = rpcerr.re_vers.high;
    246 		} else if (rpc_stat == RPC_SUCCESS) {
    247 			/*
    248 			 * Oh dear, it DOES support version 0.
    249 			 * Let's try version MAX_VERS.
    250 			 */
    251 			addr.sin_port = htons(portnum);
    252 			to.tv_sec = 5;
    253 			to.tv_usec = 0;
    254 			if ((client = clntudp_create(&addr, prognum, MAX_VERS,
    255 			    to, &sock)) == NULL) {
    256 				clnt_pcreateerror("rpcinfo");
    257 				printf("program %lu version %lu is not available\n",
    258 				    prognum, MAX_VERS);
    259 				exit(1);
    260 			}
    261 			to.tv_sec = 10;
    262 			to.tv_usec = 0;
    263 			rpc_stat = clnt_call(client, NULLPROC, xdr_void,
    264 			    (char *)NULL, xdr_void, (char *)NULL, to);
    265 			if (rpc_stat == RPC_PROGVERSMISMATCH) {
    266 				clnt_geterr(client, &rpcerr);
    267 				minvers = rpcerr.re_vers.low;
    268 				maxvers = rpcerr.re_vers.high;
    269 			} else if (rpc_stat == RPC_SUCCESS) {
    270 				/*
    271 				 * It also supports version MAX_VERS.
    272 				 * Looks like we have a wise guy.
    273 				 * OK, we give them information on all
    274 				 * 4 billion versions they support...
    275 				 */
    276 				minvers = 0;
    277 				maxvers = MAX_VERS;
    278 			} else {
    279 				(void) pstatus(client, prognum, MAX_VERS);
    280 				exit(1);
    281 			}
    282 		} else {
    283 			(void) pstatus(client, prognum, (u_long)0);
    284 			exit(1);
    285 		}
    286 		clnt_destroy(client);
    287 		for (vers = minvers; vers <= maxvers; vers++) {
    288 			addr.sin_port = htons(portnum);
    289 			to.tv_sec = 5;
    290 			to.tv_usec = 0;
    291 			if ((client = clntudp_create(&addr, prognum, vers,
    292 			    to, &sock)) == NULL) {
    293 				clnt_pcreateerror("rpcinfo");
    294 				printf("program %lu version %lu is not available\n",
    295 				    prognum, vers);
    296 				exit(1);
    297 			}
    298 			to.tv_sec = 10;
    299 			to.tv_usec = 0;
    300 			rpc_stat = clnt_call(client, NULLPROC, xdr_void,
    301 			    (char *)NULL, xdr_void, (char *)NULL, to);
    302 			if (pstatus(client, prognum, vers) < 0)
    303 				failure = 1;
    304 			clnt_destroy(client);
    305 		}
    306 	}
    307 	else {
    308 		vers = getvers(argv[2]);
    309 		addr.sin_port = htons(portnum);
    310 		to.tv_sec = 5;
    311 		to.tv_usec = 0;
    312 		if ((client = clntudp_create(&addr, prognum, vers,
    313 		    to, &sock)) == NULL) {
    314 			clnt_pcreateerror("rpcinfo");
    315 			printf("program %lu version %lu is not available\n",
    316 			    prognum, vers);
    317 			exit(1);
    318 		}
    319 		to.tv_sec = 10;
    320 		to.tv_usec = 0;
    321 		rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
    322 		    xdr_void, (char *)NULL, to);
    323 		if (pstatus(client, prognum, vers) < 0)
    324 			failure = 1;
    325 	}
    326 	(void) close(sock); /* Close it up again */
    327 	if (failure)
    328 		exit(1);
    329 }
    330 
    331 static void
    332 tcpping(portnum, argc, argv)
    333 	u_short portnum;
    334 	int argc;
    335 	char **argv;
    336 {
    337 	struct timeval to;
    338 	struct sockaddr_in addr;
    339 	enum clnt_stat rpc_stat;
    340 	CLIENT *client;
    341 	u_long prognum, vers, minvers, maxvers;
    342 	int sock = RPC_ANYSOCK;
    343 	struct rpc_err rpcerr;
    344 	int failure;
    345 
    346 	if (argc < 2 || argc > 3) {
    347 		usage();
    348 		exit(1);
    349 	}
    350 	prognum = getprognum(argv[1]);
    351 	get_inet_address(&addr, argv[0]);
    352 	failure = 0;
    353 	if (argc == 2) {
    354 		/*
    355 		 * A call to version 0 should fail with a program/version
    356 		 * mismatch, and give us the range of versions supported.
    357 		 */
    358 		addr.sin_port = htons(portnum);
    359 		if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
    360 		    &sock, 0, 0)) == NULL) {
    361 			clnt_pcreateerror("rpcinfo");
    362 			printf("program %lu is not available\n",
    363 			    prognum);
    364 			exit(1);
    365 		}
    366 		to.tv_sec = 10;
    367 		to.tv_usec = 0;
    368 		rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
    369 		    xdr_void, (char *)NULL, to);
    370 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
    371 			clnt_geterr(client, &rpcerr);
    372 			minvers = rpcerr.re_vers.low;
    373 			maxvers = rpcerr.re_vers.high;
    374 		} else if (rpc_stat == RPC_SUCCESS) {
    375 			/*
    376 			 * Oh dear, it DOES support version 0.
    377 			 * Let's try version MAX_VERS.
    378 			 */
    379 			addr.sin_port = htons(portnum);
    380 			if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
    381 			    &sock, 0, 0)) == NULL) {
    382 				clnt_pcreateerror("rpcinfo");
    383 				printf("program %lu version %lu is not available\n",
    384 				    prognum, MAX_VERS);
    385 				exit(1);
    386 			}
    387 			to.tv_sec = 10;
    388 			to.tv_usec = 0;
    389 			rpc_stat = clnt_call(client, NULLPROC, xdr_void,
    390 			    (char *)NULL, xdr_void, (char *)NULL, to);
    391 			if (rpc_stat == RPC_PROGVERSMISMATCH) {
    392 				clnt_geterr(client, &rpcerr);
    393 				minvers = rpcerr.re_vers.low;
    394 				maxvers = rpcerr.re_vers.high;
    395 			} else if (rpc_stat == RPC_SUCCESS) {
    396 				/*
    397 				 * It also supports version MAX_VERS.
    398 				 * Looks like we have a wise guy.
    399 				 * OK, we give them information on all
    400 				 * 4 billion versions they support...
    401 				 */
    402 				minvers = 0;
    403 				maxvers = MAX_VERS;
    404 			} else {
    405 				(void) pstatus(client, prognum, MAX_VERS);
    406 				exit(1);
    407 			}
    408 		} else {
    409 			(void) pstatus(client, prognum, MIN_VERS);
    410 			exit(1);
    411 		}
    412 		clnt_destroy(client);
    413 		(void) close(sock);
    414 		sock = RPC_ANYSOCK; /* Re-initialize it for later */
    415 		for (vers = minvers; vers <= maxvers; vers++) {
    416 			addr.sin_port = htons(portnum);
    417 			if ((client = clnttcp_create(&addr, prognum, vers,
    418 			    &sock, 0, 0)) == NULL) {
    419 				clnt_pcreateerror("rpcinfo");
    420 				printf("program %lu version %lu is not available\n",
    421 				    prognum, vers);
    422 				exit(1);
    423 			}
    424 			to.tv_usec = 0;
    425 			to.tv_sec = 10;
    426 			rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
    427 			    xdr_void, (char *)NULL, to);
    428 			if (pstatus(client, prognum, vers) < 0)
    429 				failure = 1;
    430 			clnt_destroy(client);
    431 			(void) close(sock);
    432 			sock = RPC_ANYSOCK;
    433 		}
    434 	}
    435 	else {
    436 		vers = getvers(argv[2]);
    437 		addr.sin_port = htons(portnum);
    438 		if ((client = clnttcp_create(&addr, prognum, vers, &sock,
    439 		    0, 0)) == NULL) {
    440 			clnt_pcreateerror("rpcinfo");
    441 			printf("program %lu version %lu is not available\n",
    442 			    prognum, vers);
    443 			exit(1);
    444 		}
    445 		to.tv_usec = 0;
    446 		to.tv_sec = 10;
    447 		rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
    448 		    xdr_void, (char *)NULL, to);
    449 		if (pstatus(client, prognum, vers) < 0)
    450 			failure = 1;
    451 	}
    452 	if (failure)
    453 		exit(1);
    454 }
    455 
    456 /*
    457  * This routine should take a pointer to an "rpc_err" structure, rather than
    458  * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
    459  * a CLIENT structure rather than a pointer to an "rpc_err" structure.
    460  * As such, we have to keep the CLIENT structure around in order to print
    461  * a good error message.
    462  */
    463 static int
    464 pstatus(client, prognum, vers)
    465 	CLIENT *client;
    466 	u_long prognum;
    467 	u_long vers;
    468 {
    469 	struct rpc_err rpcerr;
    470 
    471 	clnt_geterr(client, &rpcerr);
    472 	if (rpcerr.re_status != RPC_SUCCESS) {
    473 		clnt_perror(client, "rpcinfo");
    474 		printf("program %lu version %lu is not available\n",
    475 		    prognum, vers);
    476 		return (-1);
    477 	} else {
    478 		printf("program %lu version %lu ready and waiting\n",
    479 		    prognum, vers);
    480 		return (0);
    481 	}
    482 }
    483 
    484 static void
    485 pmapdump(argc, argv)
    486 	int argc;
    487 	char **argv;
    488 {
    489 	struct sockaddr_in server_addr;
    490 	struct hostent *hp;
    491 	struct pmaplist *head = NULL;
    492 	int socket = RPC_ANYSOCK;
    493 	struct timeval minutetimeout;
    494 	CLIENT *client;
    495 	struct rpcent *rpc;
    496 
    497 	if (argc > 1) {
    498 		usage();
    499 		exit(1);
    500 	}
    501 	if (argc == 1)
    502 		get_inet_address(&server_addr, argv[0]);
    503 	else {
    504 		memset((char *)&server_addr, 0, sizeof server_addr);
    505 		server_addr.sin_family = AF_INET;
    506 		if ((hp = gethostbyname("localhost")) != NULL)
    507 			memmove((caddr_t)&server_addr.sin_addr, hp->h_addr,
    508 			    hp->h_length);
    509 		else
    510 			(void) inet_aton("0.0.0.0", &server_addr.sin_addr);
    511 	}
    512 	minutetimeout.tv_sec = 60;
    513 	minutetimeout.tv_usec = 0;
    514 	server_addr.sin_port = htons(PMAPPORT);
    515 	if ((client = clnttcp_create(&server_addr, PMAPPROG,
    516 	    PMAPVERS, &socket, 50, 500)) == NULL) {
    517 		clnt_pcreateerror("rpcinfo: can't contact portmapper");
    518 		exit(1);
    519 	}
    520 	if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
    521 	    xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
    522 		fprintf(stderr, "rpcinfo: can't contact portmapper: ");
    523 		clnt_perror(client, "rpcinfo");
    524 		exit(1);
    525 	}
    526 	if (head == NULL) {
    527 		printf("No remote programs registered.\n");
    528 	} else {
    529 		printf("   program vers proto   port\n");
    530 		for (; head != NULL; head = head->pml_next) {
    531 			printf("%10d%5d",
    532 			    head->pml_map.pm_prog,
    533 			    head->pml_map.pm_vers);
    534 			if (head->pml_map.pm_prot == IPPROTO_UDP)
    535 				printf("%6s",  "udp");
    536 			else if (head->pml_map.pm_prot == IPPROTO_TCP)
    537 				printf("%6s", "tcp");
    538 			else
    539 				printf("%6d",  head->pml_map.pm_prot);
    540 			printf("%7d",  head->pml_map.pm_port);
    541 			rpc = getrpcbynumber(head->pml_map.pm_prog);
    542 			if (rpc)
    543 				printf("  %s\n", rpc->r_name);
    544 			else
    545 				printf("\n");
    546 		}
    547 	}
    548 }
    549 
    550 /*
    551  * reply_proc collects replies from the broadcast.
    552  * to get a unique list of responses the output of rpcinfo should
    553  * be piped through sort(1) and then uniq(1).
    554  */
    555 
    556 static bool_t
    557 reply_proc(res, who)
    558 	caddr_t res;		/* Nothing comes back */
    559 	struct sockaddr_in *who; /* Who sent us the reply */
    560 {
    561 	struct hostent *hp;
    562 
    563 	hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
    564 	    AF_INET);
    565 	printf("%s %s\n", inet_ntoa(who->sin_addr),
    566 	    (hp == NULL) ? "(unknown)" : hp->h_name);
    567 	return(FALSE);
    568 }
    569 
    570 static void
    571 brdcst(argc, argv)
    572 	int argc;
    573 	char **argv;
    574 {
    575 	enum clnt_stat rpc_stat;
    576 	u_long prognum, vers;
    577 
    578 	if (argc != 2) {
    579 		usage();
    580 		exit(1);
    581 	}
    582 	prognum = getprognum(argv[0]);
    583 	vers = getvers(argv[1]);
    584 	rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
    585 	    (char *)NULL, xdr_void, (char *)NULL, reply_proc);
    586 	if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
    587 		fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
    588 		    clnt_sperrno(rpc_stat));
    589 		exit(1);
    590 	}
    591 	exit(0);
    592 }
    593 
    594 static void
    595 deletereg(argc, argv)
    596 	int argc;
    597 	char **argv;
    598 {	u_long prog_num, version_num;
    599 
    600 	if (argc != 2) {
    601 		usage();
    602 		exit(1);
    603 	}
    604 	if (getuid()) /* This command allowed only to root */
    605 		errx(1, "Sorry. You are not root");
    606 	prog_num = getprognum(argv[0]);
    607 	version_num = getvers(argv[1]);
    608 	if ((pmap_unset(prog_num, version_num)) == 0)
    609 		errx(1, "Could not delete registration for prog %s version %s",
    610 		    argv[0], argv[1]);
    611 }
    612 
    613 static void
    614 usage()
    615 {
    616 	fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n");
    617 	fprintf(stderr, "       rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n");
    618 	fprintf(stderr, "       rpcinfo -p [ host ]\n");
    619 	fprintf(stderr, "       rpcinfo -b prognum versnum\n");
    620 	fprintf(stderr, "       rpcinfo -d prognum versnum\n");
    621 }
    622 
    623 static u_long
    624 getprognum(arg)
    625 	char *arg;
    626 {
    627 	struct rpcent *rpc;
    628 	u_long prognum;
    629 
    630 	if (isalpha(*arg)) {
    631 		rpc = getrpcbyname(arg);
    632 		if (rpc == NULL) {
    633 			fprintf(stderr, "rpcinfo: %s is unknown service\n",
    634 			    arg);
    635 			exit(1);
    636 		}
    637 		prognum = rpc->r_number;
    638 	} else {
    639 		prognum = (u_long) atoi(arg);
    640 	}
    641 
    642 	return (prognum);
    643 }
    644 
    645 static u_long
    646 getvers(arg)
    647 	char *arg;
    648 {
    649 	u_long vers;
    650 
    651 	vers = (int) atoi(arg);
    652 	return (vers);
    653 }
    654 
    655 static void
    656 get_inet_address(addr, host)
    657 	struct sockaddr_in *addr;
    658 	char *host;
    659 {
    660 	struct hostent *hp;
    661 
    662 	memset((char *)addr, 0, sizeof *addr);
    663 	if (inet_aton(host, &addr->sin_addr) == 0) {
    664 		if ((hp = gethostbyname(host)) == NULL) {
    665 			fprintf(stderr, "rpcinfo: %s is unknown host\n", host);
    666 			exit(1);
    667 		}
    668 		memmove((char *)&addr->sin_addr, hp->h_addr, hp->h_length);
    669 	}
    670 	addr->sin_family = AF_INET;
    671 }
    672