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