xref: /titanic_51/usr/src/cmd/rpcinfo/rpcinfo.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  *
22*7c478bd9Sstevel@tonic-gate  * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
23*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
29*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
30*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
33*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
34*7c478bd9Sstevel@tonic-gate  * contributors.
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate /*
40*7c478bd9Sstevel@tonic-gate  * rpcinfo: ping a particular rpc program
41*7c478bd9Sstevel@tonic-gate  * 	or dump the the registered programs on the remote machine.
42*7c478bd9Sstevel@tonic-gate  */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * We are for now defining PORTMAP here.  It doesnt even compile
46*7c478bd9Sstevel@tonic-gate  * unless it is defined.
47*7c478bd9Sstevel@tonic-gate  */
48*7c478bd9Sstevel@tonic-gate #ifndef	PORTMAP
49*7c478bd9Sstevel@tonic-gate #define	PORTMAP
50*7c478bd9Sstevel@tonic-gate #endif
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /*
53*7c478bd9Sstevel@tonic-gate  * If PORTMAP is defined, rpcinfo will talk to both portmapper and
54*7c478bd9Sstevel@tonic-gate  * rpcbind programs; else it talks only to rpcbind. In the latter case
55*7c478bd9Sstevel@tonic-gate  * all the portmapper specific options such as -u, -t, -p become void.
56*7c478bd9Sstevel@tonic-gate  */
57*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
58*7c478bd9Sstevel@tonic-gate #include <stdio.h>
59*7c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
60*7c478bd9Sstevel@tonic-gate #include <rpc/nettype.h>
61*7c478bd9Sstevel@tonic-gate #include <netdir.h>
62*7c478bd9Sstevel@tonic-gate #include <rpc/rpcent.h>
63*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
64*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
65*7c478bd9Sstevel@tonic-gate #include <string.h>
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP		/* Support for version 2 portmapper */
68*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
69*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
70*7c478bd9Sstevel@tonic-gate #include <netdb.h>
71*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
72*7c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h>
73*7c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
74*7c478bd9Sstevel@tonic-gate #endif
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate #define	MAXHOSTLEN	256
77*7c478bd9Sstevel@tonic-gate #define	MIN_VERS	((ulong_t)0)
78*7c478bd9Sstevel@tonic-gate #define	MAX_VERS	((ulong_t)4294967295L)
79*7c478bd9Sstevel@tonic-gate #define	UNKNOWN		"unknown"
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate #define	MAX(a, b) (((a) > (b)) ? (a) : (b))
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate extern int	t_errno;
84*7c478bd9Sstevel@tonic-gate extern long	strtol();
85*7c478bd9Sstevel@tonic-gate static char *spaces();
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
88*7c478bd9Sstevel@tonic-gate static void	ip_ping(/*ushort_t portflag, char *trans,
89*7c478bd9Sstevel@tonic-gate 				int argc, char **argv*/);
90*7c478bd9Sstevel@tonic-gate static CLIENT	*clnt_com_create(/* struct sockaddr_in *addr, long prog,
91*7c478bd9Sstevel@tonic-gate 			long vers, int *fd, char *trans*/);
92*7c478bd9Sstevel@tonic-gate static void	pmapdump(/*int argc, char **argv*/);
93*7c478bd9Sstevel@tonic-gate static void	get_inet_address(/*struct sockaddr_in *addr, char *host*/);
94*7c478bd9Sstevel@tonic-gate #endif
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate static bool_t	reply_proc(/*void *res, struct netbuf *who*,
97*7c478bd9Sstevel@tonic-gate 			struct netconfig *nconf*/);
98*7c478bd9Sstevel@tonic-gate static void	brdcst(/*int argc, char **argv*/);
99*7c478bd9Sstevel@tonic-gate static void	addrping(/*char *address, char *netid,
100*7c478bd9Sstevel@tonic-gate 				int argc, char **argv*/);
101*7c478bd9Sstevel@tonic-gate static void	progping(/* char *netid, int argc, char **argv*/);
102*7c478bd9Sstevel@tonic-gate static CLIENT	*clnt_addr_create(/* char *addr, struct netconfig *nconf,
103*7c478bd9Sstevel@tonic-gate 				long prog, long vers*/);
104*7c478bd9Sstevel@tonic-gate static CLIENT   *clnt_rpcbind_create(/* char *host, int vers */);
105*7c478bd9Sstevel@tonic-gate static CLIENT   *getclnthandle(/* host, nconf, rpcbversnum */);
106*7c478bd9Sstevel@tonic-gate static int	pstatus(/*CLIENT *client, ulong_t prognum, ulong_t vers*/);
107*7c478bd9Sstevel@tonic-gate static void	rpcbdump(/*char *netid, int argc, char **argv*/);
108*7c478bd9Sstevel@tonic-gate static void	rpcbgetstat(/* int argc, char **argv*/);
109*7c478bd9Sstevel@tonic-gate static void	rpcbaddrlist(/*char *netid, int argc, char **argv*/);
110*7c478bd9Sstevel@tonic-gate static void	deletereg(/*char *netid, int argc, char **argv */);
111*7c478bd9Sstevel@tonic-gate static void	print_rmtcallstat(/* rtype, infp */);
112*7c478bd9Sstevel@tonic-gate static void	print_getaddrstat(/* rtype, infp */);
113*7c478bd9Sstevel@tonic-gate static void	usage(/*void*/);
114*7c478bd9Sstevel@tonic-gate static ulong_t	getprognum(/*char *arg*/);
115*7c478bd9Sstevel@tonic-gate static ulong_t	getvers(/*char *arg*/);
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate /*
118*7c478bd9Sstevel@tonic-gate  * Functions to be performed.
119*7c478bd9Sstevel@tonic-gate  */
120*7c478bd9Sstevel@tonic-gate #define	NONE		0	/* no function */
121*7c478bd9Sstevel@tonic-gate #define	PMAPDUMP	1	/* dump portmapper registrations */
122*7c478bd9Sstevel@tonic-gate #define	TCPPING		2	/* ping TCP service */
123*7c478bd9Sstevel@tonic-gate #define	UDPPING		3	/* ping UDP service */
124*7c478bd9Sstevel@tonic-gate #define	BROADCAST	4	/* ping broadcast service */
125*7c478bd9Sstevel@tonic-gate #define	DELETES		5	/* delete registration for the service */
126*7c478bd9Sstevel@tonic-gate #define	ADDRPING	6	/* pings at the given address */
127*7c478bd9Sstevel@tonic-gate #define	PROGPING	7	/* pings a program on a given host */
128*7c478bd9Sstevel@tonic-gate #define	RPCBDUMP	8	/* dump rpcbind registrations */
129*7c478bd9Sstevel@tonic-gate #define	RPCBDUMP_SHORT	9	/* dump rpcbind registrations - short version */
130*7c478bd9Sstevel@tonic-gate #define	RPCBADDRLIST	10	/* dump addr list about one prog */
131*7c478bd9Sstevel@tonic-gate #define	RPCBGETSTAT	11	/* Get statistics */
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate struct netidlist {
134*7c478bd9Sstevel@tonic-gate 	char *netid;
135*7c478bd9Sstevel@tonic-gate 	struct netidlist *next;
136*7c478bd9Sstevel@tonic-gate };
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate struct verslist {
139*7c478bd9Sstevel@tonic-gate 	int vers;
140*7c478bd9Sstevel@tonic-gate 	struct verslist *next;
141*7c478bd9Sstevel@tonic-gate };
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate struct rpcbdump_short {
144*7c478bd9Sstevel@tonic-gate 	ulong_t prog;
145*7c478bd9Sstevel@tonic-gate 	struct verslist *vlist;
146*7c478bd9Sstevel@tonic-gate 	struct netidlist *nlist;
147*7c478bd9Sstevel@tonic-gate 	struct rpcbdump_short *next;
148*7c478bd9Sstevel@tonic-gate 	char *owner;
149*7c478bd9Sstevel@tonic-gate };
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate char *loopback_netid = NULL;
153*7c478bd9Sstevel@tonic-gate struct netconfig *loopback_nconf;
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate int
156*7c478bd9Sstevel@tonic-gate main(argc, argv)
157*7c478bd9Sstevel@tonic-gate 	int argc;
158*7c478bd9Sstevel@tonic-gate 	char **argv;
159*7c478bd9Sstevel@tonic-gate {
160*7c478bd9Sstevel@tonic-gate 	register int c;
161*7c478bd9Sstevel@tonic-gate 	extern char *optarg;
162*7c478bd9Sstevel@tonic-gate 	extern int optind;
163*7c478bd9Sstevel@tonic-gate 	int errflg;
164*7c478bd9Sstevel@tonic-gate 	int function;
165*7c478bd9Sstevel@tonic-gate 	char *netid = NULL;
166*7c478bd9Sstevel@tonic-gate 	char *address = NULL;
167*7c478bd9Sstevel@tonic-gate 	void *handle;
168*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
169*7c478bd9Sstevel@tonic-gate 	char *strptr;
170*7c478bd9Sstevel@tonic-gate 	ushort_t portnum = 0;
171*7c478bd9Sstevel@tonic-gate #endif
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	function = NONE;
174*7c478bd9Sstevel@tonic-gate 	errflg = 0;
175*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
176*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "a:bdlmn:pstT:u")) != EOF) {
177*7c478bd9Sstevel@tonic-gate #else
178*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "a:bdlmn:sT:")) != EOF) {
179*7c478bd9Sstevel@tonic-gate #endif
180*7c478bd9Sstevel@tonic-gate 		switch (c) {
181*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
182*7c478bd9Sstevel@tonic-gate 		case 'p':
183*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
184*7c478bd9Sstevel@tonic-gate 				errflg = 1;
185*7c478bd9Sstevel@tonic-gate 			else
186*7c478bd9Sstevel@tonic-gate 				function = PMAPDUMP;
187*7c478bd9Sstevel@tonic-gate 			break;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 		case 't':
190*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
191*7c478bd9Sstevel@tonic-gate 				errflg = 1;
192*7c478bd9Sstevel@tonic-gate 			else
193*7c478bd9Sstevel@tonic-gate 				function = TCPPING;
194*7c478bd9Sstevel@tonic-gate 			break;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 		case 'u':
197*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
198*7c478bd9Sstevel@tonic-gate 				errflg = 1;
199*7c478bd9Sstevel@tonic-gate 			else
200*7c478bd9Sstevel@tonic-gate 				function = UDPPING;
201*7c478bd9Sstevel@tonic-gate 			break;
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 		case 'n':
204*7c478bd9Sstevel@tonic-gate 			portnum = (ushort_t)strtol(optarg, &strptr, 10);
205*7c478bd9Sstevel@tonic-gate 			if (strptr == optarg || *strptr != '\0') {
206*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
207*7c478bd9Sstevel@tonic-gate 			"rpcinfo: %s is illegal port number\n",
208*7c478bd9Sstevel@tonic-gate 					optarg);
209*7c478bd9Sstevel@tonic-gate 				exit(1);
210*7c478bd9Sstevel@tonic-gate 			}
211*7c478bd9Sstevel@tonic-gate 			break;
212*7c478bd9Sstevel@tonic-gate #endif
213*7c478bd9Sstevel@tonic-gate 		case 'a':
214*7c478bd9Sstevel@tonic-gate 			address = optarg;
215*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
216*7c478bd9Sstevel@tonic-gate 				errflg = 1;
217*7c478bd9Sstevel@tonic-gate 			else
218*7c478bd9Sstevel@tonic-gate 				function = ADDRPING;
219*7c478bd9Sstevel@tonic-gate 			break;
220*7c478bd9Sstevel@tonic-gate 		case 'b':
221*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
222*7c478bd9Sstevel@tonic-gate 				errflg = 1;
223*7c478bd9Sstevel@tonic-gate 			else
224*7c478bd9Sstevel@tonic-gate 				function = BROADCAST;
225*7c478bd9Sstevel@tonic-gate 			break;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 		case 'd':
228*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
229*7c478bd9Sstevel@tonic-gate 				errflg = 1;
230*7c478bd9Sstevel@tonic-gate 			else
231*7c478bd9Sstevel@tonic-gate 				function = DELETES;
232*7c478bd9Sstevel@tonic-gate 			break;
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 		case 'l':
235*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
236*7c478bd9Sstevel@tonic-gate 				errflg = 1;
237*7c478bd9Sstevel@tonic-gate 			else
238*7c478bd9Sstevel@tonic-gate 				function = RPCBADDRLIST;
239*7c478bd9Sstevel@tonic-gate 			break;
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 		case 'm':
242*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
243*7c478bd9Sstevel@tonic-gate 				errflg = 1;
244*7c478bd9Sstevel@tonic-gate 			else
245*7c478bd9Sstevel@tonic-gate 				function = RPCBGETSTAT;
246*7c478bd9Sstevel@tonic-gate 			break;
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 		case 's':
249*7c478bd9Sstevel@tonic-gate 			if (function != NONE)
250*7c478bd9Sstevel@tonic-gate 				errflg = 1;
251*7c478bd9Sstevel@tonic-gate 			else
252*7c478bd9Sstevel@tonic-gate 				function = RPCBDUMP_SHORT;
253*7c478bd9Sstevel@tonic-gate 			break;
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 		case 'T':
256*7c478bd9Sstevel@tonic-gate 			netid = optarg;
257*7c478bd9Sstevel@tonic-gate 			break;
258*7c478bd9Sstevel@tonic-gate 		case '?':
259*7c478bd9Sstevel@tonic-gate 			errflg = 1;
260*7c478bd9Sstevel@tonic-gate 			break;
261*7c478bd9Sstevel@tonic-gate 		}
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	if (errflg || ((function == ADDRPING) && !netid)) {
265*7c478bd9Sstevel@tonic-gate 		usage();
266*7c478bd9Sstevel@tonic-gate 		return (1);
267*7c478bd9Sstevel@tonic-gate 	}
268*7c478bd9Sstevel@tonic-gate 	if (netid == NULL) {	/* user has not selected transport to use */
269*7c478bd9Sstevel@tonic-gate 		/*
270*7c478bd9Sstevel@tonic-gate 		 * See if a COTS loopback transport is available, in case we
271*7c478bd9Sstevel@tonic-gate 		 * will be talking to the local system.
272*7c478bd9Sstevel@tonic-gate 		 */
273*7c478bd9Sstevel@tonic-gate 		handle = setnetconfig();
274*7c478bd9Sstevel@tonic-gate 		while ((loopback_nconf = getnetconfig(handle)) != NULL) {
275*7c478bd9Sstevel@tonic-gate 			if (strcmp(loopback_nconf->nc_protofmly,
276*7c478bd9Sstevel@tonic-gate 				NC_LOOPBACK) == 0 &&
277*7c478bd9Sstevel@tonic-gate 			    (loopback_nconf->nc_semantics == NC_TPI_COTS ||
278*7c478bd9Sstevel@tonic-gate 			    loopback_nconf->nc_semantics == NC_TPI_COTS_ORD)) {
279*7c478bd9Sstevel@tonic-gate 				loopback_netid = loopback_nconf->nc_netid;
280*7c478bd9Sstevel@tonic-gate 				break;
281*7c478bd9Sstevel@tonic-gate 			}
282*7c478bd9Sstevel@tonic-gate 		}
283*7c478bd9Sstevel@tonic-gate 		if (loopback_netid == NULL) {
284*7c478bd9Sstevel@tonic-gate 			endnetconfig(handle);
285*7c478bd9Sstevel@tonic-gate 		}
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate 	if (function == NONE) {
288*7c478bd9Sstevel@tonic-gate 		if (argc - optind > 1)
289*7c478bd9Sstevel@tonic-gate 			function = PROGPING;
290*7c478bd9Sstevel@tonic-gate 		else
291*7c478bd9Sstevel@tonic-gate 			function = RPCBDUMP;
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	switch (function) {
295*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
296*7c478bd9Sstevel@tonic-gate 	case PMAPDUMP:
297*7c478bd9Sstevel@tonic-gate 		if (portnum != 0) {
298*7c478bd9Sstevel@tonic-gate 			usage();
299*7c478bd9Sstevel@tonic-gate 			return (1);
300*7c478bd9Sstevel@tonic-gate 		}
301*7c478bd9Sstevel@tonic-gate 		pmapdump(argc - optind, argv + optind);
302*7c478bd9Sstevel@tonic-gate 		break;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	case UDPPING:
305*7c478bd9Sstevel@tonic-gate 		ip_ping(portnum, "udp", argc - optind, argv + optind);
306*7c478bd9Sstevel@tonic-gate 		break;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	case TCPPING:
309*7c478bd9Sstevel@tonic-gate 		ip_ping(portnum, "tcp", argc - optind, argv + optind);
310*7c478bd9Sstevel@tonic-gate 		break;
311*7c478bd9Sstevel@tonic-gate #endif
312*7c478bd9Sstevel@tonic-gate 	case BROADCAST:
313*7c478bd9Sstevel@tonic-gate 		brdcst(argc - optind, argv + optind);
314*7c478bd9Sstevel@tonic-gate 		break;
315*7c478bd9Sstevel@tonic-gate 	case DELETES:
316*7c478bd9Sstevel@tonic-gate 		deletereg(netid, argc - optind, argv + optind);
317*7c478bd9Sstevel@tonic-gate 		break;
318*7c478bd9Sstevel@tonic-gate 	case ADDRPING:
319*7c478bd9Sstevel@tonic-gate 		addrping(address, netid, argc - optind, argv + optind);
320*7c478bd9Sstevel@tonic-gate 		break;
321*7c478bd9Sstevel@tonic-gate 	case PROGPING:
322*7c478bd9Sstevel@tonic-gate 		progping(netid, argc - optind, argv + optind);
323*7c478bd9Sstevel@tonic-gate 		break;
324*7c478bd9Sstevel@tonic-gate 	case RPCBDUMP:
325*7c478bd9Sstevel@tonic-gate 	case RPCBDUMP_SHORT:
326*7c478bd9Sstevel@tonic-gate 		rpcbdump(function, netid, argc - optind, argv + optind);
327*7c478bd9Sstevel@tonic-gate 		break;
328*7c478bd9Sstevel@tonic-gate 	case RPCBGETSTAT:
329*7c478bd9Sstevel@tonic-gate 		rpcbgetstat(argc - optind, argv + optind);
330*7c478bd9Sstevel@tonic-gate 		break;
331*7c478bd9Sstevel@tonic-gate 	case RPCBADDRLIST:
332*7c478bd9Sstevel@tonic-gate 		rpcbaddrlist(netid, argc - optind, argv + optind);
333*7c478bd9Sstevel@tonic-gate 		break;
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 	return (0);
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
339*7c478bd9Sstevel@tonic-gate static CLIENT *
340*7c478bd9Sstevel@tonic-gate clnt_com_create(addr, prog, vers, fdp, trans)
341*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *addr;
342*7c478bd9Sstevel@tonic-gate 	ulong_t prog;
343*7c478bd9Sstevel@tonic-gate 	ulong_t vers;
344*7c478bd9Sstevel@tonic-gate 	int *fdp;
345*7c478bd9Sstevel@tonic-gate 	char *trans;
346*7c478bd9Sstevel@tonic-gate {
347*7c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	if (strcmp(trans, "tcp") == 0) {
350*7c478bd9Sstevel@tonic-gate 		clnt = clnttcp_create(addr, prog, vers, fdp, 0, 0);
351*7c478bd9Sstevel@tonic-gate 	} else {
352*7c478bd9Sstevel@tonic-gate 		struct timeval to;
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 		to.tv_sec = 5;
355*7c478bd9Sstevel@tonic-gate 		to.tv_usec = 0;
356*7c478bd9Sstevel@tonic-gate 		clnt = clntudp_create(addr, prog, vers, to, fdp);
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 	if (clnt == (CLIENT *)NULL) {
359*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo");
360*7c478bd9Sstevel@tonic-gate 		if (vers == MIN_VERS)
361*7c478bd9Sstevel@tonic-gate 			printf("program %lu is not available\n", prog);
362*7c478bd9Sstevel@tonic-gate 		else
363*7c478bd9Sstevel@tonic-gate 			printf("program %lu version %lu is not available\n",
364*7c478bd9Sstevel@tonic-gate 							prog, vers);
365*7c478bd9Sstevel@tonic-gate 		exit(1);
366*7c478bd9Sstevel@tonic-gate 	}
367*7c478bd9Sstevel@tonic-gate 	return (clnt);
368*7c478bd9Sstevel@tonic-gate }
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate /*
371*7c478bd9Sstevel@tonic-gate  * If portnum is 0, then go and get the address from portmapper, which happens
372*7c478bd9Sstevel@tonic-gate  * transparently through clnt*_create(); If version number is not given, it
373*7c478bd9Sstevel@tonic-gate  * tries to find out the version number by making a call to version 0 and if
374*7c478bd9Sstevel@tonic-gate  * that fails, it obtains the high order and the low order version number. If
375*7c478bd9Sstevel@tonic-gate  * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
376*7c478bd9Sstevel@tonic-gate  */
377*7c478bd9Sstevel@tonic-gate static void
378*7c478bd9Sstevel@tonic-gate ip_ping(portnum, trans, argc, argv)
379*7c478bd9Sstevel@tonic-gate 	ushort_t portnum;
380*7c478bd9Sstevel@tonic-gate 	char *trans;
381*7c478bd9Sstevel@tonic-gate 	int argc;
382*7c478bd9Sstevel@tonic-gate 	char **argv;
383*7c478bd9Sstevel@tonic-gate {
384*7c478bd9Sstevel@tonic-gate 	CLIENT *client;
385*7c478bd9Sstevel@tonic-gate 	int fd = RPC_ANYFD;
386*7c478bd9Sstevel@tonic-gate 	struct timeval to;
387*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in addr;
388*7c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
389*7c478bd9Sstevel@tonic-gate 	ulong_t prognum, vers, minvers, maxvers;
390*7c478bd9Sstevel@tonic-gate 	struct rpc_err rpcerr;
391*7c478bd9Sstevel@tonic-gate 	int failure = 0;
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	if (argc < 2 || argc > 3) {
394*7c478bd9Sstevel@tonic-gate 		usage();
395*7c478bd9Sstevel@tonic-gate 		exit(1);
396*7c478bd9Sstevel@tonic-gate 	}
397*7c478bd9Sstevel@tonic-gate 	to.tv_sec = 10;
398*7c478bd9Sstevel@tonic-gate 	to.tv_usec = 0;
399*7c478bd9Sstevel@tonic-gate 	prognum = getprognum(argv[1]);
400*7c478bd9Sstevel@tonic-gate 	get_inet_address(&addr, argv[0]);
401*7c478bd9Sstevel@tonic-gate 	if (argc == 2) {	/* Version number not known */
402*7c478bd9Sstevel@tonic-gate 		/*
403*7c478bd9Sstevel@tonic-gate 		 * A call to version 0 should fail with a program/version
404*7c478bd9Sstevel@tonic-gate 		 * mismatch, and give us the range of versions supported.
405*7c478bd9Sstevel@tonic-gate 		 */
406*7c478bd9Sstevel@tonic-gate 		vers = MIN_VERS;
407*7c478bd9Sstevel@tonic-gate 	} else {
408*7c478bd9Sstevel@tonic-gate 		vers = getvers(argv[2]);
409*7c478bd9Sstevel@tonic-gate 	}
410*7c478bd9Sstevel@tonic-gate 	addr.sin_port = htons(portnum);
411*7c478bd9Sstevel@tonic-gate 	client = clnt_com_create(&addr, prognum, vers, &fd, trans);
412*7c478bd9Sstevel@tonic-gate 	rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
413*7c478bd9Sstevel@tonic-gate 			(char *)NULL, (xdrproc_t)xdr_void, (char *)NULL,
414*7c478bd9Sstevel@tonic-gate 			to);
415*7c478bd9Sstevel@tonic-gate 	if (argc != 2) {
416*7c478bd9Sstevel@tonic-gate 		/* Version number was known */
417*7c478bd9Sstevel@tonic-gate 		if (pstatus(client, prognum, vers) < 0)
418*7c478bd9Sstevel@tonic-gate 			exit(1);
419*7c478bd9Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
420*7c478bd9Sstevel@tonic-gate 		return;
421*7c478bd9Sstevel@tonic-gate 	}
422*7c478bd9Sstevel@tonic-gate 	/* Version number not known */
423*7c478bd9Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
424*7c478bd9Sstevel@tonic-gate 	if (rpc_stat == RPC_PROGVERSMISMATCH) {
425*7c478bd9Sstevel@tonic-gate 		clnt_geterr(client, &rpcerr);
426*7c478bd9Sstevel@tonic-gate 		minvers = rpcerr.re_vers.low;
427*7c478bd9Sstevel@tonic-gate 		maxvers = rpcerr.re_vers.high;
428*7c478bd9Sstevel@tonic-gate 	} else if (rpc_stat == RPC_SUCCESS) {
429*7c478bd9Sstevel@tonic-gate 		/*
430*7c478bd9Sstevel@tonic-gate 		 * Oh dear, it DOES support version 0.
431*7c478bd9Sstevel@tonic-gate 		 * Let's try version MAX_VERS.
432*7c478bd9Sstevel@tonic-gate 		 */
433*7c478bd9Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
434*7c478bd9Sstevel@tonic-gate 		addr.sin_port = htons(portnum);
435*7c478bd9Sstevel@tonic-gate 		client = clnt_com_create(&addr, prognum, MAX_VERS, &fd, trans);
436*7c478bd9Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
437*7c478bd9Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
438*7c478bd9Sstevel@tonic-gate 				(char *)NULL, to);
439*7c478bd9Sstevel@tonic-gate 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
440*7c478bd9Sstevel@tonic-gate 			clnt_geterr(client, &rpcerr);
441*7c478bd9Sstevel@tonic-gate 			minvers = rpcerr.re_vers.low;
442*7c478bd9Sstevel@tonic-gate 			maxvers = rpcerr.re_vers.high;
443*7c478bd9Sstevel@tonic-gate 		} else if (rpc_stat == RPC_SUCCESS) {
444*7c478bd9Sstevel@tonic-gate 			/*
445*7c478bd9Sstevel@tonic-gate 			 * It also supports version MAX_VERS.
446*7c478bd9Sstevel@tonic-gate 			 * Looks like we have a wise guy.
447*7c478bd9Sstevel@tonic-gate 			 * OK, we give them information on all
448*7c478bd9Sstevel@tonic-gate 			 * 4 billion versions they support...
449*7c478bd9Sstevel@tonic-gate 			 */
450*7c478bd9Sstevel@tonic-gate 			minvers = 0;
451*7c478bd9Sstevel@tonic-gate 			maxvers = MAX_VERS;
452*7c478bd9Sstevel@tonic-gate 		} else {
453*7c478bd9Sstevel@tonic-gate 			(void) pstatus(client, prognum, MAX_VERS);
454*7c478bd9Sstevel@tonic-gate 			exit(1);
455*7c478bd9Sstevel@tonic-gate 		}
456*7c478bd9Sstevel@tonic-gate 	} else {
457*7c478bd9Sstevel@tonic-gate 		(void) pstatus(client, prognum, (ulong_t)0);
458*7c478bd9Sstevel@tonic-gate 		exit(1);
459*7c478bd9Sstevel@tonic-gate 	}
460*7c478bd9Sstevel@tonic-gate 	(void) CLNT_DESTROY(client);
461*7c478bd9Sstevel@tonic-gate 	for (vers = minvers; vers <= maxvers; vers++) {
462*7c478bd9Sstevel@tonic-gate 		addr.sin_port = htons(portnum);
463*7c478bd9Sstevel@tonic-gate 		client = clnt_com_create(&addr, prognum, vers, &fd, trans);
464*7c478bd9Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
465*7c478bd9Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
466*7c478bd9Sstevel@tonic-gate 				(char *)NULL, to);
467*7c478bd9Sstevel@tonic-gate 		if (pstatus(client, prognum, vers) < 0)
468*7c478bd9Sstevel@tonic-gate 				failure = 1;
469*7c478bd9Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
470*7c478bd9Sstevel@tonic-gate 	}
471*7c478bd9Sstevel@tonic-gate 	if (failure)
472*7c478bd9Sstevel@tonic-gate 		exit(1);
473*7c478bd9Sstevel@tonic-gate 	(void) t_close(fd);
474*7c478bd9Sstevel@tonic-gate }
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate /*
477*7c478bd9Sstevel@tonic-gate  * Dump all the portmapper registerations
478*7c478bd9Sstevel@tonic-gate  */
479*7c478bd9Sstevel@tonic-gate static void
480*7c478bd9Sstevel@tonic-gate pmapdump(argc, argv)
481*7c478bd9Sstevel@tonic-gate 	int argc;
482*7c478bd9Sstevel@tonic-gate 	char **argv;
483*7c478bd9Sstevel@tonic-gate {
484*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in server_addr;
485*7c478bd9Sstevel@tonic-gate 	pmaplist_ptr head = NULL;
486*7c478bd9Sstevel@tonic-gate 	int socket = RPC_ANYSOCK;
487*7c478bd9Sstevel@tonic-gate 	struct timeval minutetimeout;
488*7c478bd9Sstevel@tonic-gate 	register CLIENT *client;
489*7c478bd9Sstevel@tonic-gate 	struct rpcent *rpc;
490*7c478bd9Sstevel@tonic-gate 	enum clnt_stat clnt_st;
491*7c478bd9Sstevel@tonic-gate 	struct rpc_err err;
492*7c478bd9Sstevel@tonic-gate 	struct utsname utsname;
493*7c478bd9Sstevel@tonic-gate 	char *host;
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	if (argc > 1) {
496*7c478bd9Sstevel@tonic-gate 		usage();
497*7c478bd9Sstevel@tonic-gate 		exit(1);
498*7c478bd9Sstevel@tonic-gate 	}
499*7c478bd9Sstevel@tonic-gate 	if (argc == 1) {
500*7c478bd9Sstevel@tonic-gate 		host = argv[0];
501*7c478bd9Sstevel@tonic-gate 		get_inet_address(&server_addr, host);
502*7c478bd9Sstevel@tonic-gate 	} else {
503*7c478bd9Sstevel@tonic-gate 		uname(&utsname);
504*7c478bd9Sstevel@tonic-gate 		host = utsname.nodename;
505*7c478bd9Sstevel@tonic-gate 		get_inet_address(&server_addr, host);
506*7c478bd9Sstevel@tonic-gate 	}
507*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
508*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
509*7c478bd9Sstevel@tonic-gate 	server_addr.sin_port = htons(PMAPPORT);
510*7c478bd9Sstevel@tonic-gate 	if ((client = clnttcp_create(&server_addr, PMAPPROG,
511*7c478bd9Sstevel@tonic-gate 		PMAPVERS, &socket, 50, 500)) == NULL) {
512*7c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_TLIERROR) {
513*7c478bd9Sstevel@tonic-gate 			/*
514*7c478bd9Sstevel@tonic-gate 			 * "Misc. TLI error" is not too helpful. Most likely
515*7c478bd9Sstevel@tonic-gate 			 * the connection to the remote server timed out, so
516*7c478bd9Sstevel@tonic-gate 			 * this error is at least less perplexing.
517*7c478bd9Sstevel@tonic-gate 			 */
518*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
519*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_error.re_status = RPC_FAILED;
520*7c478bd9Sstevel@tonic-gate 		}
521*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact portmapper");
522*7c478bd9Sstevel@tonic-gate 		exit(1);
523*7c478bd9Sstevel@tonic-gate 	}
524*7c478bd9Sstevel@tonic-gate 	clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t)xdr_void,
525*7c478bd9Sstevel@tonic-gate 		NULL, (xdrproc_t)xdr_pmaplist_ptr, (char *)&head,
526*7c478bd9Sstevel@tonic-gate 		minutetimeout);
527*7c478bd9Sstevel@tonic-gate 	if (clnt_st != RPC_SUCCESS) {
528*7c478bd9Sstevel@tonic-gate 		if ((clnt_st == RPC_PROGVERSMISMATCH) ||
529*7c478bd9Sstevel@tonic-gate 		    (clnt_st == RPC_PROGUNAVAIL)) {
530*7c478bd9Sstevel@tonic-gate 			CLNT_GETERR(client, &err);
531*7c478bd9Sstevel@tonic-gate 			if (err.re_vers.low > PMAPVERS)
532*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
533*7c478bd9Sstevel@tonic-gate 		"%s does not support portmapper.  Try rpcinfo %s instead\n",
534*7c478bd9Sstevel@tonic-gate 					host, host);
535*7c478bd9Sstevel@tonic-gate 			exit(1);
536*7c478bd9Sstevel@tonic-gate 		}
537*7c478bd9Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo: can't contact portmapper");
538*7c478bd9Sstevel@tonic-gate 		exit(1);
539*7c478bd9Sstevel@tonic-gate 	}
540*7c478bd9Sstevel@tonic-gate 	if (head == NULL) {
541*7c478bd9Sstevel@tonic-gate 		printf("No remote programs registered.\n");
542*7c478bd9Sstevel@tonic-gate 	} else {
543*7c478bd9Sstevel@tonic-gate 		printf("   program vers proto   port  service\n");
544*7c478bd9Sstevel@tonic-gate 		for (; head != NULL; head = head->pml_next) {
545*7c478bd9Sstevel@tonic-gate 			printf("%10ld%5ld",
546*7c478bd9Sstevel@tonic-gate 				head->pml_map.pm_prog,
547*7c478bd9Sstevel@tonic-gate 				head->pml_map.pm_vers);
548*7c478bd9Sstevel@tonic-gate 			if (head->pml_map.pm_prot == IPPROTO_UDP)
549*7c478bd9Sstevel@tonic-gate 				printf("%6s", "udp");
550*7c478bd9Sstevel@tonic-gate 			else if (head->pml_map.pm_prot == IPPROTO_TCP)
551*7c478bd9Sstevel@tonic-gate 				printf("%6s", "tcp");
552*7c478bd9Sstevel@tonic-gate 			else
553*7c478bd9Sstevel@tonic-gate 				printf("%6ld", head->pml_map.pm_prot);
554*7c478bd9Sstevel@tonic-gate 			printf("%7ld", head->pml_map.pm_port);
555*7c478bd9Sstevel@tonic-gate 			rpc = getrpcbynumber(head->pml_map.pm_prog);
556*7c478bd9Sstevel@tonic-gate 			if (rpc)
557*7c478bd9Sstevel@tonic-gate 				printf("  %s\n", rpc->r_name);
558*7c478bd9Sstevel@tonic-gate 			else
559*7c478bd9Sstevel@tonic-gate 				printf("\n");
560*7c478bd9Sstevel@tonic-gate 		}
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate static void
565*7c478bd9Sstevel@tonic-gate get_inet_address(addr, host)
566*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *addr;
567*7c478bd9Sstevel@tonic-gate 	char *host;
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
570*7c478bd9Sstevel@tonic-gate 	struct nd_hostserv service;
571*7c478bd9Sstevel@tonic-gate 	struct nd_addrlist *naddrs;
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	(void) memset((char *)addr, 0, sizeof (*addr));
574*7c478bd9Sstevel@tonic-gate 	addr->sin_addr.s_addr = inet_addr(host);
575*7c478bd9Sstevel@tonic-gate 	if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
576*7c478bd9Sstevel@tonic-gate 		if ((nconf = __rpc_getconfip("udp")) == NULL &&
577*7c478bd9Sstevel@tonic-gate 		    (nconf = __rpc_getconfip("tcp")) == NULL) {
578*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
579*7c478bd9Sstevel@tonic-gate 			"rpcinfo: couldn't find a suitable transport\n");
580*7c478bd9Sstevel@tonic-gate 			exit(1);
581*7c478bd9Sstevel@tonic-gate 		} else {
582*7c478bd9Sstevel@tonic-gate 			service.h_host = host;
583*7c478bd9Sstevel@tonic-gate 			service.h_serv = "rpcbind";
584*7c478bd9Sstevel@tonic-gate 			if (netdir_getbyname(nconf, &service, &naddrs)) {
585*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "rpcinfo: %s: %s\n",
586*7c478bd9Sstevel@tonic-gate 						host, netdir_sperror());
587*7c478bd9Sstevel@tonic-gate 				exit(1);
588*7c478bd9Sstevel@tonic-gate 			} else {
589*7c478bd9Sstevel@tonic-gate 				(void) memcpy((caddr_t)addr,
590*7c478bd9Sstevel@tonic-gate 				    naddrs->n_addrs->buf, naddrs->n_addrs->len);
591*7c478bd9Sstevel@tonic-gate 				(void) netdir_free((char *)naddrs, ND_ADDRLIST);
592*7c478bd9Sstevel@tonic-gate 			}
593*7c478bd9Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
594*7c478bd9Sstevel@tonic-gate 		}
595*7c478bd9Sstevel@tonic-gate 	} else {
596*7c478bd9Sstevel@tonic-gate 		addr->sin_family = AF_INET;
597*7c478bd9Sstevel@tonic-gate 	}
598*7c478bd9Sstevel@tonic-gate }
599*7c478bd9Sstevel@tonic-gate #endif /* PORTMAP */
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate /*
602*7c478bd9Sstevel@tonic-gate  * reply_proc collects replies from the broadcast.
603*7c478bd9Sstevel@tonic-gate  * to get a unique list of responses the output of rpcinfo should
604*7c478bd9Sstevel@tonic-gate  * be piped through sort(1) and then uniq(1).
605*7c478bd9Sstevel@tonic-gate  */
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
608*7c478bd9Sstevel@tonic-gate static bool_t
609*7c478bd9Sstevel@tonic-gate reply_proc(res, who, nconf)
610*7c478bd9Sstevel@tonic-gate 	void *res;		/* Nothing comes back */
611*7c478bd9Sstevel@tonic-gate 	struct netbuf *who;	/* Who sent us the reply */
612*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf; /* On which transport the reply came */
613*7c478bd9Sstevel@tonic-gate {
614*7c478bd9Sstevel@tonic-gate 	struct nd_hostservlist *serv;
615*7c478bd9Sstevel@tonic-gate 	char *uaddr;
616*7c478bd9Sstevel@tonic-gate 	char *hostname;
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 	if (netdir_getbyaddr(nconf, &serv, who)) {
619*7c478bd9Sstevel@tonic-gate 		hostname = UNKNOWN;
620*7c478bd9Sstevel@tonic-gate 	} else {
621*7c478bd9Sstevel@tonic-gate 		hostname = serv->h_hostservs->h_host;
622*7c478bd9Sstevel@tonic-gate 	}
623*7c478bd9Sstevel@tonic-gate 	if (!(uaddr = taddr2uaddr(nconf, who))) {
624*7c478bd9Sstevel@tonic-gate 		uaddr = UNKNOWN;
625*7c478bd9Sstevel@tonic-gate 	}
626*7c478bd9Sstevel@tonic-gate 	printf("%s\t%s\n", uaddr, hostname);
627*7c478bd9Sstevel@tonic-gate 	if (strcmp(hostname, UNKNOWN))
628*7c478bd9Sstevel@tonic-gate 		netdir_free((char *)serv, ND_HOSTSERVLIST);
629*7c478bd9Sstevel@tonic-gate 	if (strcmp(uaddr, UNKNOWN))
630*7c478bd9Sstevel@tonic-gate 		free((char *)uaddr);
631*7c478bd9Sstevel@tonic-gate 	return (FALSE);
632*7c478bd9Sstevel@tonic-gate }
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate static void
635*7c478bd9Sstevel@tonic-gate brdcst(argc, argv)
636*7c478bd9Sstevel@tonic-gate 	int argc;
637*7c478bd9Sstevel@tonic-gate 	char **argv;
638*7c478bd9Sstevel@tonic-gate {
639*7c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
640*7c478bd9Sstevel@tonic-gate 	ulong_t prognum, vers;
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 	if (argc != 2) {
643*7c478bd9Sstevel@tonic-gate 		usage();
644*7c478bd9Sstevel@tonic-gate 		exit(1);
645*7c478bd9Sstevel@tonic-gate 	}
646*7c478bd9Sstevel@tonic-gate 	prognum = getprognum(argv[0]);
647*7c478bd9Sstevel@tonic-gate 	vers = getvers(argv[1]);
648*7c478bd9Sstevel@tonic-gate 	rpc_stat = rpc_broadcast(prognum, vers, NULLPROC,
649*7c478bd9Sstevel@tonic-gate 		(xdrproc_t)xdr_void, (char *)NULL, (xdrproc_t)xdr_void,
650*7c478bd9Sstevel@tonic-gate 		(char *)NULL, (resultproc_t)reply_proc, NULL);
651*7c478bd9Sstevel@tonic-gate 	if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
652*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
653*7c478bd9Sstevel@tonic-gate 			clnt_sperrno(rpc_stat));
654*7c478bd9Sstevel@tonic-gate 		exit(1);
655*7c478bd9Sstevel@tonic-gate 	}
656*7c478bd9Sstevel@tonic-gate 	exit(0);
657*7c478bd9Sstevel@tonic-gate }
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate static bool_t
660*7c478bd9Sstevel@tonic-gate add_version(rs, vers)
661*7c478bd9Sstevel@tonic-gate 	struct rpcbdump_short *rs;
662*7c478bd9Sstevel@tonic-gate 	ulong_t vers;
663*7c478bd9Sstevel@tonic-gate {
664*7c478bd9Sstevel@tonic-gate 	struct verslist *vl;
665*7c478bd9Sstevel@tonic-gate 
666*7c478bd9Sstevel@tonic-gate 	for (vl = rs->vlist; vl; vl = vl->next)
667*7c478bd9Sstevel@tonic-gate 		if (vl->vers == vers)
668*7c478bd9Sstevel@tonic-gate 			break;
669*7c478bd9Sstevel@tonic-gate 	if (vl)
670*7c478bd9Sstevel@tonic-gate 		return (TRUE);
671*7c478bd9Sstevel@tonic-gate 	vl = (struct verslist *)malloc(sizeof (struct verslist));
672*7c478bd9Sstevel@tonic-gate 	if (vl == NULL)
673*7c478bd9Sstevel@tonic-gate 		return (FALSE);
674*7c478bd9Sstevel@tonic-gate 	vl->vers = vers;
675*7c478bd9Sstevel@tonic-gate 	vl->next = rs->vlist;
676*7c478bd9Sstevel@tonic-gate 	rs->vlist = vl;
677*7c478bd9Sstevel@tonic-gate 	return (TRUE);
678*7c478bd9Sstevel@tonic-gate }
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate static bool_t
681*7c478bd9Sstevel@tonic-gate add_netid(rs, netid)
682*7c478bd9Sstevel@tonic-gate 	struct rpcbdump_short *rs;
683*7c478bd9Sstevel@tonic-gate 	char *netid;
684*7c478bd9Sstevel@tonic-gate {
685*7c478bd9Sstevel@tonic-gate 	struct netidlist *nl;
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 	for (nl = rs->nlist; nl; nl = nl->next)
688*7c478bd9Sstevel@tonic-gate 		if (strcmp(nl->netid, netid) == 0)
689*7c478bd9Sstevel@tonic-gate 			break;
690*7c478bd9Sstevel@tonic-gate 	if (nl)
691*7c478bd9Sstevel@tonic-gate 		return (TRUE);
692*7c478bd9Sstevel@tonic-gate 	nl = (struct netidlist *)malloc(sizeof (struct netidlist));
693*7c478bd9Sstevel@tonic-gate 	if (nl == NULL)
694*7c478bd9Sstevel@tonic-gate 		return (FALSE);
695*7c478bd9Sstevel@tonic-gate 	nl->netid = netid;
696*7c478bd9Sstevel@tonic-gate 	nl->next = rs->nlist;
697*7c478bd9Sstevel@tonic-gate 	rs->nlist = nl;
698*7c478bd9Sstevel@tonic-gate 	return (TRUE);
699*7c478bd9Sstevel@tonic-gate }
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate static void
702*7c478bd9Sstevel@tonic-gate rpcbdump(dumptype, netid, argc, argv)
703*7c478bd9Sstevel@tonic-gate 	int dumptype;
704*7c478bd9Sstevel@tonic-gate 	char *netid;
705*7c478bd9Sstevel@tonic-gate 	int argc;
706*7c478bd9Sstevel@tonic-gate 	char **argv;
707*7c478bd9Sstevel@tonic-gate {
708*7c478bd9Sstevel@tonic-gate 	rpcblist_ptr head = NULL;
709*7c478bd9Sstevel@tonic-gate 	struct timeval minutetimeout;
710*7c478bd9Sstevel@tonic-gate 	register CLIENT *client;
711*7c478bd9Sstevel@tonic-gate 	struct rpcent *rpc;
712*7c478bd9Sstevel@tonic-gate 	char *host;
713*7c478bd9Sstevel@tonic-gate 	struct netidlist *nl;
714*7c478bd9Sstevel@tonic-gate 	struct verslist *vl;
715*7c478bd9Sstevel@tonic-gate 	struct rpcbdump_short *rs, *rs_tail;
716*7c478bd9Sstevel@tonic-gate 	char buf[256];
717*7c478bd9Sstevel@tonic-gate 	enum clnt_stat clnt_st;
718*7c478bd9Sstevel@tonic-gate 	struct rpc_err err;
719*7c478bd9Sstevel@tonic-gate 	struct utsname utsname;
720*7c478bd9Sstevel@tonic-gate 	struct rpcbdump_short *rs_head = NULL;
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	if (argc > 1) {
723*7c478bd9Sstevel@tonic-gate 		usage();
724*7c478bd9Sstevel@tonic-gate 		exit(1);
725*7c478bd9Sstevel@tonic-gate 	}
726*7c478bd9Sstevel@tonic-gate 	if (argc == 1) {
727*7c478bd9Sstevel@tonic-gate 		host = argv[0];
728*7c478bd9Sstevel@tonic-gate 	} else {
729*7c478bd9Sstevel@tonic-gate 		uname(&utsname);
730*7c478bd9Sstevel@tonic-gate 		host = utsname.nodename;
731*7c478bd9Sstevel@tonic-gate 	}
732*7c478bd9Sstevel@tonic-gate 	if (netid == NULL) {
733*7c478bd9Sstevel@tonic-gate 	    if (loopback_netid == NULL) {
734*7c478bd9Sstevel@tonic-gate 		client = clnt_rpcbind_create(host, RPCBVERS, NULL);
735*7c478bd9Sstevel@tonic-gate 	    } else {
736*7c478bd9Sstevel@tonic-gate 		client = getclnthandle(host, loopback_nconf, RPCBVERS, NULL);
737*7c478bd9Sstevel@tonic-gate 		if (client == NULL && rpc_createerr.cf_stat ==
738*7c478bd9Sstevel@tonic-gate 				RPC_N2AXLATEFAILURE) {
739*7c478bd9Sstevel@tonic-gate 			client = clnt_rpcbind_create(host, RPCBVERS, NULL);
740*7c478bd9Sstevel@tonic-gate 		}
741*7c478bd9Sstevel@tonic-gate 	    }
742*7c478bd9Sstevel@tonic-gate 	} else {
743*7c478bd9Sstevel@tonic-gate 		struct netconfig *nconf;
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
746*7c478bd9Sstevel@tonic-gate 		if (nconf == NULL) {
747*7c478bd9Sstevel@tonic-gate 			nc_perror("rpcinfo: invalid transport");
748*7c478bd9Sstevel@tonic-gate 			exit(1);
749*7c478bd9Sstevel@tonic-gate 		}
750*7c478bd9Sstevel@tonic-gate 		client = getclnthandle(host, nconf, RPCBVERS, NULL);
751*7c478bd9Sstevel@tonic-gate 		if (nconf)
752*7c478bd9Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
753*7c478bd9Sstevel@tonic-gate 	}
754*7c478bd9Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
755*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact rpcbind");
756*7c478bd9Sstevel@tonic-gate 		exit(1);
757*7c478bd9Sstevel@tonic-gate 	}
758*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
759*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
760*7c478bd9Sstevel@tonic-gate 	clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, (xdrproc_t)xdr_void,
761*7c478bd9Sstevel@tonic-gate 		NULL, (xdrproc_t)xdr_rpcblist_ptr, (char *)&head,
762*7c478bd9Sstevel@tonic-gate 		minutetimeout);
763*7c478bd9Sstevel@tonic-gate 	if (clnt_st != RPC_SUCCESS) {
764*7c478bd9Sstevel@tonic-gate 	    if ((clnt_st == RPC_PROGVERSMISMATCH) ||
765*7c478bd9Sstevel@tonic-gate 		(clnt_st == RPC_PROGUNAVAIL)) {
766*7c478bd9Sstevel@tonic-gate 		int vers;
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate 		CLNT_GETERR(client, &err);
769*7c478bd9Sstevel@tonic-gate 		if (err.re_vers.low == RPCBVERS4) {
770*7c478bd9Sstevel@tonic-gate 		    vers = RPCBVERS4;
771*7c478bd9Sstevel@tonic-gate 		    clnt_control(client, CLSET_VERS, (char *)&vers);
772*7c478bd9Sstevel@tonic-gate 		    clnt_st = CLNT_CALL(client, RPCBPROC_DUMP,
773*7c478bd9Sstevel@tonic-gate 			(xdrproc_t)xdr_void, NULL,
774*7c478bd9Sstevel@tonic-gate 			(xdrproc_t)xdr_rpcblist_ptr, (char *)&head,
775*7c478bd9Sstevel@tonic-gate 			minutetimeout);
776*7c478bd9Sstevel@tonic-gate 		    if (clnt_st != RPC_SUCCESS)
777*7c478bd9Sstevel@tonic-gate 			goto failed;
778*7c478bd9Sstevel@tonic-gate 		} else {
779*7c478bd9Sstevel@tonic-gate 		    if (err.re_vers.high == PMAPVERS) {
780*7c478bd9Sstevel@tonic-gate 			int high, low;
781*7c478bd9Sstevel@tonic-gate 			pmaplist_ptr pmaphead = NULL;
782*7c478bd9Sstevel@tonic-gate 			rpcblist_ptr list, prev;
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 			vers = PMAPVERS;
785*7c478bd9Sstevel@tonic-gate 			clnt_control(client, CLSET_VERS, (char *)&vers);
786*7c478bd9Sstevel@tonic-gate 			clnt_st = CLNT_CALL(client, PMAPPROC_DUMP,
787*7c478bd9Sstevel@tonic-gate 				(xdrproc_t)xdr_void, NULL,
788*7c478bd9Sstevel@tonic-gate 				(xdrproc_t)xdr_pmaplist_ptr,
789*7c478bd9Sstevel@tonic-gate 				(char *)&pmaphead, minutetimeout);
790*7c478bd9Sstevel@tonic-gate 			if (clnt_st != RPC_SUCCESS)
791*7c478bd9Sstevel@tonic-gate 				goto failed;
792*7c478bd9Sstevel@tonic-gate 			/*
793*7c478bd9Sstevel@tonic-gate 			 * convert to rpcblist_ptr format
794*7c478bd9Sstevel@tonic-gate 			 */
795*7c478bd9Sstevel@tonic-gate 			for (head = NULL; pmaphead != NULL;
796*7c478bd9Sstevel@tonic-gate 				pmaphead = pmaphead->pml_next) {
797*7c478bd9Sstevel@tonic-gate 			    list = (rpcblist *)malloc(sizeof (rpcblist));
798*7c478bd9Sstevel@tonic-gate 			    if (list == NULL)
799*7c478bd9Sstevel@tonic-gate 				goto error;
800*7c478bd9Sstevel@tonic-gate 			    if (head == NULL)
801*7c478bd9Sstevel@tonic-gate 				head = list;
802*7c478bd9Sstevel@tonic-gate 			    else
803*7c478bd9Sstevel@tonic-gate 				prev->rpcb_next = (rpcblist_ptr) list;
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate 			    list->rpcb_next = NULL;
806*7c478bd9Sstevel@tonic-gate 			    list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog;
807*7c478bd9Sstevel@tonic-gate 			    list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers;
808*7c478bd9Sstevel@tonic-gate 			    if (pmaphead->pml_map.pm_prot == IPPROTO_UDP)
809*7c478bd9Sstevel@tonic-gate 				list->rpcb_map.r_netid = "udp";
810*7c478bd9Sstevel@tonic-gate 			    else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP)
811*7c478bd9Sstevel@tonic-gate 				list->rpcb_map.r_netid = "tcp";
812*7c478bd9Sstevel@tonic-gate 			    else {
813*7c478bd9Sstevel@tonic-gate #define	MAXLONG_AS_STRING	"2147483648"
814*7c478bd9Sstevel@tonic-gate 				list->rpcb_map.r_netid =
815*7c478bd9Sstevel@tonic-gate 					malloc(strlen(MAXLONG_AS_STRING) + 1);
816*7c478bd9Sstevel@tonic-gate 				if (list->rpcb_map.r_netid == NULL)
817*7c478bd9Sstevel@tonic-gate 					goto error;
818*7c478bd9Sstevel@tonic-gate 				sprintf(list->rpcb_map.r_netid, "%6ld",
819*7c478bd9Sstevel@tonic-gate 					pmaphead->pml_map.pm_prot);
820*7c478bd9Sstevel@tonic-gate 			    }
821*7c478bd9Sstevel@tonic-gate 			    list->rpcb_map.r_owner = UNKNOWN;
822*7c478bd9Sstevel@tonic-gate 			    low = pmaphead->pml_map.pm_port & 0xff;
823*7c478bd9Sstevel@tonic-gate 			    high = (pmaphead->pml_map.pm_port >> 8) & 0xff;
824*7c478bd9Sstevel@tonic-gate 			    list->rpcb_map.r_addr = strdup("0.0.0.0.XXX.XXX");
825*7c478bd9Sstevel@tonic-gate 			    sprintf(&list->rpcb_map.r_addr[8], "%d.%d",
826*7c478bd9Sstevel@tonic-gate 				high, low);
827*7c478bd9Sstevel@tonic-gate 			    prev = list;
828*7c478bd9Sstevel@tonic-gate 			}
829*7c478bd9Sstevel@tonic-gate 		    }
830*7c478bd9Sstevel@tonic-gate 		}
831*7c478bd9Sstevel@tonic-gate 	    } else {	/* any other error */
832*7c478bd9Sstevel@tonic-gate failed:
833*7c478bd9Sstevel@tonic-gate 		    clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
834*7c478bd9Sstevel@tonic-gate 		    exit(1);
835*7c478bd9Sstevel@tonic-gate 	    }
836*7c478bd9Sstevel@tonic-gate 	}
837*7c478bd9Sstevel@tonic-gate 	if (head == NULL) {
838*7c478bd9Sstevel@tonic-gate 		printf("No remote programs registered.\n");
839*7c478bd9Sstevel@tonic-gate 	} else if (dumptype == RPCBDUMP) {
840*7c478bd9Sstevel@tonic-gate 		printf(
841*7c478bd9Sstevel@tonic-gate "   program version netid     address             service    owner\n");
842*7c478bd9Sstevel@tonic-gate 		for (; head != NULL; head = head->rpcb_next) {
843*7c478bd9Sstevel@tonic-gate 			printf("%10ld%5ld    ",
844*7c478bd9Sstevel@tonic-gate 				head->rpcb_map.r_prog, head->rpcb_map.r_vers);
845*7c478bd9Sstevel@tonic-gate 			printf("%-9s ", head->rpcb_map.r_netid);
846*7c478bd9Sstevel@tonic-gate 			printf("%-19s", head->rpcb_map.r_addr);
847*7c478bd9Sstevel@tonic-gate 			rpc = getrpcbynumber(head->rpcb_map.r_prog);
848*7c478bd9Sstevel@tonic-gate 			if (rpc)
849*7c478bd9Sstevel@tonic-gate 				printf(" %-10s", rpc->r_name);
850*7c478bd9Sstevel@tonic-gate 			else
851*7c478bd9Sstevel@tonic-gate 				printf(" %-10s", "-");
852*7c478bd9Sstevel@tonic-gate 			printf(" %s\n", head->rpcb_map.r_owner);
853*7c478bd9Sstevel@tonic-gate 		}
854*7c478bd9Sstevel@tonic-gate 	} else if (dumptype == RPCBDUMP_SHORT) {
855*7c478bd9Sstevel@tonic-gate 		for (; head != NULL; head = head->rpcb_next) {
856*7c478bd9Sstevel@tonic-gate 			for (rs = rs_head; rs; rs = rs->next)
857*7c478bd9Sstevel@tonic-gate 				if (head->rpcb_map.r_prog == rs->prog)
858*7c478bd9Sstevel@tonic-gate 					break;
859*7c478bd9Sstevel@tonic-gate 			if (rs == NULL) {
860*7c478bd9Sstevel@tonic-gate 				rs = (struct rpcbdump_short *)
861*7c478bd9Sstevel@tonic-gate 					malloc(sizeof (struct rpcbdump_short));
862*7c478bd9Sstevel@tonic-gate 				if (rs == NULL)
863*7c478bd9Sstevel@tonic-gate 					goto error;
864*7c478bd9Sstevel@tonic-gate 				rs->next = NULL;
865*7c478bd9Sstevel@tonic-gate 				if (rs_head == NULL) {
866*7c478bd9Sstevel@tonic-gate 					rs_head = rs;
867*7c478bd9Sstevel@tonic-gate 					rs_tail = rs;
868*7c478bd9Sstevel@tonic-gate 				} else {
869*7c478bd9Sstevel@tonic-gate 					rs_tail->next = rs;
870*7c478bd9Sstevel@tonic-gate 					rs_tail = rs;
871*7c478bd9Sstevel@tonic-gate 				}
872*7c478bd9Sstevel@tonic-gate 				rs->prog = head->rpcb_map.r_prog;
873*7c478bd9Sstevel@tonic-gate 				rs->owner = head->rpcb_map.r_owner;
874*7c478bd9Sstevel@tonic-gate 				rs->nlist = NULL;
875*7c478bd9Sstevel@tonic-gate 				rs->vlist = NULL;
876*7c478bd9Sstevel@tonic-gate 			}
877*7c478bd9Sstevel@tonic-gate 			if (add_version(rs, head->rpcb_map.r_vers) == FALSE)
878*7c478bd9Sstevel@tonic-gate 				goto error;
879*7c478bd9Sstevel@tonic-gate 			if (add_netid(rs, head->rpcb_map.r_netid) == FALSE)
880*7c478bd9Sstevel@tonic-gate 				goto error;
881*7c478bd9Sstevel@tonic-gate 		}
882*7c478bd9Sstevel@tonic-gate 		printf(
883*7c478bd9Sstevel@tonic-gate "   program version(s) netid(s)                         service     owner\n");
884*7c478bd9Sstevel@tonic-gate 		for (rs = rs_head; rs; rs = rs->next) {
885*7c478bd9Sstevel@tonic-gate 			char *p = buf;
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate 			printf("%10ld  ", rs->prog);
888*7c478bd9Sstevel@tonic-gate 			for (vl = rs->vlist; vl; vl = vl->next) {
889*7c478bd9Sstevel@tonic-gate 				sprintf(p, "%d", vl->vers);
890*7c478bd9Sstevel@tonic-gate 				p = p + strlen(p);
891*7c478bd9Sstevel@tonic-gate 				if (vl->next)
892*7c478bd9Sstevel@tonic-gate 					sprintf(p++, ",");
893*7c478bd9Sstevel@tonic-gate 			}
894*7c478bd9Sstevel@tonic-gate 			printf("%-10s", buf);
895*7c478bd9Sstevel@tonic-gate 			buf[0] = NULL;
896*7c478bd9Sstevel@tonic-gate 			for (nl = rs->nlist; nl; nl = nl->next) {
897*7c478bd9Sstevel@tonic-gate 				strcat(buf, nl->netid);
898*7c478bd9Sstevel@tonic-gate 				if (nl->next)
899*7c478bd9Sstevel@tonic-gate 					strcat(buf, ",");
900*7c478bd9Sstevel@tonic-gate 			}
901*7c478bd9Sstevel@tonic-gate 			printf("%-32s", buf);
902*7c478bd9Sstevel@tonic-gate 			rpc = getrpcbynumber(rs->prog);
903*7c478bd9Sstevel@tonic-gate 			if (rpc)
904*7c478bd9Sstevel@tonic-gate 				printf(" %-11s", rpc->r_name);
905*7c478bd9Sstevel@tonic-gate 			else
906*7c478bd9Sstevel@tonic-gate 				printf(" %-11s", "-");
907*7c478bd9Sstevel@tonic-gate 			printf(" %s\n", rs->owner);
908*7c478bd9Sstevel@tonic-gate 		}
909*7c478bd9Sstevel@tonic-gate 	}
910*7c478bd9Sstevel@tonic-gate 	clnt_destroy(client);
911*7c478bd9Sstevel@tonic-gate 	return;
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate error:	fprintf(stderr, "rpcinfo: no memory\n");
914*7c478bd9Sstevel@tonic-gate }
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate static char nullstring[] = "\000";
917*7c478bd9Sstevel@tonic-gate 
918*7c478bd9Sstevel@tonic-gate static void
919*7c478bd9Sstevel@tonic-gate rpcbaddrlist(netid, argc, argv)
920*7c478bd9Sstevel@tonic-gate 	char *netid;
921*7c478bd9Sstevel@tonic-gate 	int argc;
922*7c478bd9Sstevel@tonic-gate 	char **argv;
923*7c478bd9Sstevel@tonic-gate {
924*7c478bd9Sstevel@tonic-gate 	rpcb_entry_list_ptr head = NULL;
925*7c478bd9Sstevel@tonic-gate 	struct timeval minutetimeout;
926*7c478bd9Sstevel@tonic-gate 	register CLIENT *client;
927*7c478bd9Sstevel@tonic-gate 	struct rpcent *rpc;
928*7c478bd9Sstevel@tonic-gate 	char *host;
929*7c478bd9Sstevel@tonic-gate 	RPCB parms;
930*7c478bd9Sstevel@tonic-gate 	struct netbuf *targaddr;
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	if (argc != 3) {
933*7c478bd9Sstevel@tonic-gate 		usage();
934*7c478bd9Sstevel@tonic-gate 		exit(1);
935*7c478bd9Sstevel@tonic-gate 	}
936*7c478bd9Sstevel@tonic-gate 	host = argv[0];
937*7c478bd9Sstevel@tonic-gate 	if (netid == NULL) {
938*7c478bd9Sstevel@tonic-gate 	    if (loopback_netid == NULL) {
939*7c478bd9Sstevel@tonic-gate 		client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr);
940*7c478bd9Sstevel@tonic-gate 	    } else {
941*7c478bd9Sstevel@tonic-gate 		client = getclnthandle(host, loopback_nconf, RPCBVERS4,
942*7c478bd9Sstevel@tonic-gate 			&targaddr);
943*7c478bd9Sstevel@tonic-gate 		if (client == NULL && rpc_createerr.cf_stat ==
944*7c478bd9Sstevel@tonic-gate 				RPC_N2AXLATEFAILURE) {
945*7c478bd9Sstevel@tonic-gate 		    client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr);
946*7c478bd9Sstevel@tonic-gate 		}
947*7c478bd9Sstevel@tonic-gate 	    }
948*7c478bd9Sstevel@tonic-gate 	} else {
949*7c478bd9Sstevel@tonic-gate 		struct netconfig *nconf;
950*7c478bd9Sstevel@tonic-gate 
951*7c478bd9Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
952*7c478bd9Sstevel@tonic-gate 		if (nconf == NULL) {
953*7c478bd9Sstevel@tonic-gate 			nc_perror("rpcinfo: invalid transport");
954*7c478bd9Sstevel@tonic-gate 			exit(1);
955*7c478bd9Sstevel@tonic-gate 		}
956*7c478bd9Sstevel@tonic-gate 		client = getclnthandle(host, nconf, RPCBVERS4, &targaddr);
957*7c478bd9Sstevel@tonic-gate 		if (nconf)
958*7c478bd9Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
959*7c478bd9Sstevel@tonic-gate 	}
960*7c478bd9Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
961*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact rpcbind");
962*7c478bd9Sstevel@tonic-gate 		exit(1);
963*7c478bd9Sstevel@tonic-gate 	}
964*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
965*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate 	parms.r_prog = 	getprognum(argv[1]);
968*7c478bd9Sstevel@tonic-gate 	parms.r_vers = 	getvers(argv[2]);
969*7c478bd9Sstevel@tonic-gate 	parms.r_netid = client->cl_netid;
970*7c478bd9Sstevel@tonic-gate 	if (targaddr == NULL) {
971*7c478bd9Sstevel@tonic-gate 		parms.r_addr = nullstring;	/* for XDRing */
972*7c478bd9Sstevel@tonic-gate 	} else {
973*7c478bd9Sstevel@tonic-gate 		/*
974*7c478bd9Sstevel@tonic-gate 		 * We also send the remote system the address we
975*7c478bd9Sstevel@tonic-gate 		 * used to contact it in case it can help it
976*7c478bd9Sstevel@tonic-gate 		 * connect back with us
977*7c478bd9Sstevel@tonic-gate 		 */
978*7c478bd9Sstevel@tonic-gate 		struct netconfig *nconf;
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 		nconf = getnetconfigent(client->cl_netid);
981*7c478bd9Sstevel@tonic-gate 		if (nconf != NULL) {
982*7c478bd9Sstevel@tonic-gate 			parms.r_addr = taddr2uaddr(nconf, targaddr);
983*7c478bd9Sstevel@tonic-gate 			if (parms.r_addr == NULL)
984*7c478bd9Sstevel@tonic-gate 				parms.r_addr = nullstring;
985*7c478bd9Sstevel@tonic-gate 			freenetconfigent(nconf);
986*7c478bd9Sstevel@tonic-gate 		} else {
987*7c478bd9Sstevel@tonic-gate 			parms.r_addr = nullstring;	/* for XDRing */
988*7c478bd9Sstevel@tonic-gate 		}
989*7c478bd9Sstevel@tonic-gate 		free(targaddr->buf);
990*7c478bd9Sstevel@tonic-gate 		free(targaddr);
991*7c478bd9Sstevel@tonic-gate 	}
992*7c478bd9Sstevel@tonic-gate 	parms.r_owner = nullstring;
993*7c478bd9Sstevel@tonic-gate 
994*7c478bd9Sstevel@tonic-gate 	if (CLNT_CALL(client, RPCBPROC_GETADDRLIST, (xdrproc_t)xdr_rpcb,
995*7c478bd9Sstevel@tonic-gate 		(char *)&parms, (xdrproc_t)xdr_rpcb_entry_list_ptr,
996*7c478bd9Sstevel@tonic-gate 		(char *)&head, minutetimeout) != RPC_SUCCESS) {
997*7c478bd9Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
998*7c478bd9Sstevel@tonic-gate 		exit(1);
999*7c478bd9Sstevel@tonic-gate 	}
1000*7c478bd9Sstevel@tonic-gate 	if (head == NULL) {
1001*7c478bd9Sstevel@tonic-gate 		printf("No remote programs registered.\n");
1002*7c478bd9Sstevel@tonic-gate 	} else {
1003*7c478bd9Sstevel@tonic-gate 		printf(
1004*7c478bd9Sstevel@tonic-gate 	"   program vers  tp_family/name/class    address\t\t  service\n");
1005*7c478bd9Sstevel@tonic-gate 		for (; head != NULL; head = head->rpcb_entry_next) {
1006*7c478bd9Sstevel@tonic-gate 			rpcb_entry *re;
1007*7c478bd9Sstevel@tonic-gate 			char buf[128];
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate 			re = &head->rpcb_entry_map;
1010*7c478bd9Sstevel@tonic-gate 			printf("%10ld%3ld    ",
1011*7c478bd9Sstevel@tonic-gate 				parms.r_prog, parms.r_vers);
1012*7c478bd9Sstevel@tonic-gate 			sprintf(buf, "%s/%s/%s ",
1013*7c478bd9Sstevel@tonic-gate 				re->r_nc_protofmly, re->r_nc_proto,
1014*7c478bd9Sstevel@tonic-gate 				re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
1015*7c478bd9Sstevel@tonic-gate 				re->r_nc_semantics == NC_TPI_COTS ? "cots" :
1016*7c478bd9Sstevel@tonic-gate 						"cots_ord");
1017*7c478bd9Sstevel@tonic-gate 			printf("%-24s", buf);
1018*7c478bd9Sstevel@tonic-gate 			printf("%-24s", re->r_maddr);
1019*7c478bd9Sstevel@tonic-gate 			rpc = getrpcbynumber(parms.r_prog);
1020*7c478bd9Sstevel@tonic-gate 			if (rpc)
1021*7c478bd9Sstevel@tonic-gate 				printf(" %-13s", rpc->r_name);
1022*7c478bd9Sstevel@tonic-gate 			else
1023*7c478bd9Sstevel@tonic-gate 				printf(" %-13s", "-");
1024*7c478bd9Sstevel@tonic-gate 			printf("\n");
1025*7c478bd9Sstevel@tonic-gate 		}
1026*7c478bd9Sstevel@tonic-gate 	}
1027*7c478bd9Sstevel@tonic-gate 	clnt_destroy(client);
1028*7c478bd9Sstevel@tonic-gate }
1029*7c478bd9Sstevel@tonic-gate 
1030*7c478bd9Sstevel@tonic-gate /*
1031*7c478bd9Sstevel@tonic-gate  * monitor rpcbind
1032*7c478bd9Sstevel@tonic-gate  */
1033*7c478bd9Sstevel@tonic-gate static void
1034*7c478bd9Sstevel@tonic-gate rpcbgetstat(argc, argv)
1035*7c478bd9Sstevel@tonic-gate 	int argc;
1036*7c478bd9Sstevel@tonic-gate 	char **argv;
1037*7c478bd9Sstevel@tonic-gate {
1038*7c478bd9Sstevel@tonic-gate 	rpcb_stat_byvers inf;
1039*7c478bd9Sstevel@tonic-gate 	struct timeval minutetimeout;
1040*7c478bd9Sstevel@tonic-gate 	register CLIENT *client;
1041*7c478bd9Sstevel@tonic-gate 	char *host;
1042*7c478bd9Sstevel@tonic-gate 	int i, j;
1043*7c478bd9Sstevel@tonic-gate 	rpcbs_addrlist *pa;
1044*7c478bd9Sstevel@tonic-gate 	rpcbs_rmtcalllist *pr;
1045*7c478bd9Sstevel@tonic-gate 	int cnt, flen;
1046*7c478bd9Sstevel@tonic-gate 	struct utsname utsname;
1047*7c478bd9Sstevel@tonic-gate #define	MAXFIELD	64
1048*7c478bd9Sstevel@tonic-gate 	char fieldbuf[MAXFIELD];
1049*7c478bd9Sstevel@tonic-gate #define	MAXLINE		256
1050*7c478bd9Sstevel@tonic-gate 	char linebuf[MAXLINE];
1051*7c478bd9Sstevel@tonic-gate 	char *cp, *bp, *lp;
1052*7c478bd9Sstevel@tonic-gate 	char *pmaphdr[] = {
1053*7c478bd9Sstevel@tonic-gate 		"NULL", "SET", "UNSET", "GETPORT",
1054*7c478bd9Sstevel@tonic-gate 		"DUMP", "CALLIT"
1055*7c478bd9Sstevel@tonic-gate 	};
1056*7c478bd9Sstevel@tonic-gate 	char *rpcb3hdr[] = {
1057*7c478bd9Sstevel@tonic-gate 		"NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
1058*7c478bd9Sstevel@tonic-gate 		"U2T", "T2U"
1059*7c478bd9Sstevel@tonic-gate 	};
1060*7c478bd9Sstevel@tonic-gate 	char *rpcb4hdr[] = {
1061*7c478bd9Sstevel@tonic-gate 		"NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
1062*7c478bd9Sstevel@tonic-gate 		"U2T",  "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
1063*7c478bd9Sstevel@tonic-gate 	};
1064*7c478bd9Sstevel@tonic-gate 
1065*7c478bd9Sstevel@tonic-gate #define	TABSTOP	8
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate 	if (argc >= 1) {
1068*7c478bd9Sstevel@tonic-gate 		host = argv[0];
1069*7c478bd9Sstevel@tonic-gate 	} else {
1070*7c478bd9Sstevel@tonic-gate 		uname(&utsname);
1071*7c478bd9Sstevel@tonic-gate 		host = utsname.nodename;
1072*7c478bd9Sstevel@tonic-gate 	}
1073*7c478bd9Sstevel@tonic-gate 	if (loopback_netid != NULL) {
1074*7c478bd9Sstevel@tonic-gate 		client = getclnthandle(host, loopback_nconf, RPCBVERS4, NULL);
1075*7c478bd9Sstevel@tonic-gate 		if (client == NULL && rpc_createerr.cf_stat ==
1076*7c478bd9Sstevel@tonic-gate 				RPC_N2AXLATEFAILURE) {
1077*7c478bd9Sstevel@tonic-gate 			client = clnt_rpcbind_create(host, RPCBVERS4, NULL);
1078*7c478bd9Sstevel@tonic-gate 		}
1079*7c478bd9Sstevel@tonic-gate 	} else {
1080*7c478bd9Sstevel@tonic-gate 		client = clnt_rpcbind_create(host, RPCBVERS4, NULL);
1081*7c478bd9Sstevel@tonic-gate 	}
1082*7c478bd9Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
1083*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo: can't contact rpcbind");
1084*7c478bd9Sstevel@tonic-gate 		exit(1);
1085*7c478bd9Sstevel@tonic-gate 	}
1086*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
1087*7c478bd9Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
1088*7c478bd9Sstevel@tonic-gate 	memset((char *)&inf, 0, sizeof (rpcb_stat_byvers));
1089*7c478bd9Sstevel@tonic-gate 	if (CLNT_CALL(client, RPCBPROC_GETSTAT, (xdrproc_t)xdr_void, NULL,
1090*7c478bd9Sstevel@tonic-gate 		(xdrproc_t)xdr_rpcb_stat_byvers, (char *)&inf, minutetimeout)
1091*7c478bd9Sstevel@tonic-gate 			!= RPC_SUCCESS) {
1092*7c478bd9Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
1093*7c478bd9Sstevel@tonic-gate 		exit(1);
1094*7c478bd9Sstevel@tonic-gate 	}
1095*7c478bd9Sstevel@tonic-gate 	printf("PORTMAP (version 2) statistics\n");
1096*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
1097*7c478bd9Sstevel@tonic-gate 	for (i = 0; i <= rpcb_highproc_2; i++) {
1098*7c478bd9Sstevel@tonic-gate 		fieldbuf[0] = '\0';
1099*7c478bd9Sstevel@tonic-gate 		switch (i) {
1100*7c478bd9Sstevel@tonic-gate 		case PMAPPROC_SET:
1101*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo);
1102*7c478bd9Sstevel@tonic-gate 			break;
1103*7c478bd9Sstevel@tonic-gate 		case PMAPPROC_UNSET:
1104*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/",
1105*7c478bd9Sstevel@tonic-gate 				inf[RPCBVERS_2_STAT].unsetinfo);
1106*7c478bd9Sstevel@tonic-gate 			break;
1107*7c478bd9Sstevel@tonic-gate 		case PMAPPROC_GETPORT:
1108*7c478bd9Sstevel@tonic-gate 			cnt = 0;
1109*7c478bd9Sstevel@tonic-gate 			for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa;
1110*7c478bd9Sstevel@tonic-gate 				pa = pa->next)
1111*7c478bd9Sstevel@tonic-gate 				cnt += pa->success;
1112*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/", cnt);
1113*7c478bd9Sstevel@tonic-gate 			break;
1114*7c478bd9Sstevel@tonic-gate 		case PMAPPROC_CALLIT:
1115*7c478bd9Sstevel@tonic-gate 			cnt = 0;
1116*7c478bd9Sstevel@tonic-gate 			for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr;
1117*7c478bd9Sstevel@tonic-gate 				pr = pr->next)
1118*7c478bd9Sstevel@tonic-gate 				cnt += pr->success;
1119*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/", cnt);
1120*7c478bd9Sstevel@tonic-gate 			break;
1121*7c478bd9Sstevel@tonic-gate 		default: break;  /* For the remaining ones */
1122*7c478bd9Sstevel@tonic-gate 		}
1123*7c478bd9Sstevel@tonic-gate 		cp = &fieldbuf[0] + strlen(fieldbuf);
1124*7c478bd9Sstevel@tonic-gate 		sprintf(cp, "%d", inf[RPCBVERS_2_STAT].info[i]);
1125*7c478bd9Sstevel@tonic-gate 		flen = strlen(fieldbuf);
1126*7c478bd9Sstevel@tonic-gate 		printf("%s%s", pmaphdr[i],
1127*7c478bd9Sstevel@tonic-gate 			spaces((TABSTOP * (1 + flen / TABSTOP))
1128*7c478bd9Sstevel@tonic-gate 			- strlen(pmaphdr[i])));
1129*7c478bd9Sstevel@tonic-gate 		sprintf(lp, "%s%s", fieldbuf,
1130*7c478bd9Sstevel@tonic-gate 			spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
1131*7c478bd9Sstevel@tonic-gate 			- flen)));
1132*7c478bd9Sstevel@tonic-gate 		lp += (flen + cnt);
1133*7c478bd9Sstevel@tonic-gate 	}
1134*7c478bd9Sstevel@tonic-gate 	printf("\n%s\n\n", linebuf);
1135*7c478bd9Sstevel@tonic-gate 
1136*7c478bd9Sstevel@tonic-gate 	if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT]) {
1137*7c478bd9Sstevel@tonic-gate 		printf("PMAP_RMTCALL call statistics\n");
1138*7c478bd9Sstevel@tonic-gate 		print_rmtcallstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
1139*7c478bd9Sstevel@tonic-gate 		printf("\n");
1140*7c478bd9Sstevel@tonic-gate 	}
1141*7c478bd9Sstevel@tonic-gate 
1142*7c478bd9Sstevel@tonic-gate 	if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT]) {
1143*7c478bd9Sstevel@tonic-gate 		printf("PMAP_GETPORT call statistics\n");
1144*7c478bd9Sstevel@tonic-gate 		print_getaddrstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
1145*7c478bd9Sstevel@tonic-gate 		printf("\n");
1146*7c478bd9Sstevel@tonic-gate 	}
1147*7c478bd9Sstevel@tonic-gate 
1148*7c478bd9Sstevel@tonic-gate 	printf("RPCBIND (version 3) statistics\n");
1149*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
1150*7c478bd9Sstevel@tonic-gate 	for (i = 0; i <= rpcb_highproc_3; i++) {
1151*7c478bd9Sstevel@tonic-gate 		fieldbuf[0] = '\0';
1152*7c478bd9Sstevel@tonic-gate 		switch (i) {
1153*7c478bd9Sstevel@tonic-gate 		case RPCBPROC_SET:
1154*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo);
1155*7c478bd9Sstevel@tonic-gate 			break;
1156*7c478bd9Sstevel@tonic-gate 		case RPCBPROC_UNSET:
1157*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/",
1158*7c478bd9Sstevel@tonic-gate 				inf[RPCBVERS_3_STAT].unsetinfo);
1159*7c478bd9Sstevel@tonic-gate 			break;
1160*7c478bd9Sstevel@tonic-gate 		case RPCBPROC_GETADDR:
1161*7c478bd9Sstevel@tonic-gate 			cnt = 0;
1162*7c478bd9Sstevel@tonic-gate 			for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa;
1163*7c478bd9Sstevel@tonic-gate 				pa = pa->next)
1164*7c478bd9Sstevel@tonic-gate 				cnt += pa->success;
1165*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/", cnt);
1166*7c478bd9Sstevel@tonic-gate 			break;
1167*7c478bd9Sstevel@tonic-gate 		case RPCBPROC_CALLIT:
1168*7c478bd9Sstevel@tonic-gate 			cnt = 0;
1169*7c478bd9Sstevel@tonic-gate 			for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr;
1170*7c478bd9Sstevel@tonic-gate 				pr = pr->next)
1171*7c478bd9Sstevel@tonic-gate 				cnt += pr->success;
1172*7c478bd9Sstevel@tonic-gate 			sprintf(fieldbuf, "%d/", cnt);
1173*7c478bd9Sstevel@tonic-gate 			break;
1174*7c478bd9Sstevel@tonic-gate 		default: break;  /* For the remaining ones */
1175*7c478bd9Sstevel@tonic-gate 		}
1176*7c478bd9Sstevel@tonic-gate 		cp = &fieldbuf[0] + strlen(fieldbuf);
1177*7c478bd9Sstevel@tonic-gate 		sprintf(cp, "%d", inf[RPCBVERS_3_STAT].info[i]);
1178*7c478bd9Sstevel@tonic-gate 		flen = strlen(fieldbuf);
1179*7c478bd9Sstevel@tonic-gate 		printf("%s%s", rpcb3hdr[i],
1180*7c478bd9Sstevel@tonic-gate 			spaces((TABSTOP * (1 + flen / TABSTOP))
1181*7c478bd9Sstevel@tonic-gate 			- strlen(rpcb3hdr[i])));
1182*7c478bd9Sstevel@tonic-gate 		sprintf(lp, "%s%s", fieldbuf,
1183*7c478bd9Sstevel@tonic-gate 			spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
1184*7c478bd9Sstevel@tonic-gate 			- flen)));
1185*7c478bd9Sstevel@tonic-gate 		lp += (flen + cnt);
1186*7c478bd9Sstevel@tonic-gate 	}
1187*7c478bd9Sstevel@tonic-gate 	printf("\n%s\n\n", linebuf);
1188*7c478bd9Sstevel@tonic-gate 
1189*7c478bd9Sstevel@tonic-gate 	if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT]) {
1190*7c478bd9Sstevel@tonic-gate 		printf("RPCB_RMTCALL (version 3) call statistics\n");
1191*7c478bd9Sstevel@tonic-gate 		print_rmtcallstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
1192*7c478bd9Sstevel@tonic-gate 		printf("\n");
1193*7c478bd9Sstevel@tonic-gate 	}
1194*7c478bd9Sstevel@tonic-gate 
1195*7c478bd9Sstevel@tonic-gate 	if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR]) {
1196*7c478bd9Sstevel@tonic-gate 		printf("RPCB_GETADDR (version 3) call statistics\n");
1197*7c478bd9Sstevel@tonic-gate 		print_getaddrstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
1198*7c478bd9Sstevel@tonic-gate 		printf("\n");
1199*7c478bd9Sstevel@tonic-gate 	}
1200*7c478bd9Sstevel@tonic-gate 
1201*7c478bd9Sstevel@tonic-gate 	printf("RPCBIND (version 4) statistics\n");
1202*7c478bd9Sstevel@tonic-gate 
1203*7c478bd9Sstevel@tonic-gate 	for (j = 0; j <= 9; j += 9) { /* Just two iterations for printing */
1204*7c478bd9Sstevel@tonic-gate 		lp = linebuf;
1205*7c478bd9Sstevel@tonic-gate 		for (i = j; i <= MAX(8, rpcb_highproc_4 - 9 + j); i++) {
1206*7c478bd9Sstevel@tonic-gate 			fieldbuf[0] = '\0';
1207*7c478bd9Sstevel@tonic-gate 			switch (i) {
1208*7c478bd9Sstevel@tonic-gate 			case RPCBPROC_SET:
1209*7c478bd9Sstevel@tonic-gate 				sprintf(fieldbuf, "%d/",
1210*7c478bd9Sstevel@tonic-gate 					inf[RPCBVERS_4_STAT].setinfo);
1211*7c478bd9Sstevel@tonic-gate 				break;
1212*7c478bd9Sstevel@tonic-gate 			case RPCBPROC_UNSET:
1213*7c478bd9Sstevel@tonic-gate 				sprintf(fieldbuf, "%d/",
1214*7c478bd9Sstevel@tonic-gate 					inf[RPCBVERS_4_STAT].unsetinfo);
1215*7c478bd9Sstevel@tonic-gate 				break;
1216*7c478bd9Sstevel@tonic-gate 			case RPCBPROC_GETADDR:
1217*7c478bd9Sstevel@tonic-gate 				cnt = 0;
1218*7c478bd9Sstevel@tonic-gate 				for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa;
1219*7c478bd9Sstevel@tonic-gate 					pa = pa->next)
1220*7c478bd9Sstevel@tonic-gate 					cnt += pa->success;
1221*7c478bd9Sstevel@tonic-gate 				sprintf(fieldbuf, "%d/", cnt);
1222*7c478bd9Sstevel@tonic-gate 				break;
1223*7c478bd9Sstevel@tonic-gate 			case RPCBPROC_CALLIT:
1224*7c478bd9Sstevel@tonic-gate 				cnt = 0;
1225*7c478bd9Sstevel@tonic-gate 				for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr;
1226*7c478bd9Sstevel@tonic-gate 					pr = pr->next)
1227*7c478bd9Sstevel@tonic-gate 					cnt += pr->success;
1228*7c478bd9Sstevel@tonic-gate 				sprintf(fieldbuf, "%d/", cnt);
1229*7c478bd9Sstevel@tonic-gate 				break;
1230*7c478bd9Sstevel@tonic-gate 			default: break;  /* For the remaining ones */
1231*7c478bd9Sstevel@tonic-gate 			}
1232*7c478bd9Sstevel@tonic-gate 			cp = &fieldbuf[0] + strlen(fieldbuf);
1233*7c478bd9Sstevel@tonic-gate 			/*
1234*7c478bd9Sstevel@tonic-gate 			 * XXX: We also add RPCBPROC_GETADDRLIST queries to
1235*7c478bd9Sstevel@tonic-gate 			 * RPCB_GETADDR because rpcbind includes the
1236*7c478bd9Sstevel@tonic-gate 			 * RPCB_GETADDRLIST successes in RPCB_GETADDR.
1237*7c478bd9Sstevel@tonic-gate 			 */
1238*7c478bd9Sstevel@tonic-gate 			if (i != RPCBPROC_GETADDR)
1239*7c478bd9Sstevel@tonic-gate 			    sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i]);
1240*7c478bd9Sstevel@tonic-gate 			else
1241*7c478bd9Sstevel@tonic-gate 			    sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i] +
1242*7c478bd9Sstevel@tonic-gate 			    inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]);
1243*7c478bd9Sstevel@tonic-gate 			flen = strlen(fieldbuf);
1244*7c478bd9Sstevel@tonic-gate 			printf("%s%s", rpcb4hdr[i],
1245*7c478bd9Sstevel@tonic-gate 				spaces((TABSTOP * (1 + flen / TABSTOP))
1246*7c478bd9Sstevel@tonic-gate 				- strlen(rpcb4hdr[i])));
1247*7c478bd9Sstevel@tonic-gate 			sprintf(lp, "%s%s", fieldbuf,
1248*7c478bd9Sstevel@tonic-gate 				spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
1249*7c478bd9Sstevel@tonic-gate 				- flen)));
1250*7c478bd9Sstevel@tonic-gate 			lp += (flen + cnt);
1251*7c478bd9Sstevel@tonic-gate 		}
1252*7c478bd9Sstevel@tonic-gate 		printf("\n%s\n", linebuf);
1253*7c478bd9Sstevel@tonic-gate 	}
1254*7c478bd9Sstevel@tonic-gate 
1255*7c478bd9Sstevel@tonic-gate 	if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] ||
1256*7c478bd9Sstevel@tonic-gate 			    inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT]) {
1257*7c478bd9Sstevel@tonic-gate 		printf("\n");
1258*7c478bd9Sstevel@tonic-gate 		printf("RPCB_RMTCALL (version 4) call statistics\n");
1259*7c478bd9Sstevel@tonic-gate 		print_rmtcallstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
1260*7c478bd9Sstevel@tonic-gate 	}
1261*7c478bd9Sstevel@tonic-gate 
1262*7c478bd9Sstevel@tonic-gate 	if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR]) {
1263*7c478bd9Sstevel@tonic-gate 		printf("\n");
1264*7c478bd9Sstevel@tonic-gate 		printf("RPCB_GETADDR (version 4) call statistics\n");
1265*7c478bd9Sstevel@tonic-gate 		print_getaddrstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
1266*7c478bd9Sstevel@tonic-gate 	}
1267*7c478bd9Sstevel@tonic-gate 	clnt_destroy(client);
1268*7c478bd9Sstevel@tonic-gate }
1269*7c478bd9Sstevel@tonic-gate 
1270*7c478bd9Sstevel@tonic-gate /*
1271*7c478bd9Sstevel@tonic-gate  * Delete registeration for this (prog, vers, netid)
1272*7c478bd9Sstevel@tonic-gate  */
1273*7c478bd9Sstevel@tonic-gate static void
1274*7c478bd9Sstevel@tonic-gate deletereg(netid, argc, argv)
1275*7c478bd9Sstevel@tonic-gate 	char *netid;
1276*7c478bd9Sstevel@tonic-gate 	int argc;
1277*7c478bd9Sstevel@tonic-gate 	char **argv;
1278*7c478bd9Sstevel@tonic-gate {
1279*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf = NULL;
1280*7c478bd9Sstevel@tonic-gate 
1281*7c478bd9Sstevel@tonic-gate 	if (argc != 2) {
1282*7c478bd9Sstevel@tonic-gate 		usage();
1283*7c478bd9Sstevel@tonic-gate 		exit(1);
1284*7c478bd9Sstevel@tonic-gate 	}
1285*7c478bd9Sstevel@tonic-gate 	if (netid) {
1286*7c478bd9Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
1287*7c478bd9Sstevel@tonic-gate 		if (nconf == NULL) {
1288*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rpcinfo: netid %s not supported\n",
1289*7c478bd9Sstevel@tonic-gate 					netid);
1290*7c478bd9Sstevel@tonic-gate 			exit(1);
1291*7c478bd9Sstevel@tonic-gate 		}
1292*7c478bd9Sstevel@tonic-gate 	}
1293*7c478bd9Sstevel@tonic-gate 	if ((rpcb_unset(getprognum(argv[0]), getvers(argv[1]), nconf)) == 0) {
1294*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1295*7c478bd9Sstevel@tonic-gate 	"rpcinfo: Could not delete registration for prog %s version %s\n",
1296*7c478bd9Sstevel@tonic-gate 			argv[0], argv[1]);
1297*7c478bd9Sstevel@tonic-gate 		exit(1);
1298*7c478bd9Sstevel@tonic-gate 	}
1299*7c478bd9Sstevel@tonic-gate }
1300*7c478bd9Sstevel@tonic-gate 
1301*7c478bd9Sstevel@tonic-gate /*
1302*7c478bd9Sstevel@tonic-gate  * Create and return a handle for the given nconf.
1303*7c478bd9Sstevel@tonic-gate  * Exit if cannot create handle.
1304*7c478bd9Sstevel@tonic-gate  */
1305*7c478bd9Sstevel@tonic-gate static CLIENT *
1306*7c478bd9Sstevel@tonic-gate clnt_addr_create(address, nconf, prog, vers)
1307*7c478bd9Sstevel@tonic-gate 	char *address;
1308*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1309*7c478bd9Sstevel@tonic-gate 	ulong_t prog;
1310*7c478bd9Sstevel@tonic-gate 	ulong_t vers;
1311*7c478bd9Sstevel@tonic-gate {
1312*7c478bd9Sstevel@tonic-gate 	CLIENT *client;
1313*7c478bd9Sstevel@tonic-gate 	static struct netbuf *nbuf;
1314*7c478bd9Sstevel@tonic-gate 	static int fd = RPC_ANYFD;
1315*7c478bd9Sstevel@tonic-gate 	struct t_info tinfo;
1316*7c478bd9Sstevel@tonic-gate 
1317*7c478bd9Sstevel@tonic-gate 	if (fd == RPC_ANYFD) {
1318*7c478bd9Sstevel@tonic-gate 		if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) {
1319*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_TLIERROR;
1320*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_error.re_terrno = t_errno;
1321*7c478bd9Sstevel@tonic-gate 			clnt_pcreateerror("rpcinfo");
1322*7c478bd9Sstevel@tonic-gate 			exit(1);
1323*7c478bd9Sstevel@tonic-gate 		}
1324*7c478bd9Sstevel@tonic-gate 		/* Convert the uaddr to taddr */
1325*7c478bd9Sstevel@tonic-gate 		nbuf = uaddr2taddr(nconf, address);
1326*7c478bd9Sstevel@tonic-gate 		if (nbuf == NULL) {
1327*7c478bd9Sstevel@tonic-gate 			netdir_perror("rpcinfo");
1328*7c478bd9Sstevel@tonic-gate 			exit(1);
1329*7c478bd9Sstevel@tonic-gate 		}
1330*7c478bd9Sstevel@tonic-gate 	}
1331*7c478bd9Sstevel@tonic-gate 	client = clnt_tli_create(fd, nconf, nbuf, prog, vers, 0, 0);
1332*7c478bd9Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
1333*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo");
1334*7c478bd9Sstevel@tonic-gate 		exit(1);
1335*7c478bd9Sstevel@tonic-gate 	}
1336*7c478bd9Sstevel@tonic-gate 	return (client);
1337*7c478bd9Sstevel@tonic-gate }
1338*7c478bd9Sstevel@tonic-gate 
1339*7c478bd9Sstevel@tonic-gate /*
1340*7c478bd9Sstevel@tonic-gate  * If the version number is given, ping that (prog, vers); else try to find
1341*7c478bd9Sstevel@tonic-gate  * the version numbers supported for that prog and ping all the versions.
1342*7c478bd9Sstevel@tonic-gate  * Remote rpcbind is not contacted for this service. The requests are
1343*7c478bd9Sstevel@tonic-gate  * sent directly to the services themselves.
1344*7c478bd9Sstevel@tonic-gate  */
1345*7c478bd9Sstevel@tonic-gate static void
1346*7c478bd9Sstevel@tonic-gate addrping(address, netid, argc, argv)
1347*7c478bd9Sstevel@tonic-gate 	char *address;
1348*7c478bd9Sstevel@tonic-gate 	char *netid;
1349*7c478bd9Sstevel@tonic-gate 	int argc;
1350*7c478bd9Sstevel@tonic-gate 	char **argv;
1351*7c478bd9Sstevel@tonic-gate {
1352*7c478bd9Sstevel@tonic-gate 	CLIENT *client;
1353*7c478bd9Sstevel@tonic-gate 	struct timeval to;
1354*7c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
1355*7c478bd9Sstevel@tonic-gate 	ulong_t prognum, versnum, minvers, maxvers;
1356*7c478bd9Sstevel@tonic-gate 	struct rpc_err rpcerr;
1357*7c478bd9Sstevel@tonic-gate 	int failure = 0;
1358*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1359*7c478bd9Sstevel@tonic-gate 	int fd;
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate 	if (argc < 1 || argc > 2 || (netid == NULL)) {
1362*7c478bd9Sstevel@tonic-gate 		usage();
1363*7c478bd9Sstevel@tonic-gate 		exit(1);
1364*7c478bd9Sstevel@tonic-gate 	}
1365*7c478bd9Sstevel@tonic-gate 	nconf = getnetconfigent(netid);
1366*7c478bd9Sstevel@tonic-gate 	if (nconf == (struct netconfig *)NULL) {
1367*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rpcinfo: Could not find %s\n", netid);
1368*7c478bd9Sstevel@tonic-gate 		exit(1);
1369*7c478bd9Sstevel@tonic-gate 	}
1370*7c478bd9Sstevel@tonic-gate 	to.tv_sec = 10;
1371*7c478bd9Sstevel@tonic-gate 	to.tv_usec = 0;
1372*7c478bd9Sstevel@tonic-gate 	prognum = getprognum(argv[0]);
1373*7c478bd9Sstevel@tonic-gate 	if (argc == 1) {	/* Version number not known */
1374*7c478bd9Sstevel@tonic-gate 		/*
1375*7c478bd9Sstevel@tonic-gate 		 * A call to version 0 should fail with a program/version
1376*7c478bd9Sstevel@tonic-gate 		 * mismatch, and give us the range of versions supported.
1377*7c478bd9Sstevel@tonic-gate 		 */
1378*7c478bd9Sstevel@tonic-gate 		versnum = MIN_VERS;
1379*7c478bd9Sstevel@tonic-gate 	} else {
1380*7c478bd9Sstevel@tonic-gate 		versnum = getvers(argv[1]);
1381*7c478bd9Sstevel@tonic-gate 	}
1382*7c478bd9Sstevel@tonic-gate 	client = clnt_addr_create(address, nconf, prognum, versnum);
1383*7c478bd9Sstevel@tonic-gate 	rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
1384*7c478bd9Sstevel@tonic-gate 			(char *)NULL, (xdrproc_t)xdr_void,
1385*7c478bd9Sstevel@tonic-gate 			(char *)NULL, to);
1386*7c478bd9Sstevel@tonic-gate 	if (argc == 2) {
1387*7c478bd9Sstevel@tonic-gate 		/* Version number was known */
1388*7c478bd9Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
1389*7c478bd9Sstevel@tonic-gate 			failure = 1;
1390*7c478bd9Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
1391*7c478bd9Sstevel@tonic-gate 		if (failure)
1392*7c478bd9Sstevel@tonic-gate 			exit(1);
1393*7c478bd9Sstevel@tonic-gate 		return;
1394*7c478bd9Sstevel@tonic-gate 	}
1395*7c478bd9Sstevel@tonic-gate 	/* Version number not known */
1396*7c478bd9Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
1397*7c478bd9Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLGET_FD, (char *)&fd);
1398*7c478bd9Sstevel@tonic-gate 	if (rpc_stat == RPC_PROGVERSMISMATCH) {
1399*7c478bd9Sstevel@tonic-gate 		clnt_geterr(client, &rpcerr);
1400*7c478bd9Sstevel@tonic-gate 		minvers = rpcerr.re_vers.low;
1401*7c478bd9Sstevel@tonic-gate 		maxvers = rpcerr.re_vers.high;
1402*7c478bd9Sstevel@tonic-gate 	} else if (rpc_stat == RPC_SUCCESS) {
1403*7c478bd9Sstevel@tonic-gate 		/*
1404*7c478bd9Sstevel@tonic-gate 		 * Oh dear, it DOES support version 0.
1405*7c478bd9Sstevel@tonic-gate 		 * Let's try version MAX_VERS.
1406*7c478bd9Sstevel@tonic-gate 		 */
1407*7c478bd9Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
1408*7c478bd9Sstevel@tonic-gate 		client = clnt_addr_create(address, nconf, prognum, MAX_VERS);
1409*7c478bd9Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
1410*7c478bd9Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
1411*7c478bd9Sstevel@tonic-gate 				(char *)NULL, to);
1412*7c478bd9Sstevel@tonic-gate 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
1413*7c478bd9Sstevel@tonic-gate 			clnt_geterr(client, &rpcerr);
1414*7c478bd9Sstevel@tonic-gate 			minvers = rpcerr.re_vers.low;
1415*7c478bd9Sstevel@tonic-gate 			maxvers = rpcerr.re_vers.high;
1416*7c478bd9Sstevel@tonic-gate 		} else if (rpc_stat == RPC_SUCCESS) {
1417*7c478bd9Sstevel@tonic-gate 			/*
1418*7c478bd9Sstevel@tonic-gate 			 * It also supports version MAX_VERS.
1419*7c478bd9Sstevel@tonic-gate 			 * Looks like we have a wise guy.
1420*7c478bd9Sstevel@tonic-gate 			 * OK, we give them information on all
1421*7c478bd9Sstevel@tonic-gate 			 * 4 billion versions they support...
1422*7c478bd9Sstevel@tonic-gate 			 */
1423*7c478bd9Sstevel@tonic-gate 			minvers = 0;
1424*7c478bd9Sstevel@tonic-gate 			maxvers = MAX_VERS;
1425*7c478bd9Sstevel@tonic-gate 		} else {
1426*7c478bd9Sstevel@tonic-gate 			(void) pstatus(client, prognum, MAX_VERS);
1427*7c478bd9Sstevel@tonic-gate 			exit(1);
1428*7c478bd9Sstevel@tonic-gate 		}
1429*7c478bd9Sstevel@tonic-gate 	} else {
1430*7c478bd9Sstevel@tonic-gate 		(void) pstatus(client, prognum, (ulong_t)0);
1431*7c478bd9Sstevel@tonic-gate 		exit(1);
1432*7c478bd9Sstevel@tonic-gate 	}
1433*7c478bd9Sstevel@tonic-gate 	(void) CLNT_DESTROY(client);
1434*7c478bd9Sstevel@tonic-gate 	for (versnum = minvers; versnum <= maxvers; versnum++) {
1435*7c478bd9Sstevel@tonic-gate 		client = clnt_addr_create(address, nconf, prognum, versnum);
1436*7c478bd9Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
1437*7c478bd9Sstevel@tonic-gate 				(char *)NULL, (xdrproc_t)xdr_void,
1438*7c478bd9Sstevel@tonic-gate 				(char *)NULL, to);
1439*7c478bd9Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
1440*7c478bd9Sstevel@tonic-gate 				failure = 1;
1441*7c478bd9Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
1442*7c478bd9Sstevel@tonic-gate 	}
1443*7c478bd9Sstevel@tonic-gate 	(void) t_close(fd);
1444*7c478bd9Sstevel@tonic-gate 	if (failure)
1445*7c478bd9Sstevel@tonic-gate 		exit(1);
1446*7c478bd9Sstevel@tonic-gate }
1447*7c478bd9Sstevel@tonic-gate 
1448*7c478bd9Sstevel@tonic-gate /*
1449*7c478bd9Sstevel@tonic-gate  * If the version number is given, ping that (prog, vers); else try to find
1450*7c478bd9Sstevel@tonic-gate  * the version numbers supported for that prog and ping all the versions.
1451*7c478bd9Sstevel@tonic-gate  * Remote rpcbind is *contacted* for this service. The requests are
1452*7c478bd9Sstevel@tonic-gate  * then sent directly to the services themselves.
1453*7c478bd9Sstevel@tonic-gate  */
1454*7c478bd9Sstevel@tonic-gate static void
1455*7c478bd9Sstevel@tonic-gate progping(netid, argc, argv)
1456*7c478bd9Sstevel@tonic-gate 	char *netid;
1457*7c478bd9Sstevel@tonic-gate 	int argc;
1458*7c478bd9Sstevel@tonic-gate 	char **argv;
1459*7c478bd9Sstevel@tonic-gate {
1460*7c478bd9Sstevel@tonic-gate 	CLIENT *client;
1461*7c478bd9Sstevel@tonic-gate 	struct timeval to;
1462*7c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
1463*7c478bd9Sstevel@tonic-gate 	ulong_t prognum, versnum, minvers, maxvers;
1464*7c478bd9Sstevel@tonic-gate 	struct rpc_err rpcerr;
1465*7c478bd9Sstevel@tonic-gate 	int failure = 0;
1466*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1467*7c478bd9Sstevel@tonic-gate 	int fd;
1468*7c478bd9Sstevel@tonic-gate 
1469*7c478bd9Sstevel@tonic-gate 	if (argc < 2 || argc > 3 || (netid == NULL)) {
1470*7c478bd9Sstevel@tonic-gate 		usage();
1471*7c478bd9Sstevel@tonic-gate 		exit(1);
1472*7c478bd9Sstevel@tonic-gate 	}
1473*7c478bd9Sstevel@tonic-gate 	prognum = getprognum(argv[1]);
1474*7c478bd9Sstevel@tonic-gate 	if (argc == 2) { /* Version number not known */
1475*7c478bd9Sstevel@tonic-gate 		/*
1476*7c478bd9Sstevel@tonic-gate 		 * A call to version 0 should fail with a program/version
1477*7c478bd9Sstevel@tonic-gate 		 * mismatch, and give us the range of versions supported.
1478*7c478bd9Sstevel@tonic-gate 		 */
1479*7c478bd9Sstevel@tonic-gate 		versnum = MIN_VERS;
1480*7c478bd9Sstevel@tonic-gate 	} else {
1481*7c478bd9Sstevel@tonic-gate 		versnum = getvers(argv[2]);
1482*7c478bd9Sstevel@tonic-gate 	}
1483*7c478bd9Sstevel@tonic-gate 	if (netid) {
1484*7c478bd9Sstevel@tonic-gate 		nconf = getnetconfigent(netid);
1485*7c478bd9Sstevel@tonic-gate 		if (nconf == (struct netconfig *)NULL) {
1486*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rpcinfo: Could not find %s\n", netid);
1487*7c478bd9Sstevel@tonic-gate 			exit(1);
1488*7c478bd9Sstevel@tonic-gate 		}
1489*7c478bd9Sstevel@tonic-gate 		client = clnt_tp_create(argv[0], prognum, versnum, nconf);
1490*7c478bd9Sstevel@tonic-gate 	} else {
1491*7c478bd9Sstevel@tonic-gate 		client = clnt_create(argv[0], prognum, versnum, "NETPATH");
1492*7c478bd9Sstevel@tonic-gate 	}
1493*7c478bd9Sstevel@tonic-gate 	if (client == (CLIENT *)NULL) {
1494*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("rpcinfo");
1495*7c478bd9Sstevel@tonic-gate 		exit(1);
1496*7c478bd9Sstevel@tonic-gate 	}
1497*7c478bd9Sstevel@tonic-gate 	to.tv_sec = 10;
1498*7c478bd9Sstevel@tonic-gate 	to.tv_usec = 0;
1499*7c478bd9Sstevel@tonic-gate 	rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
1500*7c478bd9Sstevel@tonic-gate 			(char *)NULL, (xdrproc_t)xdr_void,
1501*7c478bd9Sstevel@tonic-gate 			(char *)NULL, to);
1502*7c478bd9Sstevel@tonic-gate 	if (argc == 3) {
1503*7c478bd9Sstevel@tonic-gate 		/* Version number was known */
1504*7c478bd9Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
1505*7c478bd9Sstevel@tonic-gate 			failure = 1;
1506*7c478bd9Sstevel@tonic-gate 		(void) CLNT_DESTROY(client);
1507*7c478bd9Sstevel@tonic-gate 		if (failure)
1508*7c478bd9Sstevel@tonic-gate 			exit(1);
1509*7c478bd9Sstevel@tonic-gate 		return;
1510*7c478bd9Sstevel@tonic-gate 	}
1511*7c478bd9Sstevel@tonic-gate 	/* Version number not known */
1512*7c478bd9Sstevel@tonic-gate 	if (rpc_stat == RPC_PROGVERSMISMATCH) {
1513*7c478bd9Sstevel@tonic-gate 		clnt_geterr(client, &rpcerr);
1514*7c478bd9Sstevel@tonic-gate 		minvers = rpcerr.re_vers.low;
1515*7c478bd9Sstevel@tonic-gate 		maxvers = rpcerr.re_vers.high;
1516*7c478bd9Sstevel@tonic-gate 	} else if (rpc_stat == RPC_SUCCESS) {
1517*7c478bd9Sstevel@tonic-gate 		/*
1518*7c478bd9Sstevel@tonic-gate 		 * Oh dear, it DOES support version 0.
1519*7c478bd9Sstevel@tonic-gate 		 * Let's try version MAX_VERS.
1520*7c478bd9Sstevel@tonic-gate 		 */
1521*7c478bd9Sstevel@tonic-gate 		versnum = MAX_VERS;
1522*7c478bd9Sstevel@tonic-gate 		(void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
1523*7c478bd9Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC,
1524*7c478bd9Sstevel@tonic-gate 				(xdrproc_t)xdr_void, (char *)NULL,
1525*7c478bd9Sstevel@tonic-gate 				(xdrproc_t)xdr_void, (char *)NULL, to);
1526*7c478bd9Sstevel@tonic-gate 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
1527*7c478bd9Sstevel@tonic-gate 			clnt_geterr(client, &rpcerr);
1528*7c478bd9Sstevel@tonic-gate 			minvers = rpcerr.re_vers.low;
1529*7c478bd9Sstevel@tonic-gate 			maxvers = rpcerr.re_vers.high;
1530*7c478bd9Sstevel@tonic-gate 		} else if (rpc_stat == RPC_SUCCESS) {
1531*7c478bd9Sstevel@tonic-gate 			/*
1532*7c478bd9Sstevel@tonic-gate 			 * It also supports version MAX_VERS.
1533*7c478bd9Sstevel@tonic-gate 			 * Looks like we have a wise guy.
1534*7c478bd9Sstevel@tonic-gate 			 * OK, we give them information on all
1535*7c478bd9Sstevel@tonic-gate 			 * 4 billion versions they support...
1536*7c478bd9Sstevel@tonic-gate 			 */
1537*7c478bd9Sstevel@tonic-gate 			minvers = 0;
1538*7c478bd9Sstevel@tonic-gate 			maxvers = MAX_VERS;
1539*7c478bd9Sstevel@tonic-gate 		} else {
1540*7c478bd9Sstevel@tonic-gate 			(void) pstatus(client, prognum, MAX_VERS);
1541*7c478bd9Sstevel@tonic-gate 			exit(1);
1542*7c478bd9Sstevel@tonic-gate 		}
1543*7c478bd9Sstevel@tonic-gate 	} else {
1544*7c478bd9Sstevel@tonic-gate 		(void) pstatus(client, prognum, (ulong_t)0);
1545*7c478bd9Sstevel@tonic-gate 		exit(1);
1546*7c478bd9Sstevel@tonic-gate 	}
1547*7c478bd9Sstevel@tonic-gate 	for (versnum = minvers; versnum <= maxvers; versnum++) {
1548*7c478bd9Sstevel@tonic-gate 		(void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
1549*7c478bd9Sstevel@tonic-gate 		rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t)xdr_void,
1550*7c478bd9Sstevel@tonic-gate 					(char *)NULL, (xdrproc_t)xdr_void,
1551*7c478bd9Sstevel@tonic-gate 					(char *)NULL, to);
1552*7c478bd9Sstevel@tonic-gate 		if (pstatus(client, prognum, versnum) < 0)
1553*7c478bd9Sstevel@tonic-gate 				failure = 1;
1554*7c478bd9Sstevel@tonic-gate 	}
1555*7c478bd9Sstevel@tonic-gate 	(void) CLNT_DESTROY(client);
1556*7c478bd9Sstevel@tonic-gate 	if (failure)
1557*7c478bd9Sstevel@tonic-gate 		exit(1);
1558*7c478bd9Sstevel@tonic-gate }
1559*7c478bd9Sstevel@tonic-gate 
1560*7c478bd9Sstevel@tonic-gate static void
1561*7c478bd9Sstevel@tonic-gate usage()
1562*7c478bd9Sstevel@tonic-gate {
1563*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "Usage: rpcinfo [-m | -s] [host]\n");
1564*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
1565*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "       rpcinfo -p [host]\n");
1566*7c478bd9Sstevel@tonic-gate #endif
1567*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "       rpcinfo -T netid host prognum [versnum]\n");
1568*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "       rpcinfo -l host prognum versnum\n");
1569*7c478bd9Sstevel@tonic-gate #ifdef PORTMAP
1570*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1571*7c478bd9Sstevel@tonic-gate "       rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
1572*7c478bd9Sstevel@tonic-gate #endif
1573*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1574*7c478bd9Sstevel@tonic-gate "       rpcinfo -a serv_address -T netid prognum [version]\n");
1575*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "       rpcinfo -b prognum versnum\n");
1576*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "       rpcinfo -d [-T netid] prognum versnum\n");
1577*7c478bd9Sstevel@tonic-gate }
1578*7c478bd9Sstevel@tonic-gate 
1579*7c478bd9Sstevel@tonic-gate static ulong_t
1580*7c478bd9Sstevel@tonic-gate getprognum  (arg)
1581*7c478bd9Sstevel@tonic-gate 	char *arg;
1582*7c478bd9Sstevel@tonic-gate {
1583*7c478bd9Sstevel@tonic-gate 	char *strptr;
1584*7c478bd9Sstevel@tonic-gate 	register struct rpcent *rpc;
1585*7c478bd9Sstevel@tonic-gate 	register ulong_t prognum;
1586*7c478bd9Sstevel@tonic-gate 	char *tptr = arg;
1587*7c478bd9Sstevel@tonic-gate 
1588*7c478bd9Sstevel@tonic-gate 	while (*tptr && isdigit(*tptr++));
1589*7c478bd9Sstevel@tonic-gate 	if (*tptr || isalpha(*(tptr - 1))) {
1590*7c478bd9Sstevel@tonic-gate 		rpc = getrpcbyname(arg);
1591*7c478bd9Sstevel@tonic-gate 		if (rpc == NULL) {
1592*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rpcinfo: %s is unknown service\n",
1593*7c478bd9Sstevel@tonic-gate 				arg);
1594*7c478bd9Sstevel@tonic-gate 			exit(1);
1595*7c478bd9Sstevel@tonic-gate 		}
1596*7c478bd9Sstevel@tonic-gate 		prognum = rpc->r_number;
1597*7c478bd9Sstevel@tonic-gate 	} else {
1598*7c478bd9Sstevel@tonic-gate 		prognum = strtol(arg, &strptr, 10);
1599*7c478bd9Sstevel@tonic-gate 		if (strptr == arg || *strptr != '\0') {
1600*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1601*7c478bd9Sstevel@tonic-gate 		"rpcinfo: %s is illegal program number\n", arg);
1602*7c478bd9Sstevel@tonic-gate 			exit(1);
1603*7c478bd9Sstevel@tonic-gate 		}
1604*7c478bd9Sstevel@tonic-gate 	}
1605*7c478bd9Sstevel@tonic-gate 	return (prognum);
1606*7c478bd9Sstevel@tonic-gate }
1607*7c478bd9Sstevel@tonic-gate 
1608*7c478bd9Sstevel@tonic-gate static ulong_t
1609*7c478bd9Sstevel@tonic-gate getvers(arg)
1610*7c478bd9Sstevel@tonic-gate 	char *arg;
1611*7c478bd9Sstevel@tonic-gate {
1612*7c478bd9Sstevel@tonic-gate 	char *strptr;
1613*7c478bd9Sstevel@tonic-gate 	register ulong_t vers;
1614*7c478bd9Sstevel@tonic-gate 
1615*7c478bd9Sstevel@tonic-gate 	vers = (int)strtol(arg, &strptr, 10);
1616*7c478bd9Sstevel@tonic-gate 	if (strptr == arg || *strptr != '\0') {
1617*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rpcinfo: %s is illegal version number\n",
1618*7c478bd9Sstevel@tonic-gate 			arg);
1619*7c478bd9Sstevel@tonic-gate 		exit(1);
1620*7c478bd9Sstevel@tonic-gate 	}
1621*7c478bd9Sstevel@tonic-gate 	return (vers);
1622*7c478bd9Sstevel@tonic-gate }
1623*7c478bd9Sstevel@tonic-gate 
1624*7c478bd9Sstevel@tonic-gate /*
1625*7c478bd9Sstevel@tonic-gate  * This routine should take a pointer to an "rpc_err" structure, rather than
1626*7c478bd9Sstevel@tonic-gate  * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
1627*7c478bd9Sstevel@tonic-gate  * a CLIENT structure rather than a pointer to an "rpc_err" structure.
1628*7c478bd9Sstevel@tonic-gate  * As such, we have to keep the CLIENT structure around in order to print
1629*7c478bd9Sstevel@tonic-gate  * a good error message.
1630*7c478bd9Sstevel@tonic-gate  */
1631*7c478bd9Sstevel@tonic-gate static int
1632*7c478bd9Sstevel@tonic-gate pstatus(client, prog, vers)
1633*7c478bd9Sstevel@tonic-gate 	register CLIENT *client;
1634*7c478bd9Sstevel@tonic-gate 	ulong_t prog;
1635*7c478bd9Sstevel@tonic-gate 	ulong_t vers;
1636*7c478bd9Sstevel@tonic-gate {
1637*7c478bd9Sstevel@tonic-gate 	struct rpc_err rpcerr;
1638*7c478bd9Sstevel@tonic-gate 
1639*7c478bd9Sstevel@tonic-gate 	clnt_geterr(client, &rpcerr);
1640*7c478bd9Sstevel@tonic-gate 	if (rpcerr.re_status != RPC_SUCCESS) {
1641*7c478bd9Sstevel@tonic-gate 		clnt_perror(client, "rpcinfo");
1642*7c478bd9Sstevel@tonic-gate 		printf("program %lu version %lu is not available\n",
1643*7c478bd9Sstevel@tonic-gate 			prog, vers);
1644*7c478bd9Sstevel@tonic-gate 		return (-1);
1645*7c478bd9Sstevel@tonic-gate 	} else {
1646*7c478bd9Sstevel@tonic-gate 		printf("program %lu version %lu ready and waiting\n",
1647*7c478bd9Sstevel@tonic-gate 			prog, vers);
1648*7c478bd9Sstevel@tonic-gate 		return (0);
1649*7c478bd9Sstevel@tonic-gate 	}
1650*7c478bd9Sstevel@tonic-gate }
1651*7c478bd9Sstevel@tonic-gate 
1652*7c478bd9Sstevel@tonic-gate static CLIENT *
1653*7c478bd9Sstevel@tonic-gate clnt_rpcbind_create(host, rpcbversnum, targaddr)
1654*7c478bd9Sstevel@tonic-gate 	char *host;
1655*7c478bd9Sstevel@tonic-gate 	ulong_t rpcbversnum;
1656*7c478bd9Sstevel@tonic-gate 	struct netbuf **targaddr;
1657*7c478bd9Sstevel@tonic-gate {
1658*7c478bd9Sstevel@tonic-gate 	static char *tlist[3] = {
1659*7c478bd9Sstevel@tonic-gate 		"circuit_n", "circuit_v", "datagram_v"
1660*7c478bd9Sstevel@tonic-gate 	};
1661*7c478bd9Sstevel@tonic-gate 	int i;
1662*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1663*7c478bd9Sstevel@tonic-gate 	CLIENT *clnt = NULL;
1664*7c478bd9Sstevel@tonic-gate 	void *handle;
1665*7c478bd9Sstevel@tonic-gate 
1666*7c478bd9Sstevel@tonic-gate 	rpc_createerr.cf_stat = RPC_SUCCESS;
1667*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 3; i++) {
1668*7c478bd9Sstevel@tonic-gate 		if ((handle = __rpc_setconf(tlist[i])) == NULL)
1669*7c478bd9Sstevel@tonic-gate 			continue;
1670*7c478bd9Sstevel@tonic-gate 		while (clnt == (CLIENT *)NULL) {
1671*7c478bd9Sstevel@tonic-gate 			if ((nconf = __rpc_getconf(handle)) == NULL) {
1672*7c478bd9Sstevel@tonic-gate 				if (rpc_createerr.cf_stat == RPC_SUCCESS)
1673*7c478bd9Sstevel@tonic-gate 				    rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1674*7c478bd9Sstevel@tonic-gate 				break;
1675*7c478bd9Sstevel@tonic-gate 			}
1676*7c478bd9Sstevel@tonic-gate 			clnt = getclnthandle(host, nconf, rpcbversnum,
1677*7c478bd9Sstevel@tonic-gate 					targaddr);
1678*7c478bd9Sstevel@tonic-gate 		}
1679*7c478bd9Sstevel@tonic-gate 		if (clnt)
1680*7c478bd9Sstevel@tonic-gate 			break;
1681*7c478bd9Sstevel@tonic-gate 		__rpc_endconf(handle);
1682*7c478bd9Sstevel@tonic-gate 	}
1683*7c478bd9Sstevel@tonic-gate 	return (clnt);
1684*7c478bd9Sstevel@tonic-gate }
1685*7c478bd9Sstevel@tonic-gate 
1686*7c478bd9Sstevel@tonic-gate static CLIENT*
1687*7c478bd9Sstevel@tonic-gate getclnthandle(host, nconf, rpcbversnum, targaddr)
1688*7c478bd9Sstevel@tonic-gate 	char *host;
1689*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1690*7c478bd9Sstevel@tonic-gate 	ulong_t rpcbversnum;
1691*7c478bd9Sstevel@tonic-gate 	struct netbuf **targaddr;
1692*7c478bd9Sstevel@tonic-gate {
1693*7c478bd9Sstevel@tonic-gate 	struct netbuf *addr;
1694*7c478bd9Sstevel@tonic-gate 	struct nd_addrlist *nas;
1695*7c478bd9Sstevel@tonic-gate 	struct nd_hostserv rpcbind_hs;
1696*7c478bd9Sstevel@tonic-gate 	CLIENT *client = NULL;
1697*7c478bd9Sstevel@tonic-gate 
1698*7c478bd9Sstevel@tonic-gate 	/* Get the address of the rpcbind */
1699*7c478bd9Sstevel@tonic-gate 	rpcbind_hs.h_host = host;
1700*7c478bd9Sstevel@tonic-gate 	rpcbind_hs.h_serv = "rpcbind";
1701*7c478bd9Sstevel@tonic-gate 	if (netdir_getbyname(nconf, &rpcbind_hs, &nas)) {
1702*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
1703*7c478bd9Sstevel@tonic-gate 		return (NULL);
1704*7c478bd9Sstevel@tonic-gate 	}
1705*7c478bd9Sstevel@tonic-gate 	addr = nas->n_addrs;
1706*7c478bd9Sstevel@tonic-gate 	client = clnt_tli_create(RPC_ANYFD, nconf, addr, RPCBPROG,
1707*7c478bd9Sstevel@tonic-gate 			rpcbversnum, 0, 0);
1708*7c478bd9Sstevel@tonic-gate 	if (client) {
1709*7c478bd9Sstevel@tonic-gate 		if (targaddr != NULL) {
1710*7c478bd9Sstevel@tonic-gate 			*targaddr =
1711*7c478bd9Sstevel@tonic-gate 			    (struct netbuf *)malloc(sizeof (struct netbuf));
1712*7c478bd9Sstevel@tonic-gate 			if (*targaddr != NULL) {
1713*7c478bd9Sstevel@tonic-gate 				(*targaddr)->maxlen = addr->maxlen;
1714*7c478bd9Sstevel@tonic-gate 				(*targaddr)->len = addr->len;
1715*7c478bd9Sstevel@tonic-gate 				(*targaddr)->buf = (char *)malloc(addr->len);
1716*7c478bd9Sstevel@tonic-gate 				if ((*targaddr)->buf != NULL) {
1717*7c478bd9Sstevel@tonic-gate 					memcpy((*targaddr)->buf, addr->buf,
1718*7c478bd9Sstevel@tonic-gate 						addr->len);
1719*7c478bd9Sstevel@tonic-gate 				}
1720*7c478bd9Sstevel@tonic-gate 			}
1721*7c478bd9Sstevel@tonic-gate 		}
1722*7c478bd9Sstevel@tonic-gate 	} else {
1723*7c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_TLIERROR) {
1724*7c478bd9Sstevel@tonic-gate 			/*
1725*7c478bd9Sstevel@tonic-gate 			 * Assume that the other system is dead; this is a
1726*7c478bd9Sstevel@tonic-gate 			 * better error to display to the user.
1727*7c478bd9Sstevel@tonic-gate 			 */
1728*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1729*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_error.re_status = RPC_FAILED;
1730*7c478bd9Sstevel@tonic-gate 		}
1731*7c478bd9Sstevel@tonic-gate 	}
1732*7c478bd9Sstevel@tonic-gate 	netdir_free((char *)nas, ND_ADDRLIST);
1733*7c478bd9Sstevel@tonic-gate 	return (client);
1734*7c478bd9Sstevel@tonic-gate }
1735*7c478bd9Sstevel@tonic-gate 
1736*7c478bd9Sstevel@tonic-gate static void
1737*7c478bd9Sstevel@tonic-gate print_rmtcallstat(rtype, infp)
1738*7c478bd9Sstevel@tonic-gate 	int rtype;
1739*7c478bd9Sstevel@tonic-gate 	rpcb_stat *infp;
1740*7c478bd9Sstevel@tonic-gate {
1741*7c478bd9Sstevel@tonic-gate 	register rpcbs_rmtcalllist_ptr pr;
1742*7c478bd9Sstevel@tonic-gate 	struct rpcent *rpc;
1743*7c478bd9Sstevel@tonic-gate 
1744*7c478bd9Sstevel@tonic-gate 	if (rtype == RPCBVERS_4_STAT)
1745*7c478bd9Sstevel@tonic-gate 		printf(
1746*7c478bd9Sstevel@tonic-gate 		"prog\t\tvers\tproc\tnetid\tindirect success failure\n");
1747*7c478bd9Sstevel@tonic-gate 	else
1748*7c478bd9Sstevel@tonic-gate 		printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
1749*7c478bd9Sstevel@tonic-gate 	for (pr = infp->rmtinfo; pr; pr = pr->next) {
1750*7c478bd9Sstevel@tonic-gate 		rpc = getrpcbynumber(pr->prog);
1751*7c478bd9Sstevel@tonic-gate 		if (rpc)
1752*7c478bd9Sstevel@tonic-gate 			printf("%-16s", rpc->r_name);
1753*7c478bd9Sstevel@tonic-gate 		else
1754*7c478bd9Sstevel@tonic-gate 			printf("%-16d", pr->prog);
1755*7c478bd9Sstevel@tonic-gate 		printf("%d\t%d\t%-7s ",
1756*7c478bd9Sstevel@tonic-gate 			pr->vers, pr->proc, pr->netid);
1757*7c478bd9Sstevel@tonic-gate 		if (rtype == RPCBVERS_4_STAT)
1758*7c478bd9Sstevel@tonic-gate 			printf("%d\t ", pr->indirect);
1759*7c478bd9Sstevel@tonic-gate 		printf("%d\t%d\n", pr->success, pr->failure);
1760*7c478bd9Sstevel@tonic-gate 	}
1761*7c478bd9Sstevel@tonic-gate }
1762*7c478bd9Sstevel@tonic-gate 
1763*7c478bd9Sstevel@tonic-gate static void
1764*7c478bd9Sstevel@tonic-gate print_getaddrstat(rtype, infp)
1765*7c478bd9Sstevel@tonic-gate 	int rtype;
1766*7c478bd9Sstevel@tonic-gate 	rpcb_stat *infp;
1767*7c478bd9Sstevel@tonic-gate {
1768*7c478bd9Sstevel@tonic-gate 	rpcbs_addrlist_ptr al;
1769*7c478bd9Sstevel@tonic-gate 	register struct rpcent *rpc;
1770*7c478bd9Sstevel@tonic-gate 
1771*7c478bd9Sstevel@tonic-gate 	printf("prog\t\tvers\tnetid\t  success\tfailure\n");
1772*7c478bd9Sstevel@tonic-gate 	for (al = infp->addrinfo; al; al = al->next) {
1773*7c478bd9Sstevel@tonic-gate 		rpc = getrpcbynumber(al->prog);
1774*7c478bd9Sstevel@tonic-gate 		if (rpc)
1775*7c478bd9Sstevel@tonic-gate 			printf("%-16s", rpc->r_name);
1776*7c478bd9Sstevel@tonic-gate 		else
1777*7c478bd9Sstevel@tonic-gate 			printf("%-16d", al->prog);
1778*7c478bd9Sstevel@tonic-gate 		printf("%d\t%-9s %-12d\t%d\n",
1779*7c478bd9Sstevel@tonic-gate 			al->vers, al->netid,
1780*7c478bd9Sstevel@tonic-gate 			al->success, al->failure);
1781*7c478bd9Sstevel@tonic-gate 	}
1782*7c478bd9Sstevel@tonic-gate }
1783*7c478bd9Sstevel@tonic-gate 
1784*7c478bd9Sstevel@tonic-gate static char *
1785*7c478bd9Sstevel@tonic-gate spaces(howmany)
1786*7c478bd9Sstevel@tonic-gate int howmany;
1787*7c478bd9Sstevel@tonic-gate {
1788*7c478bd9Sstevel@tonic-gate 	static char space_array[] =		/* 64 spaces */
1789*7c478bd9Sstevel@tonic-gate 	"                                                                ";
1790*7c478bd9Sstevel@tonic-gate 
1791*7c478bd9Sstevel@tonic-gate 	if (howmany <= 0 || howmany > sizeof (space_array)) {
1792*7c478bd9Sstevel@tonic-gate 		return ("");
1793*7c478bd9Sstevel@tonic-gate 	}
1794*7c478bd9Sstevel@tonic-gate 	return (&space_array[sizeof (space_array) - howmany - 1]);
1795*7c478bd9Sstevel@tonic-gate }
1796