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