xref: /onnv-gate/usr/src/cmd/rpcinfo/rpcinfo.c (revision 11563:19a889966d85)
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*11563SVallish.Vaidyeshwara@Sun.COM  * Common Development and Distribution License (the "License").
6*11563SVallish.Vaidyeshwara@Sun.COM  * 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  *
21*11563SVallish.Vaidyeshwara@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
220Sstevel@tonic-gate  * Use is subject to license terms.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
250Sstevel@tonic-gate /* All Rights Reserved */
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
280Sstevel@tonic-gate  * The Regents of the University of California
290Sstevel@tonic-gate  * All Rights Reserved
300Sstevel@tonic-gate  *
310Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
320Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
330Sstevel@tonic-gate  * contributors.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * rpcinfo: ping a particular rpc program
380Sstevel@tonic-gate  * 	or dump the the registered programs on the remote machine.
390Sstevel@tonic-gate  */
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * We are for now defining PORTMAP here.  It doesnt even compile
430Sstevel@tonic-gate  * unless it is defined.
440Sstevel@tonic-gate  */
450Sstevel@tonic-gate #ifndef	PORTMAP
460Sstevel@tonic-gate #define	PORTMAP
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * If PORTMAP is defined, rpcinfo will talk to both portmapper and
510Sstevel@tonic-gate  * rpcbind programs; else it talks only to rpcbind. In the latter case
520Sstevel@tonic-gate  * all the portmapper specific options such as -u, -t, -p become void.
530Sstevel@tonic-gate  */
540Sstevel@tonic-gate #include <rpc/rpc.h>
550Sstevel@tonic-gate #include <stdio.h>
560Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
570Sstevel@tonic-gate #include <rpc/nettype.h>
580Sstevel@tonic-gate #include <netdir.h>
590Sstevel@tonic-gate #include <rpc/rpcent.h>
600Sstevel@tonic-gate #include <sys/utsname.h>
610Sstevel@tonic-gate #include <stdlib.h>
620Sstevel@tonic-gate #include <string.h>
63*11563SVallish.Vaidyeshwara@Sun.COM #include <ctype.h>
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #ifdef PORTMAP		/* Support for version 2 portmapper */
660Sstevel@tonic-gate #include <netinet/in.h>
670Sstevel@tonic-gate #include <sys/socket.h>
680Sstevel@tonic-gate #include <netdb.h>
690Sstevel@tonic-gate #include <arpa/inet.h>
700Sstevel@tonic-gate #include <rpc/pmap_prot.h>
710Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
720Sstevel@tonic-gate #endif
730Sstevel@tonic-gate 
740Sstevel@tonic-gate #define	MAXHOSTLEN	256
750Sstevel@tonic-gate #define	MIN_VERS	((ulong_t)0)
76481Sssdevi #define	MAX_VERS	(4294967295UL)
770Sstevel@tonic-gate #define	UNKNOWN		"unknown"
780Sstevel@tonic-gate 
790Sstevel@tonic-gate #define	MAX(a, b) (((a) > (b)) ? (a) : (b))
800Sstevel@tonic-gate 
810Sstevel@tonic-gate extern int	t_errno;
820Sstevel@tonic-gate extern long	strtol();
830Sstevel@tonic-gate static char *spaces();
840Sstevel@tonic-gate 
850Sstevel@tonic-gate #ifdef PORTMAP
860Sstevel@tonic-gate static void	ip_ping(/*ushort_t portflag, char *trans,
870Sstevel@tonic-gate 				int argc, char **argv*/);
880Sstevel@tonic-gate static CLIENT	*clnt_com_create(/* struct sockaddr_in *addr, long prog,
890Sstevel@tonic-gate 			long vers, int *fd, char *trans*/);
900Sstevel@tonic-gate static void	pmapdump(/*int argc, char **argv*/);
910Sstevel@tonic-gate static void	get_inet_address(/*struct sockaddr_in *addr, char *host*/);
920Sstevel@tonic-gate #endif
930Sstevel@tonic-gate 
940Sstevel@tonic-gate static bool_t	reply_proc(/*void *res, struct netbuf *who*,
950Sstevel@tonic-gate 			struct netconfig *nconf*/);
960Sstevel@tonic-gate static void	brdcst(/*int argc, char **argv*/);
970Sstevel@tonic-gate static void	addrping(/*char *address, char *netid,
980Sstevel@tonic-gate 				int argc, char **argv*/);
990Sstevel@tonic-gate static void	progping(/* char *netid, int argc, char **argv*/);
1000Sstevel@tonic-gate static CLIENT	*clnt_addr_create(/* char *addr, struct netconfig *nconf,
1010Sstevel@tonic-gate 				long prog, long vers*/);
1020Sstevel@tonic-gate static CLIENT   *clnt_rpcbind_create(/* char *host, int vers */);
1030Sstevel@tonic-gate static CLIENT   *getclnthandle(/* host, nconf, rpcbversnum */);
1040Sstevel@tonic-gate static int	pstatus(/*CLIENT *client, ulong_t prognum, ulong_t vers*/);
1050Sstevel@tonic-gate static void	rpcbdump(/*char *netid, int argc, char **argv*/);
1060Sstevel@tonic-gate static void	rpcbgetstat(/* int argc, char **argv*/);
1070Sstevel@tonic-gate static void	rpcbaddrlist(/*char *netid, int argc, char **argv*/);
1080Sstevel@tonic-gate static void	deletereg(/*char *netid, int argc, char **argv */);
1090Sstevel@tonic-gate static void	print_rmtcallstat(/* rtype, infp */);
1100Sstevel@tonic-gate static void	print_getaddrstat(/* rtype, infp */);
1110Sstevel@tonic-gate static void	usage(/*void*/);
1120Sstevel@tonic-gate static ulong_t	getprognum(/*char *arg*/);
1130Sstevel@tonic-gate static ulong_t	getvers(/*char *arg*/);
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate  * Functions to be performed.
1170Sstevel@tonic-gate  */
1180Sstevel@tonic-gate #define	NONE		0	/* no function */
1190Sstevel@tonic-gate #define	PMAPDUMP	1	/* dump portmapper registrations */
1200Sstevel@tonic-gate #define	TCPPING		2	/* ping TCP service */
1210Sstevel@tonic-gate #define	UDPPING		3	/* ping UDP service */
1220Sstevel@tonic-gate #define	BROADCAST	4	/* ping broadcast service */
1230Sstevel@tonic-gate #define	DELETES		5	/* delete registration for the service */
1240Sstevel@tonic-gate #define	ADDRPING	6	/* pings at the given address */
1250Sstevel@tonic-gate #define	PROGPING	7	/* pings a program on a given host */
1260Sstevel@tonic-gate #define	RPCBDUMP	8	/* dump rpcbind registrations */
1270Sstevel@tonic-gate #define	RPCBDUMP_SHORT	9	/* dump rpcbind registrations - short version */
1280Sstevel@tonic-gate #define	RPCBADDRLIST	10	/* dump addr list about one prog */
1290Sstevel@tonic-gate #define	RPCBGETSTAT	11	/* Get statistics */
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate struct netidlist {
1320Sstevel@tonic-gate 	char *netid;
1330Sstevel@tonic-gate 	struct netidlist *next;
1340Sstevel@tonic-gate };
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate struct verslist {
1370Sstevel@tonic-gate 	int vers;
1380Sstevel@tonic-gate 	struct verslist *next;
1390Sstevel@tonic-gate };
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate struct rpcbdump_short {
1420Sstevel@tonic-gate 	ulong_t prog;
1430Sstevel@tonic-gate 	struct verslist *vlist;
1440Sstevel@tonic-gate 	struct netidlist *nlist;
1450Sstevel@tonic-gate 	struct rpcbdump_short *next;
1460Sstevel@tonic-gate 	char *owner;
1470Sstevel@tonic-gate };
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate char *loopback_netid = NULL;
1510Sstevel@tonic-gate struct netconfig *loopback_nconf;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate int
main(argc,argv)1540Sstevel@tonic-gate main(argc, argv)
1550Sstevel@tonic-gate 	int argc;
1560Sstevel@tonic-gate 	char **argv;
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate 	register int c;
1590Sstevel@tonic-gate 	extern char *optarg;
1600Sstevel@tonic-gate 	extern int optind;
1610Sstevel@tonic-gate 	int errflg;
1620Sstevel@tonic-gate 	int function;
1630Sstevel@tonic-gate 	char *netid = NULL;
1640Sstevel@tonic-gate 	char *address = NULL;
1650Sstevel@tonic-gate 	void *handle;
1660Sstevel@tonic-gate #ifdef PORTMAP
1670Sstevel@tonic-gate 	char *strptr;
1680Sstevel@tonic-gate 	ushort_t portnum = 0;
1690Sstevel@tonic-gate #endif
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	function = NONE;
1720Sstevel@tonic-gate 	errflg = 0;
1730Sstevel@tonic-gate #ifdef PORTMAP
1740Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "a:bdlmn:pstT:u")) != EOF) {
1750Sstevel@tonic-gate #else
1760Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "a:bdlmn:sT:")) != EOF) {
1770Sstevel@tonic-gate #endif
1780Sstevel@tonic-gate 		switch (c) {
1790Sstevel@tonic-gate #ifdef PORTMAP
1800Sstevel@tonic-gate 		case 'p':
1810Sstevel@tonic-gate 			if (function != NONE)
1820Sstevel@tonic-gate 				errflg = 1;
1830Sstevel@tonic-gate 			else
1840Sstevel@tonic-gate 				function = PMAPDUMP;
1850Sstevel@tonic-gate 			break;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 		case 't':
1880Sstevel@tonic-gate 			if (function != NONE)
1890Sstevel@tonic-gate 				errflg = 1;
1900Sstevel@tonic-gate 			else
1910Sstevel@tonic-gate 				function = TCPPING;
1920Sstevel@tonic-gate 			break;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 		case 'u':
1950Sstevel@tonic-gate 			if (function != NONE)
1960Sstevel@tonic-gate 				errflg = 1;
1970Sstevel@tonic-gate 			else
1980Sstevel@tonic-gate 				function = UDPPING;
1990Sstevel@tonic-gate 			break;
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 		case 'n':
2020Sstevel@tonic-gate 			portnum = (ushort_t)strtol(optarg, &strptr, 10);
2030Sstevel@tonic-gate 			if (strptr == optarg || *strptr != '\0') {
204*11563SVallish.Vaidyeshwara@Sun.COM 				(void) fprintf(stderr,
2050Sstevel@tonic-gate 			"rpcinfo: %s is illegal port number\n",
2060Sstevel@tonic-gate 					optarg);
2070Sstevel@tonic-gate 				exit(1);
2080Sstevel@tonic-gate 			}
2090Sstevel@tonic-gate 			break;
2100Sstevel@tonic-gate #endif
2110Sstevel@tonic-gate 		case 'a':
2120Sstevel@tonic-gate 			address = optarg;
2130Sstevel@tonic-gate 			if (function != NONE)
2140Sstevel@tonic-gate 				errflg = 1;
2150Sstevel@tonic-gate 			else
2160Sstevel@tonic-gate 				function = ADDRPING;
2170Sstevel@tonic-gate 			break;
2180Sstevel@tonic-gate 		case 'b':
2190Sstevel@tonic-gate 			if (function != NONE)
2200Sstevel@tonic-gate 				errflg = 1;
2210Sstevel@tonic-gate 			else
2220Sstevel@tonic-gate 				function = BROADCAST;
2230Sstevel@tonic-gate 			break;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 		case 'd':
2260Sstevel@tonic-gate 			if (function != NONE)
2270Sstevel@tonic-gate 				errflg = 1;
2280Sstevel@tonic-gate 			else
2290Sstevel@tonic-gate 				function = DELETES;
2300Sstevel@tonic-gate 			break;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 		case 'l':
2330Sstevel@tonic-gate 			if (function != NONE)
2340Sstevel@tonic-gate 				errflg = 1;
2350Sstevel@tonic-gate 			else
2360Sstevel@tonic-gate 				function = RPCBADDRLIST;
2370Sstevel@tonic-gate 			break;
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 		case 'm':
2400Sstevel@tonic-gate 			if (function != NONE)
2410Sstevel@tonic-gate 				errflg = 1;
2420Sstevel@tonic-gate 			else
2430Sstevel@tonic-gate 				function = RPCBGETSTAT;
2440Sstevel@tonic-gate 			break;
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 		case 's':
2470Sstevel@tonic-gate 			if (function != NONE)
2480Sstevel@tonic-gate 				errflg = 1;
2490Sstevel@tonic-gate 			else
2500Sstevel@tonic-gate 				function = RPCBDUMP_SHORT;
2510Sstevel@tonic-gate 			break;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 		case 'T':
2540Sstevel@tonic-gate 			netid = optarg;
2550Sstevel@tonic-gate 			break;
2560Sstevel@tonic-gate 		case '?':
2570Sstevel@tonic-gate 			errflg = 1;
2580Sstevel@tonic-gate 			break;
2590Sstevel@tonic-gate 		}
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	if (errflg || ((function == ADDRPING) && !netid)) {
2630Sstevel@tonic-gate 		usage();
2640Sstevel@tonic-gate 		return (1);
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate 	if (netid == NULL) {	/* user has not selected transport to use */
2670Sstevel@tonic-gate 		/*
2680Sstevel@tonic-gate 		 * See if a COTS loopback transport is available, in case we
2690Sstevel@tonic-gate 		 * will be talking to the local system.
2700Sstevel@tonic-gate 		 */
2710Sstevel@tonic-gate 		handle = setnetconfig();
2720Sstevel@tonic-gate 		while ((loopback_nconf = getnetconfig(handle)) != NULL) {
2730Sstevel@tonic-gate 			if (strcmp(loopback_nconf->nc_protofmly,
2740Sstevel@tonic-gate 				NC_LOOPBACK) == 0 &&
2750Sstevel@tonic-gate 			    (loopback_nconf->nc_semantics == NC_TPI_COTS ||
2760Sstevel@tonic-gate 			    loopback_nconf->nc_semantics == NC_TPI_COTS_ORD)) {
2770Sstevel@tonic-gate 				loopback_netid = loopback_nconf->nc_netid;
2780Sstevel@tonic-gate 				break;
2790Sstevel@tonic-gate 			}
2800Sstevel@tonic-gate 		}
2810Sstevel@tonic-gate 		if (loopback_netid == NULL) {
282*11563SVallish.Vaidyeshwara@Sun.COM 			(void) endnetconfig(handle);
2830Sstevel@tonic-gate 		}
2840Sstevel@tonic-gate 	}
2850Sstevel@tonic-gate 	if (function == NONE) {
2860Sstevel@tonic-gate 		if (argc - optind > 1)
2870Sstevel@tonic-gate 			function = PROGPING;
2880Sstevel@tonic-gate 		else
2890Sstevel@tonic-gate 			function = RPCBDUMP;
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	switch (function) {
2930Sstevel@tonic-gate #ifdef PORTMAP
2940Sstevel@tonic-gate 	case PMAPDUMP:
2950Sstevel@tonic-gate 		if (portnum != 0) {
2960Sstevel@tonic-gate 			usage();
2970Sstevel@tonic-gate 			return (1);
2980Sstevel@tonic-gate 		}
2990Sstevel@tonic-gate 		pmapdump(argc - optind, argv + optind);
3000Sstevel@tonic-gate 		break;
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	case UDPPING:
3030Sstevel@tonic-gate 		ip_ping(portnum, "udp", argc - optind, argv + optind);
3040Sstevel@tonic-gate 		break;
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	case TCPPING:
3070Sstevel@tonic-gate 		ip_ping(portnum, "tcp", argc - optind, argv + optind);
3080Sstevel@tonic-gate 		break;
3090Sstevel@tonic-gate #endif
3100Sstevel@tonic-gate 	case BROADCAST:
3110Sstevel@tonic-gate 		brdcst(argc - optind, argv + optind);
3120Sstevel@tonic-gate 		break;
3130Sstevel@tonic-gate 	case DELETES:
3140Sstevel@tonic-gate 		deletereg(netid, argc - optind, argv + optind);
3150Sstevel@tonic-gate 		break;
3160Sstevel@tonic-gate 	case ADDRPING:
3170Sstevel@tonic-gate 		addrping(address, netid, argc - optind, argv + optind);
3180Sstevel@tonic-gate 		break;
3190Sstevel@tonic-gate 	case PROGPING:
3200Sstevel@tonic-gate 		progping(netid, argc - optind, argv + optind);
3210Sstevel@tonic-gate 		break;
3220Sstevel@tonic-gate 	case RPCBDUMP:
3230Sstevel@tonic-gate 	case RPCBDUMP_SHORT:
3240Sstevel@tonic-gate 		rpcbdump(function, netid, argc - optind, argv + optind);
3250Sstevel@tonic-gate 		break;
3260Sstevel@tonic-gate 	case RPCBGETSTAT:
3270Sstevel@tonic-gate 		rpcbgetstat(argc - optind, argv + optind);
3280Sstevel@tonic-gate 		break;
3290Sstevel@tonic-gate 	case RPCBADDRLIST:
3300Sstevel@tonic-gate 		rpcbaddrlist(netid, argc - optind, argv + optind);
3310Sstevel@tonic-gate 		break;
3320Sstevel@tonic-gate 	}
3330Sstevel@tonic-gate 	return (0);
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate #ifdef PORTMAP
3370Sstevel@tonic-gate static CLIENT *
clnt_com_create(addr,prog,vers,fdp,trans)3380Sstevel@tonic-gate clnt_com_create(addr, prog, vers, fdp, trans)
3390Sstevel@tonic-gate 	struct sockaddr_in *addr;
3400Sstevel@tonic-gate 	ulong_t prog;
3410Sstevel@tonic-gate 	ulong_t vers;
3420Sstevel@tonic-gate 	int *fdp;
3430Sstevel@tonic-gate 	char *trans;
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate 	CLIENT *clnt;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	if (strcmp(trans, "tcp") == 0) {
3480Sstevel@tonic-gate 		clnt = clnttcp_create(addr, prog, vers, fdp, 0, 0);
3490Sstevel@tonic-gate 	} else {
3500Sstevel@tonic-gate 		struct timeval to;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 		to.tv_sec = 5;
3530Sstevel@tonic-gate 		to.tv_usec = 0;
3540Sstevel@tonic-gate 		clnt = clntudp_create(addr, prog, vers, to, fdp);
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate 	if (clnt == (CLIENT *)NULL) {
3570Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo");
3580Sstevel@tonic-gate 		if (vers == MIN_VERS)
359*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("program %lu is not available\n", prog);
3600Sstevel@tonic-gate 		else
361*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf(
362*11563SVallish.Vaidyeshwara@Sun.COM 				"program %lu version %lu is not available\n",
3630Sstevel@tonic-gate 							prog, vers);
3640Sstevel@tonic-gate 		exit(1);
3650Sstevel@tonic-gate 	}
3660Sstevel@tonic-gate 	return (clnt);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate /*
3700Sstevel@tonic-gate  * If portnum is 0, then go and get the address from portmapper, which happens
3710Sstevel@tonic-gate  * transparently through clnt*_create(); If version number is not given, it
3720Sstevel@tonic-gate  * tries to find out the version number by making a call to version 0 and if
3730Sstevel@tonic-gate  * that fails, it obtains the high order and the low order version number. If
3740Sstevel@tonic-gate  * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
3750Sstevel@tonic-gate  */
3760Sstevel@tonic-gate static void
ip_ping(portnum,trans,argc,argv)3770Sstevel@tonic-gate ip_ping(portnum, trans, argc, argv)
3780Sstevel@tonic-gate 	ushort_t portnum;
3790Sstevel@tonic-gate 	char *trans;
3800Sstevel@tonic-gate 	int argc;
3810Sstevel@tonic-gate 	char **argv;
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	CLIENT *client;
3840Sstevel@tonic-gate 	int fd = RPC_ANYFD;
3850Sstevel@tonic-gate 	struct timeval to;
3860Sstevel@tonic-gate 	struct sockaddr_in addr;
3870Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
3880Sstevel@tonic-gate 	ulong_t prognum, vers, minvers, maxvers;
3890Sstevel@tonic-gate 	struct rpc_err rpcerr;
3900Sstevel@tonic-gate 	int failure = 0;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	if (argc < 2 || argc > 3) {
3930Sstevel@tonic-gate 		usage();
3940Sstevel@tonic-gate 		exit(1);
3950Sstevel@tonic-gate 	}
3960Sstevel@tonic-gate 	to.tv_sec = 10;
3970Sstevel@tonic-gate 	to.tv_usec = 0;
3980Sstevel@tonic-gate 	prognum = getprognum(argv[1]);
3990Sstevel@tonic-gate 	get_inet_address(&addr, argv[0]);
4000Sstevel@tonic-gate 	if (argc == 2) {	/* Version number not known */
4010Sstevel@tonic-gate 		/*
4020Sstevel@tonic-gate 		 * A call to version 0 should fail with a program/version
4030Sstevel@tonic-gate 		 * mismatch, and give us the range of versions supported.
4040Sstevel@tonic-gate 		 */
4050Sstevel@tonic-gate 		vers = MIN_VERS;
4060Sstevel@tonic-gate 	} else {
4070Sstevel@tonic-gate 		vers = getvers(argv[2]);
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 	addr.sin_port = htons(portnum);
4100Sstevel@tonic-gate 	client = clnt_com_create(&addr, prognum, vers, &fd, trans);
4110Sstevel@tonic-gate 	rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
4120Sstevel@tonic-gate 			(char *)NULL, (xdrproc_t)xdr_void, (char *)NULL,
4130Sstevel@tonic-gate 			to);
4140Sstevel@tonic-gate 	if (argc != 2) {
4150Sstevel@tonic-gate 		/* Version number was known */
4160Sstevel@tonic-gate 		if (pstatus(client, prognum, vers) < 0)
4170Sstevel@tonic-gate 			exit(1);
4180Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
4190Sstevel@tonic-gate 		return;
4200Sstevel@tonic-gate 	}
4210Sstevel@tonic-gate 	/* Version number not known */
4220Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
4230Sstevel@tonic-gate 	if (rpc_stat == RPC_PROGVERSMISMATCH) {
4240Sstevel@tonic-gate 		clnt_geterr(client, &rpcerr);
4250Sstevel@tonic-gate 		minvers = rpcerr.re_vers.low;
4260Sstevel@tonic-gate 		maxvers = rpcerr.re_vers.high;
4270Sstevel@tonic-gate 	} else if (rpc_stat == RPC_SUCCESS) {
4280Sstevel@tonic-gate 		/*
4290Sstevel@tonic-gate 		 * Oh dear, it DOES support version 0.
4300Sstevel@tonic-gate 		 * Let's try version MAX_VERS.
4310Sstevel@tonic-gate 		 */
4320Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
4330Sstevel@tonic-gate 		addr.sin_port = htons(portnum);
4340Sstevel@tonic-gate 		client = clnt_com_create(&addr, prognum, MAX_VERS, &fd, trans);
4350Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
4360Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
4370Sstevel@tonic-gate 				(char *)NULL, to);
4380Sstevel@tonic-gate 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
4390Sstevel@tonic-gate 			clnt_geterr(client, &rpcerr);
4400Sstevel@tonic-gate 			minvers = rpcerr.re_vers.low;
4410Sstevel@tonic-gate 			maxvers = rpcerr.re_vers.high;
4420Sstevel@tonic-gate 		} else if (rpc_stat == RPC_SUCCESS) {
4430Sstevel@tonic-gate 			/*
4440Sstevel@tonic-gate 			 * It also supports version MAX_VERS.
4450Sstevel@tonic-gate 			 * Looks like we have a wise guy.
4460Sstevel@tonic-gate 			 * OK, we give them information on all
4470Sstevel@tonic-gate 			 * 4 billion versions they support...
4480Sstevel@tonic-gate 			 */
4490Sstevel@tonic-gate 			minvers = 0;
4500Sstevel@tonic-gate 			maxvers = MAX_VERS;
4510Sstevel@tonic-gate 		} else {
4520Sstevel@tonic-gate 			(void) pstatus(client, prognum, MAX_VERS);
4530Sstevel@tonic-gate 			exit(1);
4540Sstevel@tonic-gate 		}
4550Sstevel@tonic-gate 	} else {
4560Sstevel@tonic-gate 		(void) pstatus(client, prognum, (ulong_t)0);
4570Sstevel@tonic-gate 		exit(1);
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 	(void) CLNT_DESTROY(client);
4600Sstevel@tonic-gate 	for (vers = minvers; vers <= maxvers; vers++) {
4610Sstevel@tonic-gate 		addr.sin_port = htons(portnum);
4620Sstevel@tonic-gate 		client = clnt_com_create(&addr, prognum, vers, &fd, trans);
4630Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
4640Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
4650Sstevel@tonic-gate 				(char *)NULL, to);
4660Sstevel@tonic-gate 		if (pstatus(client, prognum, vers) < 0)
4670Sstevel@tonic-gate 				failure = 1;
4680Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
4690Sstevel@tonic-gate 	}
4700Sstevel@tonic-gate 	if (failure)
4710Sstevel@tonic-gate 		exit(1);
4720Sstevel@tonic-gate 	(void) t_close(fd);
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate /*
4760Sstevel@tonic-gate  * Dump all the portmapper registerations
4770Sstevel@tonic-gate  */
4780Sstevel@tonic-gate static void
pmapdump(argc,argv)4790Sstevel@tonic-gate pmapdump(argc, argv)
4800Sstevel@tonic-gate 	int argc;
4810Sstevel@tonic-gate 	char **argv;
4820Sstevel@tonic-gate {
4830Sstevel@tonic-gate 	struct sockaddr_in server_addr;
4840Sstevel@tonic-gate 	pmaplist_ptr head = NULL;
4850Sstevel@tonic-gate 	int socket = RPC_ANYSOCK;
4860Sstevel@tonic-gate 	struct timeval minutetimeout;
4870Sstevel@tonic-gate 	register CLIENT *client;
4880Sstevel@tonic-gate 	struct rpcent *rpc;
4890Sstevel@tonic-gate 	enum clnt_stat clnt_st;
4900Sstevel@tonic-gate 	struct rpc_err err;
4910Sstevel@tonic-gate 	struct utsname utsname;
4920Sstevel@tonic-gate 	char *host;
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	if (argc > 1) {
4950Sstevel@tonic-gate 		usage();
4960Sstevel@tonic-gate 		exit(1);
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 	if (argc == 1) {
4990Sstevel@tonic-gate 		host = argv[0];
5000Sstevel@tonic-gate 		get_inet_address(&server_addr, host);
5010Sstevel@tonic-gate 	} else {
502*11563SVallish.Vaidyeshwara@Sun.COM 		(void) uname(&utsname);
5030Sstevel@tonic-gate 		host = utsname.nodename;
5040Sstevel@tonic-gate 		get_inet_address(&server_addr, host);
5050Sstevel@tonic-gate 	}
5060Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
5070Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
5080Sstevel@tonic-gate 	server_addr.sin_port = htons(PMAPPORT);
5090Sstevel@tonic-gate 	if ((client = clnttcp_create(&server_addr, PMAPPROG,
5100Sstevel@tonic-gate 		PMAPVERS, &socket, 50, 500)) == NULL) {
5110Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_TLIERROR) {
5120Sstevel@tonic-gate 			/*
5130Sstevel@tonic-gate 			 * "Misc. TLI error" is not too helpful. Most likely
5140Sstevel@tonic-gate 			 * the connection to the remote server timed out, so
5150Sstevel@tonic-gate 			 * this error is at least less perplexing.
5160Sstevel@tonic-gate 			 */
5170Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
5180Sstevel@tonic-gate 			rpc_createerr.cf_error.re_status = RPC_FAILED;
5190Sstevel@tonic-gate 		}
5200Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact portmapper");
5210Sstevel@tonic-gate 		exit(1);
5220Sstevel@tonic-gate 	}
5230Sstevel@tonic-gate 	clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t)xdr_void,
5240Sstevel@tonic-gate 		NULL, (xdrproc_t)xdr_pmaplist_ptr, (char *)&head,
5250Sstevel@tonic-gate 		minutetimeout);
5260Sstevel@tonic-gate 	if (clnt_st != RPC_SUCCESS) {
5270Sstevel@tonic-gate 		if ((clnt_st == RPC_PROGVERSMISMATCH) ||
5280Sstevel@tonic-gate 		    (clnt_st == RPC_PROGUNAVAIL)) {
5290Sstevel@tonic-gate 			CLNT_GETERR(client, &err);
5300Sstevel@tonic-gate 			if (err.re_vers.low > PMAPVERS)
531*11563SVallish.Vaidyeshwara@Sun.COM 				(void) fprintf(stderr,
5320Sstevel@tonic-gate 		"%s does not support portmapper.  Try rpcinfo %s instead\n",
5330Sstevel@tonic-gate 					host, host);
5340Sstevel@tonic-gate 			exit(1);
5350Sstevel@tonic-gate 		}
5360Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo: can't contact portmapper");
5370Sstevel@tonic-gate 		exit(1);
5380Sstevel@tonic-gate 	}
5390Sstevel@tonic-gate 	if (head == NULL) {
540*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("No remote programs registered.\n");
5410Sstevel@tonic-gate 	} else {
542*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("   program vers proto   port  service\n");
5430Sstevel@tonic-gate 		for (; head != NULL; head = head->pml_next) {
544*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%10ld%5ld",
5450Sstevel@tonic-gate 				head->pml_map.pm_prog,
5460Sstevel@tonic-gate 				head->pml_map.pm_vers);
5470Sstevel@tonic-gate 			if (head->pml_map.pm_prot == IPPROTO_UDP)
548*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf("%6s", "udp");
5490Sstevel@tonic-gate 			else if (head->pml_map.pm_prot == IPPROTO_TCP)
550*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf("%6s", "tcp");
5510Sstevel@tonic-gate 			else
552*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf("%6ld", head->pml_map.pm_prot);
553*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%7ld", head->pml_map.pm_port);
5540Sstevel@tonic-gate 			rpc = getrpcbynumber(head->pml_map.pm_prog);
5550Sstevel@tonic-gate 			if (rpc)
556*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf("  %s\n", rpc->r_name);
5570Sstevel@tonic-gate 			else
558*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf("\n");
5590Sstevel@tonic-gate 		}
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate static void
get_inet_address(addr,host)5640Sstevel@tonic-gate get_inet_address(addr, host)
5650Sstevel@tonic-gate 	struct sockaddr_in *addr;
5660Sstevel@tonic-gate 	char *host;
5670Sstevel@tonic-gate {
5680Sstevel@tonic-gate 	struct netconfig *nconf;
5690Sstevel@tonic-gate 	struct nd_hostserv service;
5700Sstevel@tonic-gate 	struct nd_addrlist *naddrs;
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	(void) memset((char *)addr, 0, sizeof (*addr));
5730Sstevel@tonic-gate 	addr->sin_addr.s_addr = inet_addr(host);
574*11563SVallish.Vaidyeshwara@Sun.COM 	if (addr->sin_addr.s_addr == (uint32_t)-1 ||
575*11563SVallish.Vaidyeshwara@Sun.COM 	    addr->sin_addr.s_addr == 0) {
5760Sstevel@tonic-gate 		if ((nconf = __rpc_getconfip("udp")) == NULL &&
5770Sstevel@tonic-gate 		    (nconf = __rpc_getconfip("tcp")) == NULL) {
578*11563SVallish.Vaidyeshwara@Sun.COM 			(void) fprintf(stderr,
5790Sstevel@tonic-gate 			"rpcinfo: couldn't find a suitable transport\n");
5800Sstevel@tonic-gate 			exit(1);
5810Sstevel@tonic-gate 		} else {
5820Sstevel@tonic-gate 			service.h_host = host;
5830Sstevel@tonic-gate 			service.h_serv = "rpcbind";
5840Sstevel@tonic-gate 			if (netdir_getbyname(nconf, &service, &naddrs)) {
585*11563SVallish.Vaidyeshwara@Sun.COM 				(void) fprintf(stderr, "rpcinfo: %s: %s\n",
5860Sstevel@tonic-gate 						host, netdir_sperror());
5870Sstevel@tonic-gate 				exit(1);
5880Sstevel@tonic-gate 			} else {
5890Sstevel@tonic-gate 				(void) memcpy((caddr_t)addr,
5900Sstevel@tonic-gate 				    naddrs->n_addrs->buf, naddrs->n_addrs->len);
5910Sstevel@tonic-gate 				(void) netdir_free((char *)naddrs, ND_ADDRLIST);
5920Sstevel@tonic-gate 			}
5930Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
5940Sstevel@tonic-gate 		}
5950Sstevel@tonic-gate 	} else {
5960Sstevel@tonic-gate 		addr->sin_family = AF_INET;
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate #endif /* PORTMAP */
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate /*
6020Sstevel@tonic-gate  * reply_proc collects replies from the broadcast.
6030Sstevel@tonic-gate  * to get a unique list of responses the output of rpcinfo should
6040Sstevel@tonic-gate  * be piped through sort(1) and then uniq(1).
6050Sstevel@tonic-gate  */
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate /*ARGSUSED*/
6080Sstevel@tonic-gate static bool_t
reply_proc(res,who,nconf)6090Sstevel@tonic-gate reply_proc(res, who, nconf)
6100Sstevel@tonic-gate 	void *res;		/* Nothing comes back */
6110Sstevel@tonic-gate 	struct netbuf *who;	/* Who sent us the reply */
6120Sstevel@tonic-gate 	struct netconfig *nconf; /* On which transport the reply came */
6130Sstevel@tonic-gate {
6140Sstevel@tonic-gate 	struct nd_hostservlist *serv;
6150Sstevel@tonic-gate 	char *uaddr;
6160Sstevel@tonic-gate 	char *hostname;
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	if (netdir_getbyaddr(nconf, &serv, who)) {
6190Sstevel@tonic-gate 		hostname = UNKNOWN;
6200Sstevel@tonic-gate 	} else {
6210Sstevel@tonic-gate 		hostname = serv->h_hostservs->h_host;
6220Sstevel@tonic-gate 	}
6230Sstevel@tonic-gate 	if (!(uaddr = taddr2uaddr(nconf, who))) {
6240Sstevel@tonic-gate 		uaddr = UNKNOWN;
6250Sstevel@tonic-gate 	}
626*11563SVallish.Vaidyeshwara@Sun.COM 	(void) printf("%s\t%s\n", uaddr, hostname);
6270Sstevel@tonic-gate 	if (strcmp(hostname, UNKNOWN))
6280Sstevel@tonic-gate 		netdir_free((char *)serv, ND_HOSTSERVLIST);
6290Sstevel@tonic-gate 	if (strcmp(uaddr, UNKNOWN))
6300Sstevel@tonic-gate 		free((char *)uaddr);
6310Sstevel@tonic-gate 	return (FALSE);
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate static void
brdcst(argc,argv)6350Sstevel@tonic-gate brdcst(argc, argv)
6360Sstevel@tonic-gate 	int argc;
6370Sstevel@tonic-gate 	char **argv;
6380Sstevel@tonic-gate {
6390Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
6400Sstevel@tonic-gate 	ulong_t prognum, vers;
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	if (argc != 2) {
6430Sstevel@tonic-gate 		usage();
6440Sstevel@tonic-gate 		exit(1);
6450Sstevel@tonic-gate 	}
6460Sstevel@tonic-gate 	prognum = getprognum(argv[0]);
6470Sstevel@tonic-gate 	vers = getvers(argv[1]);
6480Sstevel@tonic-gate 	rpc_stat = rpc_broadcast(prognum, vers, NULLPROC,
6490Sstevel@tonic-gate 		(xdrproc_t)xdr_void, (char *)NULL, (xdrproc_t)xdr_void,
6500Sstevel@tonic-gate 		(char *)NULL, (resultproc_t)reply_proc, NULL);
6510Sstevel@tonic-gate 	if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
652*11563SVallish.Vaidyeshwara@Sun.COM 		(void) fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
6530Sstevel@tonic-gate 			clnt_sperrno(rpc_stat));
6540Sstevel@tonic-gate 		exit(1);
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 	exit(0);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate static bool_t
add_version(rs,vers)6600Sstevel@tonic-gate add_version(rs, vers)
6610Sstevel@tonic-gate 	struct rpcbdump_short *rs;
6620Sstevel@tonic-gate 	ulong_t vers;
6630Sstevel@tonic-gate {
6640Sstevel@tonic-gate 	struct verslist *vl;
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 	for (vl = rs->vlist; vl; vl = vl->next)
6670Sstevel@tonic-gate 		if (vl->vers == vers)
6680Sstevel@tonic-gate 			break;
6690Sstevel@tonic-gate 	if (vl)
6700Sstevel@tonic-gate 		return (TRUE);
6710Sstevel@tonic-gate 	vl = (struct verslist *)malloc(sizeof (struct verslist));
6720Sstevel@tonic-gate 	if (vl == NULL)
6730Sstevel@tonic-gate 		return (FALSE);
6740Sstevel@tonic-gate 	vl->vers = vers;
6750Sstevel@tonic-gate 	vl->next = rs->vlist;
6760Sstevel@tonic-gate 	rs->vlist = vl;
6770Sstevel@tonic-gate 	return (TRUE);
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate static bool_t
add_netid(rs,netid)6810Sstevel@tonic-gate add_netid(rs, netid)
6820Sstevel@tonic-gate 	struct rpcbdump_short *rs;
6830Sstevel@tonic-gate 	char *netid;
6840Sstevel@tonic-gate {
6850Sstevel@tonic-gate 	struct netidlist *nl;
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 	for (nl = rs->nlist; nl; nl = nl->next)
6880Sstevel@tonic-gate 		if (strcmp(nl->netid, netid) == 0)
6890Sstevel@tonic-gate 			break;
6900Sstevel@tonic-gate 	if (nl)
6910Sstevel@tonic-gate 		return (TRUE);
6920Sstevel@tonic-gate 	nl = (struct netidlist *)malloc(sizeof (struct netidlist));
6930Sstevel@tonic-gate 	if (nl == NULL)
6940Sstevel@tonic-gate 		return (FALSE);
6950Sstevel@tonic-gate 	nl->netid = netid;
6960Sstevel@tonic-gate 	nl->next = rs->nlist;
6970Sstevel@tonic-gate 	rs->nlist = nl;
6980Sstevel@tonic-gate 	return (TRUE);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate static void
rpcbdump(dumptype,netid,argc,argv)7020Sstevel@tonic-gate rpcbdump(dumptype, netid, argc, argv)
7030Sstevel@tonic-gate 	int dumptype;
7040Sstevel@tonic-gate 	char *netid;
7050Sstevel@tonic-gate 	int argc;
7060Sstevel@tonic-gate 	char **argv;
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate 	rpcblist_ptr head = NULL;
7090Sstevel@tonic-gate 	struct timeval minutetimeout;
7100Sstevel@tonic-gate 	register CLIENT *client;
7110Sstevel@tonic-gate 	struct rpcent *rpc;
7120Sstevel@tonic-gate 	char *host;
7130Sstevel@tonic-gate 	struct netidlist *nl;
7140Sstevel@tonic-gate 	struct verslist *vl;
7150Sstevel@tonic-gate 	struct rpcbdump_short *rs, *rs_tail;
7160Sstevel@tonic-gate 	enum clnt_stat clnt_st;
7170Sstevel@tonic-gate 	struct rpc_err err;
7180Sstevel@tonic-gate 	struct utsname utsname;
7190Sstevel@tonic-gate 	struct rpcbdump_short *rs_head = NULL;
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	if (argc > 1) {
7220Sstevel@tonic-gate 		usage();
7230Sstevel@tonic-gate 		exit(1);
7240Sstevel@tonic-gate 	}
7250Sstevel@tonic-gate 	if (argc == 1) {
7260Sstevel@tonic-gate 		host = argv[0];
7270Sstevel@tonic-gate 	} else {
728*11563SVallish.Vaidyeshwara@Sun.COM 		(void) uname(&utsname);
7290Sstevel@tonic-gate 		host = utsname.nodename;
7300Sstevel@tonic-gate 	}
7310Sstevel@tonic-gate 	if (netid == NULL) {
7320Sstevel@tonic-gate 	    if (loopback_netid == NULL) {
7330Sstevel@tonic-gate 		client = clnt_rpcbind_create(host, RPCBVERS, NULL);
7340Sstevel@tonic-gate 	    } else {
7350Sstevel@tonic-gate 		client = getclnthandle(host, loopback_nconf, RPCBVERS, NULL);
7360Sstevel@tonic-gate 		if (client == NULL && rpc_createerr.cf_stat ==
7370Sstevel@tonic-gate 				RPC_N2AXLATEFAILURE) {
7380Sstevel@tonic-gate 			client = clnt_rpcbind_create(host, RPCBVERS, NULL);
7390Sstevel@tonic-gate 		}
7400Sstevel@tonic-gate 	    }
7410Sstevel@tonic-gate 	} else {
7420Sstevel@tonic-gate 		struct netconfig *nconf;
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
7450Sstevel@tonic-gate 		if (nconf == NULL) {
7460Sstevel@tonic-gate 			nc_perror("rpcinfo: invalid transport");
7470Sstevel@tonic-gate 			exit(1);
7480Sstevel@tonic-gate 		}
7490Sstevel@tonic-gate 		client = getclnthandle(host, nconf, RPCBVERS, NULL);
7500Sstevel@tonic-gate 		if (nconf)
7510Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
7520Sstevel@tonic-gate 	}
7530Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
7540Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact rpcbind");
7550Sstevel@tonic-gate 		exit(1);
7560Sstevel@tonic-gate 	}
7570Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
7580Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
7590Sstevel@tonic-gate 	clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, (xdrproc_t)xdr_void,
7600Sstevel@tonic-gate 		NULL, (xdrproc_t)xdr_rpcblist_ptr, (char *)&head,
7610Sstevel@tonic-gate 		minutetimeout);
7620Sstevel@tonic-gate 	if (clnt_st != RPC_SUCCESS) {
7630Sstevel@tonic-gate 	    if ((clnt_st == RPC_PROGVERSMISMATCH) ||
7640Sstevel@tonic-gate 		(clnt_st == RPC_PROGUNAVAIL)) {
7650Sstevel@tonic-gate 		int vers;
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 		CLNT_GETERR(client, &err);
7680Sstevel@tonic-gate 		if (err.re_vers.low == RPCBVERS4) {
7690Sstevel@tonic-gate 		    vers = RPCBVERS4;
7700Sstevel@tonic-gate 		    clnt_control(client, CLSET_VERS, (char *)&vers);
7710Sstevel@tonic-gate 		    clnt_st = CLNT_CALL(client, RPCBPROC_DUMP,
7720Sstevel@tonic-gate 			(xdrproc_t)xdr_void, NULL,
7730Sstevel@tonic-gate 			(xdrproc_t)xdr_rpcblist_ptr, (char *)&head,
7740Sstevel@tonic-gate 			minutetimeout);
7750Sstevel@tonic-gate 		    if (clnt_st != RPC_SUCCESS)
7760Sstevel@tonic-gate 			goto failed;
7770Sstevel@tonic-gate 		} else {
7780Sstevel@tonic-gate 		    if (err.re_vers.high == PMAPVERS) {
7790Sstevel@tonic-gate 			int high, low;
7800Sstevel@tonic-gate 			pmaplist_ptr pmaphead = NULL;
781*11563SVallish.Vaidyeshwara@Sun.COM 			rpcblist_ptr list, prev = NULL;
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 			vers = PMAPVERS;
7840Sstevel@tonic-gate 			clnt_control(client, CLSET_VERS, (char *)&vers);
7850Sstevel@tonic-gate 			clnt_st = CLNT_CALL(client, PMAPPROC_DUMP,
7860Sstevel@tonic-gate 				(xdrproc_t)xdr_void, NULL,
7870Sstevel@tonic-gate 				(xdrproc_t)xdr_pmaplist_ptr,
7880Sstevel@tonic-gate 				(char *)&pmaphead, minutetimeout);
7890Sstevel@tonic-gate 			if (clnt_st != RPC_SUCCESS)
7900Sstevel@tonic-gate 				goto failed;
7910Sstevel@tonic-gate 			/*
7920Sstevel@tonic-gate 			 * convert to rpcblist_ptr format
7930Sstevel@tonic-gate 			 */
7940Sstevel@tonic-gate 			for (head = NULL; pmaphead != NULL;
7950Sstevel@tonic-gate 				pmaphead = pmaphead->pml_next) {
7960Sstevel@tonic-gate 			    list = (rpcblist *)malloc(sizeof (rpcblist));
7970Sstevel@tonic-gate 			    if (list == NULL)
7980Sstevel@tonic-gate 				goto error;
7990Sstevel@tonic-gate 			    if (head == NULL)
8000Sstevel@tonic-gate 				head = list;
8010Sstevel@tonic-gate 			    else
8020Sstevel@tonic-gate 				prev->rpcb_next = (rpcblist_ptr) list;
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 			    list->rpcb_next = NULL;
8050Sstevel@tonic-gate 			    list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog;
8060Sstevel@tonic-gate 			    list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers;
8070Sstevel@tonic-gate 			    if (pmaphead->pml_map.pm_prot == IPPROTO_UDP)
8080Sstevel@tonic-gate 				list->rpcb_map.r_netid = "udp";
8090Sstevel@tonic-gate 			    else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP)
8100Sstevel@tonic-gate 				list->rpcb_map.r_netid = "tcp";
8110Sstevel@tonic-gate 			    else {
8120Sstevel@tonic-gate #define	MAXLONG_AS_STRING	"2147483648"
8130Sstevel@tonic-gate 				list->rpcb_map.r_netid =
8140Sstevel@tonic-gate 					malloc(strlen(MAXLONG_AS_STRING) + 1);
8150Sstevel@tonic-gate 				if (list->rpcb_map.r_netid == NULL)
8160Sstevel@tonic-gate 					goto error;
817*11563SVallish.Vaidyeshwara@Sun.COM 				(void) sprintf(list->rpcb_map.r_netid, "%6ld",
8180Sstevel@tonic-gate 					pmaphead->pml_map.pm_prot);
8190Sstevel@tonic-gate 			    }
8200Sstevel@tonic-gate 			    list->rpcb_map.r_owner = UNKNOWN;
8210Sstevel@tonic-gate 			    low = pmaphead->pml_map.pm_port & 0xff;
8220Sstevel@tonic-gate 			    high = (pmaphead->pml_map.pm_port >> 8) & 0xff;
8230Sstevel@tonic-gate 			    list->rpcb_map.r_addr = strdup("0.0.0.0.XXX.XXX");
824*11563SVallish.Vaidyeshwara@Sun.COM 			    (void) sprintf(&list->rpcb_map.r_addr[8], "%d.%d",
8250Sstevel@tonic-gate 				high, low);
8260Sstevel@tonic-gate 			    prev = list;
8270Sstevel@tonic-gate 			}
8280Sstevel@tonic-gate 		    }
8290Sstevel@tonic-gate 		}
8300Sstevel@tonic-gate 	    } else {	/* any other error */
8310Sstevel@tonic-gate failed:
8320Sstevel@tonic-gate 		    clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
8330Sstevel@tonic-gate 		    exit(1);
8340Sstevel@tonic-gate 	    }
8350Sstevel@tonic-gate 	}
8360Sstevel@tonic-gate 	if (head == NULL) {
837*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("No remote programs registered.\n");
8380Sstevel@tonic-gate 	} else if (dumptype == RPCBDUMP) {
839*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf(
8400Sstevel@tonic-gate "   program version netid     address             service    owner\n");
8410Sstevel@tonic-gate 		for (; head != NULL; head = head->rpcb_next) {
842*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%10ld%5ld    ",
8430Sstevel@tonic-gate 				head->rpcb_map.r_prog, head->rpcb_map.r_vers);
844*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-9s ", head->rpcb_map.r_netid);
845*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-19s", head->rpcb_map.r_addr);
8460Sstevel@tonic-gate 			rpc = getrpcbynumber(head->rpcb_map.r_prog);
8470Sstevel@tonic-gate 			if (rpc)
848*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf(" %-10s", rpc->r_name);
8490Sstevel@tonic-gate 			else
850*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf(" %-10s", "-");
851*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf(" %s\n", head->rpcb_map.r_owner);
8520Sstevel@tonic-gate 		}
8530Sstevel@tonic-gate 	} else if (dumptype == RPCBDUMP_SHORT) {
8540Sstevel@tonic-gate 		for (; head != NULL; head = head->rpcb_next) {
8550Sstevel@tonic-gate 			for (rs = rs_head; rs; rs = rs->next)
8560Sstevel@tonic-gate 				if (head->rpcb_map.r_prog == rs->prog)
8570Sstevel@tonic-gate 					break;
8580Sstevel@tonic-gate 			if (rs == NULL) {
8590Sstevel@tonic-gate 				rs = (struct rpcbdump_short *)
8600Sstevel@tonic-gate 					malloc(sizeof (struct rpcbdump_short));
8610Sstevel@tonic-gate 				if (rs == NULL)
8620Sstevel@tonic-gate 					goto error;
8630Sstevel@tonic-gate 				rs->next = NULL;
8640Sstevel@tonic-gate 				if (rs_head == NULL) {
8650Sstevel@tonic-gate 					rs_head = rs;
8660Sstevel@tonic-gate 					rs_tail = rs;
8670Sstevel@tonic-gate 				} else {
8680Sstevel@tonic-gate 					rs_tail->next = rs;
8690Sstevel@tonic-gate 					rs_tail = rs;
8700Sstevel@tonic-gate 				}
8710Sstevel@tonic-gate 				rs->prog = head->rpcb_map.r_prog;
8720Sstevel@tonic-gate 				rs->owner = head->rpcb_map.r_owner;
8730Sstevel@tonic-gate 				rs->nlist = NULL;
8740Sstevel@tonic-gate 				rs->vlist = NULL;
8750Sstevel@tonic-gate 			}
8760Sstevel@tonic-gate 			if (add_version(rs, head->rpcb_map.r_vers) == FALSE)
8770Sstevel@tonic-gate 				goto error;
8780Sstevel@tonic-gate 			if (add_netid(rs, head->rpcb_map.r_netid) == FALSE)
8790Sstevel@tonic-gate 				goto error;
8800Sstevel@tonic-gate 		}
881*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf(
8820Sstevel@tonic-gate "   program version(s) netid(s)                         service     owner\n");
8830Sstevel@tonic-gate 		for (rs = rs_head; rs; rs = rs->next) {
884*11563SVallish.Vaidyeshwara@Sun.COM 			int bytes_trans = 0;
885*11563SVallish.Vaidyeshwara@Sun.COM 			int len;
8860Sstevel@tonic-gate 
887*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%10ld  ", rs->prog);
8880Sstevel@tonic-gate 			for (vl = rs->vlist; vl; vl = vl->next) {
889*11563SVallish.Vaidyeshwara@Sun.COM 				bytes_trans += (len = printf("%d", vl->vers))
890*11563SVallish.Vaidyeshwara@Sun.COM 				    < 0 ? 0 : len;
8910Sstevel@tonic-gate 				if (vl->next)
892*11563SVallish.Vaidyeshwara@Sun.COM 					bytes_trans += (len = printf(",")) < 0
893*11563SVallish.Vaidyeshwara@Sun.COM 					    ? 0 : len;
8940Sstevel@tonic-gate 			}
895*11563SVallish.Vaidyeshwara@Sun.COM 			/*
896*11563SVallish.Vaidyeshwara@Sun.COM 			 * If number of bytes transferred is less than 10,
897*11563SVallish.Vaidyeshwara@Sun.COM 			 * align 10 bytes for version(s) column. If bytes
898*11563SVallish.Vaidyeshwara@Sun.COM 			 * transferred is more than 10, add a trailing white
899*11563SVallish.Vaidyeshwara@Sun.COM 			 * space.
900*11563SVallish.Vaidyeshwara@Sun.COM 			 */
901*11563SVallish.Vaidyeshwara@Sun.COM 			if (bytes_trans < 10)
902*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf("%*s", (bytes_trans - 10), " ");
903*11563SVallish.Vaidyeshwara@Sun.COM 			else
904*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf(" ");
905*11563SVallish.Vaidyeshwara@Sun.COM 
906*11563SVallish.Vaidyeshwara@Sun.COM 			bytes_trans = 0;
9070Sstevel@tonic-gate 			for (nl = rs->nlist; nl; nl = nl->next) {
908*11563SVallish.Vaidyeshwara@Sun.COM 				bytes_trans += (len = printf("%s", nl->netid))
909*11563SVallish.Vaidyeshwara@Sun.COM 				    < 0 ? 0 : len;
9100Sstevel@tonic-gate 				if (nl->next)
911*11563SVallish.Vaidyeshwara@Sun.COM 					bytes_trans += (len = printf(",")) < 0
912*11563SVallish.Vaidyeshwara@Sun.COM 					    ? 0 : len;
9130Sstevel@tonic-gate 			}
914*11563SVallish.Vaidyeshwara@Sun.COM 			/*
915*11563SVallish.Vaidyeshwara@Sun.COM 			 * Align netid(s) column output for 32 bytes.
916*11563SVallish.Vaidyeshwara@Sun.COM 			 */
917*11563SVallish.Vaidyeshwara@Sun.COM 			if (bytes_trans < 32)
918*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf("%*s", (bytes_trans - 32), " ");
919*11563SVallish.Vaidyeshwara@Sun.COM 
9200Sstevel@tonic-gate 			rpc = getrpcbynumber(rs->prog);
9210Sstevel@tonic-gate 			if (rpc)
922*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf(" %-11s", rpc->r_name);
9230Sstevel@tonic-gate 			else
924*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf(" %-11s", "-");
925*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf(" %s\n", rs->owner);
9260Sstevel@tonic-gate 		}
9270Sstevel@tonic-gate 	}
9280Sstevel@tonic-gate 	clnt_destroy(client);
9290Sstevel@tonic-gate 	return;
9300Sstevel@tonic-gate 
931*11563SVallish.Vaidyeshwara@Sun.COM error:	(void) fprintf(stderr, "rpcinfo: no memory\n");
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate static char nullstring[] = "\000";
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate static void
rpcbaddrlist(netid,argc,argv)9370Sstevel@tonic-gate rpcbaddrlist(netid, argc, argv)
9380Sstevel@tonic-gate 	char *netid;
9390Sstevel@tonic-gate 	int argc;
9400Sstevel@tonic-gate 	char **argv;
9410Sstevel@tonic-gate {
9420Sstevel@tonic-gate 	rpcb_entry_list_ptr head = NULL;
9430Sstevel@tonic-gate 	struct timeval minutetimeout;
9440Sstevel@tonic-gate 	register CLIENT *client;
9450Sstevel@tonic-gate 	struct rpcent *rpc;
9460Sstevel@tonic-gate 	char *host;
9470Sstevel@tonic-gate 	RPCB parms;
9480Sstevel@tonic-gate 	struct netbuf *targaddr;
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	if (argc != 3) {
9510Sstevel@tonic-gate 		usage();
9520Sstevel@tonic-gate 		exit(1);
9530Sstevel@tonic-gate 	}
9540Sstevel@tonic-gate 	host = argv[0];
9550Sstevel@tonic-gate 	if (netid == NULL) {
9560Sstevel@tonic-gate 	    if (loopback_netid == NULL) {
9570Sstevel@tonic-gate 		client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr);
9580Sstevel@tonic-gate 	    } else {
9590Sstevel@tonic-gate 		client = getclnthandle(host, loopback_nconf, RPCBVERS4,
9600Sstevel@tonic-gate 			&targaddr);
9610Sstevel@tonic-gate 		if (client == NULL && rpc_createerr.cf_stat ==
9620Sstevel@tonic-gate 				RPC_N2AXLATEFAILURE) {
9630Sstevel@tonic-gate 		    client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr);
9640Sstevel@tonic-gate 		}
9650Sstevel@tonic-gate 	    }
9660Sstevel@tonic-gate 	} else {
9670Sstevel@tonic-gate 		struct netconfig *nconf;
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
9700Sstevel@tonic-gate 		if (nconf == NULL) {
9710Sstevel@tonic-gate 			nc_perror("rpcinfo: invalid transport");
9720Sstevel@tonic-gate 			exit(1);
9730Sstevel@tonic-gate 		}
9740Sstevel@tonic-gate 		client = getclnthandle(host, nconf, RPCBVERS4, &targaddr);
9750Sstevel@tonic-gate 		if (nconf)
9760Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
9770Sstevel@tonic-gate 	}
9780Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
9790Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact rpcbind");
9800Sstevel@tonic-gate 		exit(1);
9810Sstevel@tonic-gate 	}
9820Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
9830Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate 	parms.r_prog = 	getprognum(argv[1]);
9860Sstevel@tonic-gate 	parms.r_vers = 	getvers(argv[2]);
9870Sstevel@tonic-gate 	parms.r_netid = client->cl_netid;
9880Sstevel@tonic-gate 	if (targaddr == NULL) {
9890Sstevel@tonic-gate 		parms.r_addr = nullstring;	/* for XDRing */
9900Sstevel@tonic-gate 	} else {
9910Sstevel@tonic-gate 		/*
9920Sstevel@tonic-gate 		 * We also send the remote system the address we
9930Sstevel@tonic-gate 		 * used to contact it in case it can help it
9940Sstevel@tonic-gate 		 * connect back with us
9950Sstevel@tonic-gate 		 */
9960Sstevel@tonic-gate 		struct netconfig *nconf;
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate 		nconf = getnetconfigent(client->cl_netid);
9990Sstevel@tonic-gate 		if (nconf != NULL) {
10000Sstevel@tonic-gate 			parms.r_addr = taddr2uaddr(nconf, targaddr);
10010Sstevel@tonic-gate 			if (parms.r_addr == NULL)
10020Sstevel@tonic-gate 				parms.r_addr = nullstring;
10030Sstevel@tonic-gate 			freenetconfigent(nconf);
10040Sstevel@tonic-gate 		} else {
10050Sstevel@tonic-gate 			parms.r_addr = nullstring;	/* for XDRing */
10060Sstevel@tonic-gate 		}
10070Sstevel@tonic-gate 		free(targaddr->buf);
10080Sstevel@tonic-gate 		free(targaddr);
10090Sstevel@tonic-gate 	}
10100Sstevel@tonic-gate 	parms.r_owner = nullstring;
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate 	if (CLNT_CALL(client, RPCBPROC_GETADDRLIST, (xdrproc_t)xdr_rpcb,
10130Sstevel@tonic-gate 		(char *)&parms, (xdrproc_t)xdr_rpcb_entry_list_ptr,
10140Sstevel@tonic-gate 		(char *)&head, minutetimeout) != RPC_SUCCESS) {
10150Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
10160Sstevel@tonic-gate 		exit(1);
10170Sstevel@tonic-gate 	}
10180Sstevel@tonic-gate 	if (head == NULL) {
1019*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("No remote programs registered.\n");
10200Sstevel@tonic-gate 	} else {
1021*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf(
10220Sstevel@tonic-gate 	"   program vers  tp_family/name/class    address\t\t  service\n");
10230Sstevel@tonic-gate 		for (; head != NULL; head = head->rpcb_entry_next) {
10240Sstevel@tonic-gate 			rpcb_entry *re;
10250Sstevel@tonic-gate 			char buf[128];
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 			re = &head->rpcb_entry_map;
1028*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%10ld%3ld    ",
10290Sstevel@tonic-gate 				parms.r_prog, parms.r_vers);
1030*11563SVallish.Vaidyeshwara@Sun.COM 			(void) snprintf(buf, sizeof (buf), "%s/%s/%s ",
10310Sstevel@tonic-gate 				re->r_nc_protofmly, re->r_nc_proto,
10320Sstevel@tonic-gate 				re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
10330Sstevel@tonic-gate 				re->r_nc_semantics == NC_TPI_COTS ? "cots" :
10340Sstevel@tonic-gate 						"cots_ord");
1035*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-24s", buf);
1036*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-24s", re->r_maddr);
10370Sstevel@tonic-gate 			rpc = getrpcbynumber(parms.r_prog);
10380Sstevel@tonic-gate 			if (rpc)
1039*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf(" %-13s", rpc->r_name);
10400Sstevel@tonic-gate 			else
1041*11563SVallish.Vaidyeshwara@Sun.COM 				(void) printf(" %-13s", "-");
1042*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("\n");
10430Sstevel@tonic-gate 		}
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 	clnt_destroy(client);
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate /*
10490Sstevel@tonic-gate  * monitor rpcbind
10500Sstevel@tonic-gate  */
10510Sstevel@tonic-gate static void
rpcbgetstat(argc,argv)10520Sstevel@tonic-gate rpcbgetstat(argc, argv)
10530Sstevel@tonic-gate 	int argc;
10540Sstevel@tonic-gate 	char **argv;
10550Sstevel@tonic-gate {
10560Sstevel@tonic-gate 	rpcb_stat_byvers inf;
10570Sstevel@tonic-gate 	struct timeval minutetimeout;
10580Sstevel@tonic-gate 	register CLIENT *client;
10590Sstevel@tonic-gate 	char *host;
10600Sstevel@tonic-gate 	int i, j;
10610Sstevel@tonic-gate 	rpcbs_addrlist *pa;
10620Sstevel@tonic-gate 	rpcbs_rmtcalllist *pr;
10630Sstevel@tonic-gate 	int cnt, flen;
10640Sstevel@tonic-gate 	struct utsname utsname;
10650Sstevel@tonic-gate #define	MAXFIELD	64
10660Sstevel@tonic-gate 	char fieldbuf[MAXFIELD];
10670Sstevel@tonic-gate #define	MAXLINE		256
10680Sstevel@tonic-gate 	char linebuf[MAXLINE];
1069*11563SVallish.Vaidyeshwara@Sun.COM 	char *cp, *lp;
10700Sstevel@tonic-gate 	char *pmaphdr[] = {
10710Sstevel@tonic-gate 		"NULL", "SET", "UNSET", "GETPORT",
10720Sstevel@tonic-gate 		"DUMP", "CALLIT"
10730Sstevel@tonic-gate 	};
10740Sstevel@tonic-gate 	char *rpcb3hdr[] = {
10750Sstevel@tonic-gate 		"NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
10760Sstevel@tonic-gate 		"U2T", "T2U"
10770Sstevel@tonic-gate 	};
10780Sstevel@tonic-gate 	char *rpcb4hdr[] = {
10790Sstevel@tonic-gate 		"NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
10800Sstevel@tonic-gate 		"U2T",  "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
10810Sstevel@tonic-gate 	};
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate #define	TABSTOP	8
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate 	if (argc >= 1) {
10860Sstevel@tonic-gate 		host = argv[0];
10870Sstevel@tonic-gate 	} else {
1088*11563SVallish.Vaidyeshwara@Sun.COM 		(void) uname(&utsname);
10890Sstevel@tonic-gate 		host = utsname.nodename;
10900Sstevel@tonic-gate 	}
10910Sstevel@tonic-gate 	if (loopback_netid != NULL) {
10920Sstevel@tonic-gate 		client = getclnthandle(host, loopback_nconf, RPCBVERS4, NULL);
10930Sstevel@tonic-gate 		if (client == NULL && rpc_createerr.cf_stat ==
10940Sstevel@tonic-gate 				RPC_N2AXLATEFAILURE) {
10950Sstevel@tonic-gate 			client = clnt_rpcbind_create(host, RPCBVERS4, NULL);
10960Sstevel@tonic-gate 		}
10970Sstevel@tonic-gate 	} else {
10980Sstevel@tonic-gate 		client = clnt_rpcbind_create(host, RPCBVERS4, NULL);
10990Sstevel@tonic-gate 	}
11000Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
11010Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact rpcbind");
11020Sstevel@tonic-gate 		exit(1);
11030Sstevel@tonic-gate 	}
11040Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
11050Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
1106*11563SVallish.Vaidyeshwara@Sun.COM 	(void) memset((char *)&inf, 0, sizeof (rpcb_stat_byvers));
11070Sstevel@tonic-gate 	if (CLNT_CALL(client, RPCBPROC_GETSTAT, (xdrproc_t)xdr_void, NULL,
11080Sstevel@tonic-gate 		(xdrproc_t)xdr_rpcb_stat_byvers, (char *)&inf, minutetimeout)
11090Sstevel@tonic-gate 			!= RPC_SUCCESS) {
11100Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
11110Sstevel@tonic-gate 		exit(1);
11120Sstevel@tonic-gate 	}
1113*11563SVallish.Vaidyeshwara@Sun.COM 	(void) printf("PORTMAP (version 2) statistics\n");
11140Sstevel@tonic-gate 	lp = linebuf;
11150Sstevel@tonic-gate 	for (i = 0; i <= rpcb_highproc_2; i++) {
11160Sstevel@tonic-gate 		fieldbuf[0] = '\0';
11170Sstevel@tonic-gate 		switch (i) {
11180Sstevel@tonic-gate 		case PMAPPROC_SET:
1119*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/",
1120*11563SVallish.Vaidyeshwara@Sun.COM 				inf[RPCBVERS_2_STAT].setinfo);
11210Sstevel@tonic-gate 			break;
11220Sstevel@tonic-gate 		case PMAPPROC_UNSET:
1123*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/",
11240Sstevel@tonic-gate 				inf[RPCBVERS_2_STAT].unsetinfo);
11250Sstevel@tonic-gate 			break;
11260Sstevel@tonic-gate 		case PMAPPROC_GETPORT:
11270Sstevel@tonic-gate 			cnt = 0;
11280Sstevel@tonic-gate 			for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa;
11290Sstevel@tonic-gate 				pa = pa->next)
11300Sstevel@tonic-gate 				cnt += pa->success;
1131*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/", cnt);
11320Sstevel@tonic-gate 			break;
11330Sstevel@tonic-gate 		case PMAPPROC_CALLIT:
11340Sstevel@tonic-gate 			cnt = 0;
11350Sstevel@tonic-gate 			for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr;
11360Sstevel@tonic-gate 				pr = pr->next)
11370Sstevel@tonic-gate 				cnt += pr->success;
1138*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/", cnt);
11390Sstevel@tonic-gate 			break;
11400Sstevel@tonic-gate 		default: break;  /* For the remaining ones */
11410Sstevel@tonic-gate 		}
11420Sstevel@tonic-gate 		cp = &fieldbuf[0] + strlen(fieldbuf);
1143*11563SVallish.Vaidyeshwara@Sun.COM 		(void) sprintf(cp, "%d", inf[RPCBVERS_2_STAT].info[i]);
11440Sstevel@tonic-gate 		flen = strlen(fieldbuf);
1145*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("%s%s", pmaphdr[i],
1146*11563SVallish.Vaidyeshwara@Sun.COM 			spaces((int)((TABSTOP * (1 + flen / TABSTOP))
1147*11563SVallish.Vaidyeshwara@Sun.COM 			- strlen(pmaphdr[i]))));
1148*11563SVallish.Vaidyeshwara@Sun.COM 		(void) snprintf(lp, (MAXLINE - (lp - linebuf)), "%s%s",
1149*11563SVallish.Vaidyeshwara@Sun.COM 			fieldbuf, spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
11500Sstevel@tonic-gate 			- flen)));
11510Sstevel@tonic-gate 		lp += (flen + cnt);
11520Sstevel@tonic-gate 	}
1153*11563SVallish.Vaidyeshwara@Sun.COM 	(void) printf("\n%s\n\n", linebuf);
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate 	if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT]) {
1156*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("PMAP_RMTCALL call statistics\n");
11570Sstevel@tonic-gate 		print_rmtcallstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
1158*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("\n");
11590Sstevel@tonic-gate 	}
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate 	if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT]) {
1162*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("PMAP_GETPORT call statistics\n");
11630Sstevel@tonic-gate 		print_getaddrstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
1164*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("\n");
11650Sstevel@tonic-gate 	}
11660Sstevel@tonic-gate 
1167*11563SVallish.Vaidyeshwara@Sun.COM 	(void) printf("RPCBIND (version 3) statistics\n");
11680Sstevel@tonic-gate 	lp = linebuf;
11690Sstevel@tonic-gate 	for (i = 0; i <= rpcb_highproc_3; i++) {
11700Sstevel@tonic-gate 		fieldbuf[0] = '\0';
11710Sstevel@tonic-gate 		switch (i) {
11720Sstevel@tonic-gate 		case RPCBPROC_SET:
1173*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/",
1174*11563SVallish.Vaidyeshwara@Sun.COM 				inf[RPCBVERS_3_STAT].setinfo);
11750Sstevel@tonic-gate 			break;
11760Sstevel@tonic-gate 		case RPCBPROC_UNSET:
1177*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/",
11780Sstevel@tonic-gate 				inf[RPCBVERS_3_STAT].unsetinfo);
11790Sstevel@tonic-gate 			break;
11800Sstevel@tonic-gate 		case RPCBPROC_GETADDR:
11810Sstevel@tonic-gate 			cnt = 0;
11820Sstevel@tonic-gate 			for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa;
11830Sstevel@tonic-gate 				pa = pa->next)
11840Sstevel@tonic-gate 				cnt += pa->success;
1185*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/", cnt);
11860Sstevel@tonic-gate 			break;
11870Sstevel@tonic-gate 		case RPCBPROC_CALLIT:
11880Sstevel@tonic-gate 			cnt = 0;
11890Sstevel@tonic-gate 			for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr;
11900Sstevel@tonic-gate 				pr = pr->next)
11910Sstevel@tonic-gate 				cnt += pr->success;
1192*11563SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(fieldbuf, "%d/", cnt);
11930Sstevel@tonic-gate 			break;
11940Sstevel@tonic-gate 		default: break;  /* For the remaining ones */
11950Sstevel@tonic-gate 		}
11960Sstevel@tonic-gate 		cp = &fieldbuf[0] + strlen(fieldbuf);
1197*11563SVallish.Vaidyeshwara@Sun.COM 		(void) sprintf(cp, "%d", inf[RPCBVERS_3_STAT].info[i]);
11980Sstevel@tonic-gate 		flen = strlen(fieldbuf);
1199*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("%s%s", rpcb3hdr[i],
1200*11563SVallish.Vaidyeshwara@Sun.COM 			spaces((int)((TABSTOP * (1 + flen / TABSTOP))
1201*11563SVallish.Vaidyeshwara@Sun.COM 			- strlen(rpcb3hdr[i]))));
1202*11563SVallish.Vaidyeshwara@Sun.COM 		(void) snprintf(lp, (MAXLINE - (lp - linebuf)), "%s%s",
1203*11563SVallish.Vaidyeshwara@Sun.COM 			fieldbuf, spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
12040Sstevel@tonic-gate 			- flen)));
12050Sstevel@tonic-gate 		lp += (flen + cnt);
12060Sstevel@tonic-gate 	}
1207*11563SVallish.Vaidyeshwara@Sun.COM 	(void) printf("\n%s\n\n", linebuf);
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate 	if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT]) {
1210*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("RPCB_RMTCALL (version 3) call statistics\n");
12110Sstevel@tonic-gate 		print_rmtcallstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
1212*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("\n");
12130Sstevel@tonic-gate 	}
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 	if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR]) {
1216*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("RPCB_GETADDR (version 3) call statistics\n");
12170Sstevel@tonic-gate 		print_getaddrstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
1218*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("\n");
12190Sstevel@tonic-gate 	}
12200Sstevel@tonic-gate 
1221*11563SVallish.Vaidyeshwara@Sun.COM 	(void) printf("RPCBIND (version 4) statistics\n");
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 	for (j = 0; j <= 9; j += 9) { /* Just two iterations for printing */
12240Sstevel@tonic-gate 		lp = linebuf;
12250Sstevel@tonic-gate 		for (i = j; i <= MAX(8, rpcb_highproc_4 - 9 + j); i++) {
12260Sstevel@tonic-gate 			fieldbuf[0] = '\0';
12270Sstevel@tonic-gate 			switch (i) {
12280Sstevel@tonic-gate 			case RPCBPROC_SET:
1229*11563SVallish.Vaidyeshwara@Sun.COM 				(void) sprintf(fieldbuf, "%d/",
12300Sstevel@tonic-gate 					inf[RPCBVERS_4_STAT].setinfo);
12310Sstevel@tonic-gate 				break;
12320Sstevel@tonic-gate 			case RPCBPROC_UNSET:
1233*11563SVallish.Vaidyeshwara@Sun.COM 				(void) sprintf(fieldbuf, "%d/",
12340Sstevel@tonic-gate 					inf[RPCBVERS_4_STAT].unsetinfo);
12350Sstevel@tonic-gate 				break;
12360Sstevel@tonic-gate 			case RPCBPROC_GETADDR:
12370Sstevel@tonic-gate 				cnt = 0;
12380Sstevel@tonic-gate 				for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa;
12390Sstevel@tonic-gate 					pa = pa->next)
12400Sstevel@tonic-gate 					cnt += pa->success;
1241*11563SVallish.Vaidyeshwara@Sun.COM 				(void) sprintf(fieldbuf, "%d/", cnt);
12420Sstevel@tonic-gate 				break;
12430Sstevel@tonic-gate 			case RPCBPROC_CALLIT:
12440Sstevel@tonic-gate 				cnt = 0;
12450Sstevel@tonic-gate 				for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr;
12460Sstevel@tonic-gate 					pr = pr->next)
12470Sstevel@tonic-gate 					cnt += pr->success;
1248*11563SVallish.Vaidyeshwara@Sun.COM 				(void) sprintf(fieldbuf, "%d/", cnt);
12490Sstevel@tonic-gate 				break;
12500Sstevel@tonic-gate 			default: break;  /* For the remaining ones */
12510Sstevel@tonic-gate 			}
12520Sstevel@tonic-gate 			cp = &fieldbuf[0] + strlen(fieldbuf);
12530Sstevel@tonic-gate 			/*
12540Sstevel@tonic-gate 			 * XXX: We also add RPCBPROC_GETADDRLIST queries to
12550Sstevel@tonic-gate 			 * RPCB_GETADDR because rpcbind includes the
12560Sstevel@tonic-gate 			 * RPCB_GETADDRLIST successes in RPCB_GETADDR.
12570Sstevel@tonic-gate 			 */
12580Sstevel@tonic-gate 			if (i != RPCBPROC_GETADDR)
1259*11563SVallish.Vaidyeshwara@Sun.COM 			    (void) sprintf(cp, "%d",
1260*11563SVallish.Vaidyeshwara@Sun.COM 				inf[RPCBVERS_4_STAT].info[i]);
12610Sstevel@tonic-gate 			else
1262*11563SVallish.Vaidyeshwara@Sun.COM 			    (void) sprintf(cp, "%d",
1263*11563SVallish.Vaidyeshwara@Sun.COM 			    inf[RPCBVERS_4_STAT].info[i] +
12640Sstevel@tonic-gate 			    inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]);
12650Sstevel@tonic-gate 			flen = strlen(fieldbuf);
1266*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%s%s", rpcb4hdr[i],
1267*11563SVallish.Vaidyeshwara@Sun.COM 				spaces((int)((TABSTOP * (1 + flen / TABSTOP))
1268*11563SVallish.Vaidyeshwara@Sun.COM 				- strlen(rpcb4hdr[i]))));
1269*11563SVallish.Vaidyeshwara@Sun.COM 			(void) snprintf(lp, MAXLINE - (lp - linebuf), "%s%s",
1270*11563SVallish.Vaidyeshwara@Sun.COM 				fieldbuf, spaces(cnt =
1271*11563SVallish.Vaidyeshwara@Sun.COM 				((TABSTOP * (1 + flen / TABSTOP)) - flen)));
12720Sstevel@tonic-gate 			lp += (flen + cnt);
12730Sstevel@tonic-gate 		}
1274*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("\n%s\n", linebuf);
12750Sstevel@tonic-gate 	}
12760Sstevel@tonic-gate 
12770Sstevel@tonic-gate 	if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] ||
12780Sstevel@tonic-gate 			    inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT]) {
1279*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("\n");
1280*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("RPCB_RMTCALL (version 4) call statistics\n");
12810Sstevel@tonic-gate 		print_rmtcallstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
12820Sstevel@tonic-gate 	}
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 	if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR]) {
1285*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("\n");
1286*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("RPCB_GETADDR (version 4) call statistics\n");
12870Sstevel@tonic-gate 		print_getaddrstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
12880Sstevel@tonic-gate 	}
12890Sstevel@tonic-gate 	clnt_destroy(client);
12900Sstevel@tonic-gate }
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate /*
12930Sstevel@tonic-gate  * Delete registeration for this (prog, vers, netid)
12940Sstevel@tonic-gate  */
12950Sstevel@tonic-gate static void
deletereg(netid,argc,argv)12960Sstevel@tonic-gate deletereg(netid, argc, argv)
12970Sstevel@tonic-gate 	char *netid;
12980Sstevel@tonic-gate 	int argc;
12990Sstevel@tonic-gate 	char **argv;
13000Sstevel@tonic-gate {
13010Sstevel@tonic-gate 	struct netconfig *nconf = NULL;
13020Sstevel@tonic-gate 
13030Sstevel@tonic-gate 	if (argc != 2) {
13040Sstevel@tonic-gate 		usage();
13050Sstevel@tonic-gate 		exit(1);
13060Sstevel@tonic-gate 	}
13070Sstevel@tonic-gate 	if (netid) {
13080Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
13090Sstevel@tonic-gate 		if (nconf == NULL) {
1310*11563SVallish.Vaidyeshwara@Sun.COM 			(void) fprintf(stderr,
1311*11563SVallish.Vaidyeshwara@Sun.COM 				"rpcinfo: netid %s not supported\n", netid);
13120Sstevel@tonic-gate 			exit(1);
13130Sstevel@tonic-gate 		}
13140Sstevel@tonic-gate 	}
13150Sstevel@tonic-gate 	if ((rpcb_unset(getprognum(argv[0]), getvers(argv[1]), nconf)) == 0) {
1316*11563SVallish.Vaidyeshwara@Sun.COM 		(void) fprintf(stderr,
13170Sstevel@tonic-gate 	"rpcinfo: Could not delete registration for prog %s version %s\n",
13180Sstevel@tonic-gate 			argv[0], argv[1]);
13190Sstevel@tonic-gate 		exit(1);
13200Sstevel@tonic-gate 	}
13210Sstevel@tonic-gate }
13220Sstevel@tonic-gate 
13230Sstevel@tonic-gate /*
13240Sstevel@tonic-gate  * Create and return a handle for the given nconf.
13250Sstevel@tonic-gate  * Exit if cannot create handle.
13260Sstevel@tonic-gate  */
13270Sstevel@tonic-gate static CLIENT *
clnt_addr_create(address,nconf,prog,vers)13280Sstevel@tonic-gate clnt_addr_create(address, nconf, prog, vers)
13290Sstevel@tonic-gate 	char *address;
13300Sstevel@tonic-gate 	struct netconfig *nconf;
13310Sstevel@tonic-gate 	ulong_t prog;
13320Sstevel@tonic-gate 	ulong_t vers;
13330Sstevel@tonic-gate {
13340Sstevel@tonic-gate 	CLIENT *client;
13350Sstevel@tonic-gate 	static struct netbuf *nbuf;
13360Sstevel@tonic-gate 	static int fd = RPC_ANYFD;
13370Sstevel@tonic-gate 	struct t_info tinfo;
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate 	if (fd == RPC_ANYFD) {
13400Sstevel@tonic-gate 		if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) {
13410Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_TLIERROR;
13420Sstevel@tonic-gate 			rpc_createerr.cf_error.re_terrno = t_errno;
13430Sstevel@tonic-gate 			clnt_pcreateerror("rpcinfo");
13440Sstevel@tonic-gate 			exit(1);
13450Sstevel@tonic-gate 		}
13460Sstevel@tonic-gate 		/* Convert the uaddr to taddr */
13470Sstevel@tonic-gate 		nbuf = uaddr2taddr(nconf, address);
13480Sstevel@tonic-gate 		if (nbuf == NULL) {
13490Sstevel@tonic-gate 			netdir_perror("rpcinfo");
13500Sstevel@tonic-gate 			exit(1);
13510Sstevel@tonic-gate 		}
13520Sstevel@tonic-gate 	}
13530Sstevel@tonic-gate 	client = clnt_tli_create(fd, nconf, nbuf, prog, vers, 0, 0);
13540Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
13550Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo");
13560Sstevel@tonic-gate 		exit(1);
13570Sstevel@tonic-gate 	}
13580Sstevel@tonic-gate 	return (client);
13590Sstevel@tonic-gate }
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate /*
13620Sstevel@tonic-gate  * If the version number is given, ping that (prog, vers); else try to find
13630Sstevel@tonic-gate  * the version numbers supported for that prog and ping all the versions.
13640Sstevel@tonic-gate  * Remote rpcbind is not contacted for this service. The requests are
13650Sstevel@tonic-gate  * sent directly to the services themselves.
13660Sstevel@tonic-gate  */
13670Sstevel@tonic-gate static void
addrping(address,netid,argc,argv)13680Sstevel@tonic-gate addrping(address, netid, argc, argv)
13690Sstevel@tonic-gate 	char *address;
13700Sstevel@tonic-gate 	char *netid;
13710Sstevel@tonic-gate 	int argc;
13720Sstevel@tonic-gate 	char **argv;
13730Sstevel@tonic-gate {
13740Sstevel@tonic-gate 	CLIENT *client;
13750Sstevel@tonic-gate 	struct timeval to;
13760Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
13770Sstevel@tonic-gate 	ulong_t prognum, versnum, minvers, maxvers;
13780Sstevel@tonic-gate 	struct rpc_err rpcerr;
13790Sstevel@tonic-gate 	int failure = 0;
13800Sstevel@tonic-gate 	struct netconfig *nconf;
13810Sstevel@tonic-gate 	int fd;
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 	if (argc < 1 || argc > 2 || (netid == NULL)) {
13840Sstevel@tonic-gate 		usage();
13850Sstevel@tonic-gate 		exit(1);
13860Sstevel@tonic-gate 	}
13870Sstevel@tonic-gate 	nconf = getnetconfigent(netid);
13880Sstevel@tonic-gate 	if (nconf == (struct netconfig *)NULL) {
1389*11563SVallish.Vaidyeshwara@Sun.COM 		(void) fprintf(stderr, "rpcinfo: Could not find %s\n", netid);
13900Sstevel@tonic-gate 		exit(1);
13910Sstevel@tonic-gate 	}
13920Sstevel@tonic-gate 	to.tv_sec = 10;
13930Sstevel@tonic-gate 	to.tv_usec = 0;
13940Sstevel@tonic-gate 	prognum = getprognum(argv[0]);
13950Sstevel@tonic-gate 	if (argc == 1) {	/* Version number not known */
13960Sstevel@tonic-gate 		/*
13970Sstevel@tonic-gate 		 * A call to version 0 should fail with a program/version
13980Sstevel@tonic-gate 		 * mismatch, and give us the range of versions supported.
13990Sstevel@tonic-gate 		 */
14000Sstevel@tonic-gate 		versnum = MIN_VERS;
14010Sstevel@tonic-gate 	} else {
14020Sstevel@tonic-gate 		versnum = getvers(argv[1]);
14030Sstevel@tonic-gate 	}
14040Sstevel@tonic-gate 	client = clnt_addr_create(address, nconf, prognum, versnum);
14050Sstevel@tonic-gate 	rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
14060Sstevel@tonic-gate 			(char *)NULL, (xdrproc_t)xdr_void,
14070Sstevel@tonic-gate 			(char *)NULL, to);
14080Sstevel@tonic-gate 	if (argc == 2) {
14090Sstevel@tonic-gate 		/* Version number was known */
14100Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
14110Sstevel@tonic-gate 			failure = 1;
14120Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
14130Sstevel@tonic-gate 		if (failure)
14140Sstevel@tonic-gate 			exit(1);
14150Sstevel@tonic-gate 		return;
14160Sstevel@tonic-gate 	}
14170Sstevel@tonic-gate 	/* Version number not known */
14180Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
14190Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLGET_FD, (char *)&fd);
14200Sstevel@tonic-gate 	if (rpc_stat == RPC_PROGVERSMISMATCH) {
14210Sstevel@tonic-gate 		clnt_geterr(client, &rpcerr);
14220Sstevel@tonic-gate 		minvers = rpcerr.re_vers.low;
14230Sstevel@tonic-gate 		maxvers = rpcerr.re_vers.high;
14240Sstevel@tonic-gate 	} else if (rpc_stat == RPC_SUCCESS) {
14250Sstevel@tonic-gate 		/*
14260Sstevel@tonic-gate 		 * Oh dear, it DOES support version 0.
14270Sstevel@tonic-gate 		 * Let's try version MAX_VERS.
14280Sstevel@tonic-gate 		 */
14290Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
14300Sstevel@tonic-gate 		client = clnt_addr_create(address, nconf, prognum, MAX_VERS);
14310Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
14320Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
14330Sstevel@tonic-gate 				(char *)NULL, to);
14340Sstevel@tonic-gate 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
14350Sstevel@tonic-gate 			clnt_geterr(client, &rpcerr);
14360Sstevel@tonic-gate 			minvers = rpcerr.re_vers.low;
14370Sstevel@tonic-gate 			maxvers = rpcerr.re_vers.high;
14380Sstevel@tonic-gate 		} else if (rpc_stat == RPC_SUCCESS) {
14390Sstevel@tonic-gate 			/*
14400Sstevel@tonic-gate 			 * It also supports version MAX_VERS.
14410Sstevel@tonic-gate 			 * Looks like we have a wise guy.
14420Sstevel@tonic-gate 			 * OK, we give them information on all
14430Sstevel@tonic-gate 			 * 4 billion versions they support...
14440Sstevel@tonic-gate 			 */
14450Sstevel@tonic-gate 			minvers = 0;
14460Sstevel@tonic-gate 			maxvers = MAX_VERS;
14470Sstevel@tonic-gate 		} else {
14480Sstevel@tonic-gate 			(void) pstatus(client, prognum, MAX_VERS);
14490Sstevel@tonic-gate 			exit(1);
14500Sstevel@tonic-gate 		}
14510Sstevel@tonic-gate 	} else {
14520Sstevel@tonic-gate 		(void) pstatus(client, prognum, (ulong_t)0);
14530Sstevel@tonic-gate 		exit(1);
14540Sstevel@tonic-gate 	}
14550Sstevel@tonic-gate 	(void) CLNT_DESTROY(client);
14560Sstevel@tonic-gate 	for (versnum = minvers; versnum <= maxvers; versnum++) {
14570Sstevel@tonic-gate 		client = clnt_addr_create(address, nconf, prognum, versnum);
14580Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
14590Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
14600Sstevel@tonic-gate 				(char *)NULL, to);
14610Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
14620Sstevel@tonic-gate 				failure = 1;
14630Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
14640Sstevel@tonic-gate 	}
14650Sstevel@tonic-gate 	(void) t_close(fd);
14660Sstevel@tonic-gate 	if (failure)
14670Sstevel@tonic-gate 		exit(1);
14680Sstevel@tonic-gate }
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate /*
14710Sstevel@tonic-gate  * If the version number is given, ping that (prog, vers); else try to find
14720Sstevel@tonic-gate  * the version numbers supported for that prog and ping all the versions.
14730Sstevel@tonic-gate  * Remote rpcbind is *contacted* for this service. The requests are
14740Sstevel@tonic-gate  * then sent directly to the services themselves.
14750Sstevel@tonic-gate  */
14760Sstevel@tonic-gate static void
progping(netid,argc,argv)14770Sstevel@tonic-gate progping(netid, argc, argv)
14780Sstevel@tonic-gate 	char *netid;
14790Sstevel@tonic-gate 	int argc;
14800Sstevel@tonic-gate 	char **argv;
14810Sstevel@tonic-gate {
14820Sstevel@tonic-gate 	CLIENT *client;
14830Sstevel@tonic-gate 	struct timeval to;
14840Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
14850Sstevel@tonic-gate 	ulong_t prognum, versnum, minvers, maxvers;
14860Sstevel@tonic-gate 	struct rpc_err rpcerr;
14870Sstevel@tonic-gate 	int failure = 0;
14880Sstevel@tonic-gate 	struct netconfig *nconf;
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate 	if (argc < 2 || argc > 3 || (netid == NULL)) {
14910Sstevel@tonic-gate 		usage();
14920Sstevel@tonic-gate 		exit(1);
14930Sstevel@tonic-gate 	}
14940Sstevel@tonic-gate 	prognum = getprognum(argv[1]);
14950Sstevel@tonic-gate 	if (argc == 2) { /* Version number not known */
14960Sstevel@tonic-gate 		/*
14970Sstevel@tonic-gate 		 * A call to version 0 should fail with a program/version
14980Sstevel@tonic-gate 		 * mismatch, and give us the range of versions supported.
14990Sstevel@tonic-gate 		 */
15000Sstevel@tonic-gate 		versnum = MIN_VERS;
15010Sstevel@tonic-gate 	} else {
15020Sstevel@tonic-gate 		versnum = getvers(argv[2]);
15030Sstevel@tonic-gate 	}
15040Sstevel@tonic-gate 	if (netid) {
15050Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
15060Sstevel@tonic-gate 		if (nconf == (struct netconfig *)NULL) {
1507*11563SVallish.Vaidyeshwara@Sun.COM 			(void) fprintf(stderr,
1508*11563SVallish.Vaidyeshwara@Sun.COM 				"rpcinfo: Could not find %s\n", netid);
15090Sstevel@tonic-gate 			exit(1);
15100Sstevel@tonic-gate 		}
15110Sstevel@tonic-gate 		client = clnt_tp_create(argv[0], prognum, versnum, nconf);
15120Sstevel@tonic-gate 	} else {
15130Sstevel@tonic-gate 		client = clnt_create(argv[0], prognum, versnum, "NETPATH");
15140Sstevel@tonic-gate 	}
15150Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
15160Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo");
15170Sstevel@tonic-gate 		exit(1);
15180Sstevel@tonic-gate 	}
15190Sstevel@tonic-gate 	to.tv_sec = 10;
15200Sstevel@tonic-gate 	to.tv_usec = 0;
15210Sstevel@tonic-gate 	rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
15220Sstevel@tonic-gate 			(char *)NULL, (xdrproc_t)xdr_void,
15230Sstevel@tonic-gate 			(char *)NULL, to);
15240Sstevel@tonic-gate 	if (argc == 3) {
15250Sstevel@tonic-gate 		/* Version number was known */
15260Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
15270Sstevel@tonic-gate 			failure = 1;
15280Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
15290Sstevel@tonic-gate 		if (failure)
15300Sstevel@tonic-gate 			exit(1);
15310Sstevel@tonic-gate 		return;
15320Sstevel@tonic-gate 	}
15330Sstevel@tonic-gate 	/* Version number not known */
15340Sstevel@tonic-gate 	if (rpc_stat == RPC_PROGVERSMISMATCH) {
15350Sstevel@tonic-gate 		clnt_geterr(client, &rpcerr);
15360Sstevel@tonic-gate 		minvers = rpcerr.re_vers.low;
15370Sstevel@tonic-gate 		maxvers = rpcerr.re_vers.high;
15380Sstevel@tonic-gate 	} else if (rpc_stat == RPC_SUCCESS) {
15390Sstevel@tonic-gate 		/*
15400Sstevel@tonic-gate 		 * Oh dear, it DOES support version 0.
15410Sstevel@tonic-gate 		 * Let's try version MAX_VERS.
15420Sstevel@tonic-gate 		 */
15430Sstevel@tonic-gate 		versnum = MAX_VERS;
15440Sstevel@tonic-gate 		(void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
15450Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC,
15460Sstevel@tonic-gate 				(xdrproc_t)xdr_void, (char *)NULL,
15470Sstevel@tonic-gate 				(xdrproc_t)xdr_void, (char *)NULL, to);
15480Sstevel@tonic-gate 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
15490Sstevel@tonic-gate 			clnt_geterr(client, &rpcerr);
15500Sstevel@tonic-gate 			minvers = rpcerr.re_vers.low;
15510Sstevel@tonic-gate 			maxvers = rpcerr.re_vers.high;
15520Sstevel@tonic-gate 		} else if (rpc_stat == RPC_SUCCESS) {
15530Sstevel@tonic-gate 			/*
15540Sstevel@tonic-gate 			 * It also supports version MAX_VERS.
15550Sstevel@tonic-gate 			 * Looks like we have a wise guy.
15560Sstevel@tonic-gate 			 * OK, we give them information on all
15570Sstevel@tonic-gate 			 * 4 billion versions they support...
15580Sstevel@tonic-gate 			 */
15590Sstevel@tonic-gate 			minvers = 0;
15600Sstevel@tonic-gate 			maxvers = MAX_VERS;
15610Sstevel@tonic-gate 		} else {
15620Sstevel@tonic-gate 			(void) pstatus(client, prognum, MAX_VERS);
15630Sstevel@tonic-gate 			exit(1);
15640Sstevel@tonic-gate 		}
15650Sstevel@tonic-gate 	} else {
15660Sstevel@tonic-gate 		(void) pstatus(client, prognum, (ulong_t)0);
15670Sstevel@tonic-gate 		exit(1);
15680Sstevel@tonic-gate 	}
15690Sstevel@tonic-gate 	for (versnum = minvers; versnum <= maxvers; versnum++) {
15700Sstevel@tonic-gate 		(void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
15710Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
15720Sstevel@tonic-gate 					(char *)NULL, (xdrproc_t)xdr_void,
15730Sstevel@tonic-gate 					(char *)NULL, to);
15740Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
15750Sstevel@tonic-gate 				failure = 1;
15760Sstevel@tonic-gate 	}
15770Sstevel@tonic-gate 	(void) CLNT_DESTROY(client);
15780Sstevel@tonic-gate 	if (failure)
15790Sstevel@tonic-gate 		exit(1);
15800Sstevel@tonic-gate }
15810Sstevel@tonic-gate 
15820Sstevel@tonic-gate static void
usage()15830Sstevel@tonic-gate usage()
15840Sstevel@tonic-gate {
1585*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr, "Usage: rpcinfo [-m | -s] [host]\n");
15860Sstevel@tonic-gate #ifdef PORTMAP
1587*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr, "       rpcinfo -p [host]\n");
15880Sstevel@tonic-gate #endif
1589*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr,
1590*11563SVallish.Vaidyeshwara@Sun.COM 	    "       rpcinfo -T netid host prognum [versnum]\n");
1591*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr, "       rpcinfo -l host prognum versnum\n");
15920Sstevel@tonic-gate #ifdef PORTMAP
1593*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr,
15940Sstevel@tonic-gate "       rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
15950Sstevel@tonic-gate #endif
1596*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr,
15970Sstevel@tonic-gate "       rpcinfo -a serv_address -T netid prognum [version]\n");
1598*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr, "       rpcinfo -b prognum versnum\n");
1599*11563SVallish.Vaidyeshwara@Sun.COM 	(void) fprintf(stderr,
1600*11563SVallish.Vaidyeshwara@Sun.COM 	    "       rpcinfo -d [-T netid] prognum versnum\n");
16010Sstevel@tonic-gate }
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate static ulong_t
getprognum(arg)16040Sstevel@tonic-gate getprognum  (arg)
16050Sstevel@tonic-gate 	char *arg;
16060Sstevel@tonic-gate {
16070Sstevel@tonic-gate 	char *strptr;
16080Sstevel@tonic-gate 	register struct rpcent *rpc;
16090Sstevel@tonic-gate 	register ulong_t prognum;
16100Sstevel@tonic-gate 	char *tptr = arg;
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate 	while (*tptr && isdigit(*tptr++));
16130Sstevel@tonic-gate 	if (*tptr || isalpha(*(tptr - 1))) {
16140Sstevel@tonic-gate 		rpc = getrpcbyname(arg);
16150Sstevel@tonic-gate 		if (rpc == NULL) {
1616*11563SVallish.Vaidyeshwara@Sun.COM 			(void) fprintf(stderr,
1617*11563SVallish.Vaidyeshwara@Sun.COM 				"rpcinfo: %s is unknown service\n", arg);
16180Sstevel@tonic-gate 			exit(1);
16190Sstevel@tonic-gate 		}
16200Sstevel@tonic-gate 		prognum = rpc->r_number;
16210Sstevel@tonic-gate 	} else {
16220Sstevel@tonic-gate 		prognum = strtol(arg, &strptr, 10);
16230Sstevel@tonic-gate 		if (strptr == arg || *strptr != '\0') {
1624*11563SVallish.Vaidyeshwara@Sun.COM 			(void) fprintf(stderr,
16250Sstevel@tonic-gate 		"rpcinfo: %s is illegal program number\n", arg);
16260Sstevel@tonic-gate 			exit(1);
16270Sstevel@tonic-gate 		}
16280Sstevel@tonic-gate 	}
16290Sstevel@tonic-gate 	return (prognum);
16300Sstevel@tonic-gate }
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate static ulong_t
getvers(arg)16330Sstevel@tonic-gate getvers(arg)
16340Sstevel@tonic-gate 	char *arg;
16350Sstevel@tonic-gate {
16360Sstevel@tonic-gate 	char *strptr;
16370Sstevel@tonic-gate 	register ulong_t vers;
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 	vers = (int)strtol(arg, &strptr, 10);
16400Sstevel@tonic-gate 	if (strptr == arg || *strptr != '\0') {
1641*11563SVallish.Vaidyeshwara@Sun.COM 		(void) fprintf(stderr,
1642*11563SVallish.Vaidyeshwara@Sun.COM 			"rpcinfo: %s is illegal version number\n", arg);
16430Sstevel@tonic-gate 		exit(1);
16440Sstevel@tonic-gate 	}
16450Sstevel@tonic-gate 	return (vers);
16460Sstevel@tonic-gate }
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate /*
16490Sstevel@tonic-gate  * This routine should take a pointer to an "rpc_err" structure, rather than
16500Sstevel@tonic-gate  * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
16510Sstevel@tonic-gate  * a CLIENT structure rather than a pointer to an "rpc_err" structure.
16520Sstevel@tonic-gate  * As such, we have to keep the CLIENT structure around in order to print
16530Sstevel@tonic-gate  * a good error message.
16540Sstevel@tonic-gate  */
16550Sstevel@tonic-gate static int
pstatus(client,prog,vers)16560Sstevel@tonic-gate pstatus(client, prog, vers)
16570Sstevel@tonic-gate 	register CLIENT *client;
16580Sstevel@tonic-gate 	ulong_t prog;
16590Sstevel@tonic-gate 	ulong_t vers;
16600Sstevel@tonic-gate {
16610Sstevel@tonic-gate 	struct rpc_err rpcerr;
16620Sstevel@tonic-gate 
16630Sstevel@tonic-gate 	clnt_geterr(client, &rpcerr);
16640Sstevel@tonic-gate 	if (rpcerr.re_status != RPC_SUCCESS) {
16650Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo");
1666*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("program %lu version %lu is not available\n",
16670Sstevel@tonic-gate 			prog, vers);
16680Sstevel@tonic-gate 		return (-1);
16690Sstevel@tonic-gate 	} else {
1670*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("program %lu version %lu ready and waiting\n",
16710Sstevel@tonic-gate 			prog, vers);
16720Sstevel@tonic-gate 		return (0);
16730Sstevel@tonic-gate 	}
16740Sstevel@tonic-gate }
16750Sstevel@tonic-gate 
16760Sstevel@tonic-gate static CLIENT *
clnt_rpcbind_create(host,rpcbversnum,targaddr)16770Sstevel@tonic-gate clnt_rpcbind_create(host, rpcbversnum, targaddr)
16780Sstevel@tonic-gate 	char *host;
16790Sstevel@tonic-gate 	ulong_t rpcbversnum;
16800Sstevel@tonic-gate 	struct netbuf **targaddr;
16810Sstevel@tonic-gate {
16820Sstevel@tonic-gate 	static char *tlist[3] = {
16830Sstevel@tonic-gate 		"circuit_n", "circuit_v", "datagram_v"
16840Sstevel@tonic-gate 	};
16850Sstevel@tonic-gate 	int i;
16860Sstevel@tonic-gate 	struct netconfig *nconf;
16870Sstevel@tonic-gate 	CLIENT *clnt = NULL;
16880Sstevel@tonic-gate 	void *handle;
16890Sstevel@tonic-gate 
16900Sstevel@tonic-gate 	rpc_createerr.cf_stat = RPC_SUCCESS;
16910Sstevel@tonic-gate 	for (i = 0; i < 3; i++) {
16920Sstevel@tonic-gate 		if ((handle = __rpc_setconf(tlist[i])) == NULL)
16930Sstevel@tonic-gate 			continue;
16940Sstevel@tonic-gate 		while (clnt == (CLIENT *)NULL) {
16950Sstevel@tonic-gate 			if ((nconf = __rpc_getconf(handle)) == NULL) {
16960Sstevel@tonic-gate 				if (rpc_createerr.cf_stat == RPC_SUCCESS)
16970Sstevel@tonic-gate 				    rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
16980Sstevel@tonic-gate 				break;
16990Sstevel@tonic-gate 			}
17000Sstevel@tonic-gate 			clnt = getclnthandle(host, nconf, rpcbversnum,
17010Sstevel@tonic-gate 					targaddr);
17020Sstevel@tonic-gate 		}
17030Sstevel@tonic-gate 		if (clnt)
17040Sstevel@tonic-gate 			break;
17050Sstevel@tonic-gate 		__rpc_endconf(handle);
17060Sstevel@tonic-gate 	}
17070Sstevel@tonic-gate 	return (clnt);
17080Sstevel@tonic-gate }
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate static CLIENT*
getclnthandle(host,nconf,rpcbversnum,targaddr)17110Sstevel@tonic-gate getclnthandle(host, nconf, rpcbversnum, targaddr)
17120Sstevel@tonic-gate 	char *host;
17130Sstevel@tonic-gate 	struct netconfig *nconf;
17140Sstevel@tonic-gate 	ulong_t rpcbversnum;
17150Sstevel@tonic-gate 	struct netbuf **targaddr;
17160Sstevel@tonic-gate {
17170Sstevel@tonic-gate 	struct netbuf *addr;
17180Sstevel@tonic-gate 	struct nd_addrlist *nas;
17190Sstevel@tonic-gate 	struct nd_hostserv rpcbind_hs;
17200Sstevel@tonic-gate 	CLIENT *client = NULL;
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate 	/* Get the address of the rpcbind */
17230Sstevel@tonic-gate 	rpcbind_hs.h_host = host;
17240Sstevel@tonic-gate 	rpcbind_hs.h_serv = "rpcbind";
17250Sstevel@tonic-gate 	if (netdir_getbyname(nconf, &rpcbind_hs, &nas)) {
17260Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
17270Sstevel@tonic-gate 		return (NULL);
17280Sstevel@tonic-gate 	}
17290Sstevel@tonic-gate 	addr = nas->n_addrs;
17300Sstevel@tonic-gate 	client = clnt_tli_create(RPC_ANYFD, nconf, addr, RPCBPROG,
17310Sstevel@tonic-gate 			rpcbversnum, 0, 0);
17320Sstevel@tonic-gate 	if (client) {
17330Sstevel@tonic-gate 		if (targaddr != NULL) {
17340Sstevel@tonic-gate 			*targaddr =
17350Sstevel@tonic-gate 			    (struct netbuf *)malloc(sizeof (struct netbuf));
17360Sstevel@tonic-gate 			if (*targaddr != NULL) {
17370Sstevel@tonic-gate 				(*targaddr)->maxlen = addr->maxlen;
17380Sstevel@tonic-gate 				(*targaddr)->len = addr->len;
17390Sstevel@tonic-gate 				(*targaddr)->buf = (char *)malloc(addr->len);
17400Sstevel@tonic-gate 				if ((*targaddr)->buf != NULL) {
1741*11563SVallish.Vaidyeshwara@Sun.COM 					(void) memcpy((*targaddr)->buf,
1742*11563SVallish.Vaidyeshwara@Sun.COM 						addr->buf, addr->len);
17430Sstevel@tonic-gate 				}
17440Sstevel@tonic-gate 			}
17450Sstevel@tonic-gate 		}
17460Sstevel@tonic-gate 	} else {
17470Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_TLIERROR) {
17480Sstevel@tonic-gate 			/*
17490Sstevel@tonic-gate 			 * Assume that the other system is dead; this is a
17500Sstevel@tonic-gate 			 * better error to display to the user.
17510Sstevel@tonic-gate 			 */
17520Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_RPCBFAILURE;
17530Sstevel@tonic-gate 			rpc_createerr.cf_error.re_status = RPC_FAILED;
17540Sstevel@tonic-gate 		}
17550Sstevel@tonic-gate 	}
17560Sstevel@tonic-gate 	netdir_free((char *)nas, ND_ADDRLIST);
17570Sstevel@tonic-gate 	return (client);
17580Sstevel@tonic-gate }
17590Sstevel@tonic-gate 
17600Sstevel@tonic-gate static void
print_rmtcallstat(rtype,infp)17610Sstevel@tonic-gate print_rmtcallstat(rtype, infp)
17620Sstevel@tonic-gate 	int rtype;
17630Sstevel@tonic-gate 	rpcb_stat *infp;
17640Sstevel@tonic-gate {
17650Sstevel@tonic-gate 	register rpcbs_rmtcalllist_ptr pr;
17660Sstevel@tonic-gate 	struct rpcent *rpc;
17670Sstevel@tonic-gate 
17680Sstevel@tonic-gate 	if (rtype == RPCBVERS_4_STAT)
1769*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf(
17700Sstevel@tonic-gate 		"prog\t\tvers\tproc\tnetid\tindirect success failure\n");
17710Sstevel@tonic-gate 	else
1772*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
17730Sstevel@tonic-gate 	for (pr = infp->rmtinfo; pr; pr = pr->next) {
17740Sstevel@tonic-gate 		rpc = getrpcbynumber(pr->prog);
17750Sstevel@tonic-gate 		if (rpc)
1776*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-16s", rpc->r_name);
17770Sstevel@tonic-gate 		else
1778*11563SVallish.Vaidyeshwara@Sun.COM #if defined(_LP64) || defined(_I32LPx)
1779*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-16u", pr->prog);
1780*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("%u\t%u\t%-7s ",
1781*11563SVallish.Vaidyeshwara@Sun.COM #else
1782*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-16lu", pr->prog);
1783*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("%lu\t%lu\t%-7s ",
1784*11563SVallish.Vaidyeshwara@Sun.COM #endif
17850Sstevel@tonic-gate 			pr->vers, pr->proc, pr->netid);
17860Sstevel@tonic-gate 		if (rtype == RPCBVERS_4_STAT)
1787*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%d\t ", pr->indirect);
1788*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("%d\t%d\n", pr->success, pr->failure);
17890Sstevel@tonic-gate 	}
17900Sstevel@tonic-gate }
17910Sstevel@tonic-gate 
17920Sstevel@tonic-gate static void
1793*11563SVallish.Vaidyeshwara@Sun.COM /* LINTED E_FUNC_ARG_UNUSED for 1st arg rtype */
print_getaddrstat(rtype,infp)17940Sstevel@tonic-gate print_getaddrstat(rtype, infp)
17950Sstevel@tonic-gate 	int rtype;
17960Sstevel@tonic-gate 	rpcb_stat *infp;
17970Sstevel@tonic-gate {
17980Sstevel@tonic-gate 	rpcbs_addrlist_ptr al;
17990Sstevel@tonic-gate 	register struct rpcent *rpc;
18000Sstevel@tonic-gate 
1801*11563SVallish.Vaidyeshwara@Sun.COM 	(void) printf("prog\t\tvers\tnetid\t  success\tfailure\n");
18020Sstevel@tonic-gate 	for (al = infp->addrinfo; al; al = al->next) {
18030Sstevel@tonic-gate 		rpc = getrpcbynumber(al->prog);
18040Sstevel@tonic-gate 		if (rpc)
1805*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-16s", rpc->r_name);
18060Sstevel@tonic-gate 		else
1807*11563SVallish.Vaidyeshwara@Sun.COM #if defined(_LP64) || defined(_I32LPx)
1808*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-16u", al->prog);
1809*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("%u\t%-9s %-12d\t%d\n",
1810*11563SVallish.Vaidyeshwara@Sun.COM #else
1811*11563SVallish.Vaidyeshwara@Sun.COM 			(void) printf("%-16lu", al->prog);
1812*11563SVallish.Vaidyeshwara@Sun.COM 		(void) printf("%lu\t%-9s %-12d\t%d\n",
1813*11563SVallish.Vaidyeshwara@Sun.COM #endif
18140Sstevel@tonic-gate 			al->vers, al->netid,
18150Sstevel@tonic-gate 			al->success, al->failure);
18160Sstevel@tonic-gate 	}
18170Sstevel@tonic-gate }
18180Sstevel@tonic-gate 
18190Sstevel@tonic-gate static char *
spaces(howmany)18200Sstevel@tonic-gate spaces(howmany)
18210Sstevel@tonic-gate int howmany;
18220Sstevel@tonic-gate {
18230Sstevel@tonic-gate 	static char space_array[] =		/* 64 spaces */
18240Sstevel@tonic-gate 	"                                                                ";
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate 	if (howmany <= 0 || howmany > sizeof (space_array)) {
18270Sstevel@tonic-gate 		return ("");
18280Sstevel@tonic-gate 	}
18290Sstevel@tonic-gate 	return (&space_array[sizeof (space_array) - howmany - 1]);
18300Sstevel@tonic-gate }
1831