3 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4 * unrestricted use provided that this legend is included on all tape
5 * media and as a part of the software program in whole or part. Users
6 * may copy or modify Sun RPC without charge, but are not authorized
7 * to license or distribute it to anyone else except as part of a product or
8 * program developed by the user.
10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 * Sun RPC is provided with no support and without any obligation on the
15 * part of Sun Microsystems, Inc. to assist in its use, correction,
16 * modification or enhancement.
18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20 * OR ANY PART THEREOF.
22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23 * or profits or other special, indirect and consequential damages, even if
24 * Sun has been advised of the possibility of such damages.
26 * Sun Microsystems, Inc.
28 * Mountain View, California 94043
30 * @(#)rpcinfo.c 1.18 93/07/05 SMI; 1.16 89/04/05 Copyr 1986 Sun Micro
31 * $NetBSD: rpcinfo.c,v 1.15 2000/10/04 20:09:05 mjl Exp $
32 * $FreeBSD: src/usr.bin/rpcinfo/rpcinfo.c,v 1.17 2004/03/11 10:22:25 bde Exp $
33 * $DragonFly: src/usr.bin/rpcinfo/rpcinfo.c,v 1.3 2007/11/25 01:28:23 swildner Exp $
37 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
41 * rpcinfo: ping a particular rpc program
42 * or dump the the registered programs on the remote machine.
46 * We are for now defining PORTMAP here. It doesnt even compile
47 * unless it is defined.
54 * If PORTMAP is defined, rpcinfo will talk to both portmapper and
55 * rpcbind programs; else it talks only to rpcbind. In the latter case
56 * all the portmapper specific options such as -u, -t, -p become void.
58 #include <sys/types.h>
59 #include <sys/param.h>
60 #include <sys/socket.h>
64 #include <rpc/rpcb_prot.h>
65 #include <rpc/rpcent.h>
66 #include <rpc/nettype.h>
67 #include <rpc/rpc_com.h>
74 #ifdef PORTMAP /* Support for version 2 portmapper */
75 #include <netinet/in.h>
77 #include <arpa/inet.h>
78 #include <rpc/pmap_prot.h>
79 #include <rpc/pmap_clnt.h>
82 #define MAXHOSTLEN 256
83 #define MIN_VERS ((u_long) 0)
84 #define MAX_VERS ((u_long) 4294967295UL)
85 #define UNKNOWN "unknown"
88 * Functions to be performed.
90 #define NONE 0 /* no function */
91 #define PMAPDUMP 1 /* dump portmapper registrations */
92 #define TCPPING 2 /* ping TCP service */
93 #define UDPPING 3 /* ping UDP service */
94 #define BROADCAST 4 /* ping broadcast service */
95 #define DELETES 5 /* delete registration for the service */
96 #define ADDRPING 6 /* pings at the given address */
97 #define PROGPING 7 /* pings a program on a given host */
98 #define RPCBDUMP 8 /* dump rpcbind registrations */
99 #define RPCBDUMP_SHORT 9 /* dump rpcbind registrations - short version */
100 #define RPCBADDRLIST 10 /* dump addr list about one prog */
101 #define RPCBGETSTAT 11 /* Get statistics */
105 struct netidlist
*next
;
110 struct verslist
*next
;
113 struct rpcbdump_short
{
115 struct verslist
*vlist
;
116 struct netidlist
*nlist
;
117 struct rpcbdump_short
*next
;
124 static void ip_ping(u_short
, char *, int, char **);
125 static CLIENT
*clnt_com_create(struct sockaddr_in
*, u_long
, u_long
, int *,
127 static void pmapdump(int, char **);
128 static void get_inet_address(struct sockaddr_in
*, char *);
131 static bool_t
reply_proc(void *, struct netbuf
*, struct netconfig
*);
132 static void brdcst(int, char **);
133 static void addrping(char *, char *, int, char **);
134 static void progping(char *, int, char **);
135 static CLIENT
*clnt_addr_create(char *, struct netconfig
*, u_long
, u_long
);
136 static CLIENT
*clnt_rpcbind_create(char *, int, struct netbuf
**);
137 static CLIENT
*getclnthandle(char *, struct netconfig
*, u_long
,
139 static CLIENT
*local_rpcb(u_long
, u_long
);
140 static int pstatus(CLIENT
*, u_long
, u_long
);
141 static void rpcbdump(int, char *, int, char **);
142 static void rpcbgetstat(int, char **);
143 static void rpcbaddrlist(char *, int, char **);
144 static void deletereg(char *, int, char **);
145 static void print_rmtcallstat(int, rpcb_stat
*);
146 static void print_getaddrstat(int, rpcb_stat
*);
147 static void usage(void);
148 static u_long
getprognum(char *);
149 static u_long
getvers(char *);
150 static char *spaces(int);
151 static bool_t
add_version(struct rpcbdump_short
*, u_long
);
152 static bool_t
add_netid(struct rpcbdump_short
*, char *);
155 main(int argc
, char **argv
)
161 char *address
= NULL
;
170 while ((c
= getopt(argc
, argv
, "a:bdlmn:pstT:u")) != -1) {
172 while ((c
= getopt(argc
, argv
, "a:bdlmn:sT:")) != -1) {
177 if (function
!= NONE
)
184 if (function
!= NONE
)
191 if (function
!= NONE
)
198 portnum
= (u_short
) strtol(optarg
, &strptr
, 10);
199 if (strptr
== optarg
|| *strptr
!= '\0')
200 errx(1, "%s is illegal port number", optarg
);
205 if (function
!= NONE
)
211 if (function
!= NONE
)
214 function
= BROADCAST
;
218 if (function
!= NONE
)
225 if (function
!= NONE
)
228 function
= RPCBADDRLIST
;
232 if (function
!= NONE
)
235 function
= RPCBGETSTAT
;
239 if (function
!= NONE
)
242 function
= RPCBDUMP_SHORT
;
254 if (errflg
|| ((function
== ADDRPING
) && !netid
))
257 if (function
== NONE
) {
258 if (argc
- optind
> 1)
269 pmapdump(argc
- optind
, argv
+ optind
);
273 ip_ping(portnum
, "udp", argc
- optind
, argv
+ optind
);
277 ip_ping(portnum
, "tcp", argc
- optind
, argv
+ optind
);
281 brdcst(argc
- optind
, argv
+ optind
);
284 deletereg(netid
, argc
- optind
, argv
+ optind
);
287 addrping(address
, netid
, argc
- optind
, argv
+ optind
);
290 progping(netid
, argc
- optind
, argv
+ optind
);
294 rpcbdump(function
, netid
, argc
- optind
, argv
+ optind
);
297 rpcbgetstat(argc
- optind
, argv
+ optind
);
300 rpcbaddrlist(netid
, argc
- optind
, argv
+ optind
);
307 local_rpcb(u_long prog
, u_long vers
)
310 struct netconfig
*nconf
;
313 localhandle
= setnetconfig();
314 while ((nconf
= getnetconfig(localhandle
)) != NULL
) {
315 if (nconf
->nc_protofmly
!= NULL
&&
316 strcmp(nconf
->nc_protofmly
, NC_LOOPBACK
) == 0)
320 warnx("getnetconfig: %s", nc_sperror());
324 clnt
= clnt_tp_create(NULL
, prog
, vers
, nconf
);
325 endnetconfig(localhandle
);
331 clnt_com_create(struct sockaddr_in
*addr
, u_long prog
, u_long vers
,
332 int *fdp
, char *trans
)
336 if (strcmp(trans
, "tcp") == 0) {
337 clnt
= clnttcp_create(addr
, prog
, vers
, fdp
, 0, 0);
343 clnt
= clntudp_create(addr
, prog
, vers
, to
, fdp
);
346 clnt_pcreateerror("rpcinfo");
347 if (vers
== MIN_VERS
)
348 printf("program %lu is not available\n", prog
);
350 printf("program %lu version %lu is not available\n",
358 * If portnum is 0, then go and get the address from portmapper, which happens
359 * transparently through clnt*_create(); If version number is not given, it
360 * tries to find out the version number by making a call to version 0 and if
361 * that fails, it obtains the high order and the low order version number. If
362 * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
365 ip_ping(u_short portnum
, char *trans
, int argc
, char **argv
)
370 struct sockaddr_in addr
;
371 enum clnt_stat rpc_stat
;
372 u_long prognum
, vers
, minvers
, maxvers
;
373 struct rpc_err rpcerr
;
376 if (argc
< 2 || argc
> 3)
380 prognum
= getprognum(argv
[1]);
381 get_inet_address(&addr
, argv
[0]);
382 if (argc
== 2) { /* Version number not known */
384 * A call to version 0 should fail with a program/version
385 * mismatch, and give us the range of versions supported.
389 vers
= getvers(argv
[2]);
391 addr
.sin_port
= htons(portnum
);
392 client
= clnt_com_create(&addr
, prognum
, vers
, &fd
, trans
);
393 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
394 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
396 /* Version number was known */
397 if (pstatus(client
, prognum
, vers
) < 0)
399 CLNT_DESTROY(client
);
402 /* Version number not known */
403 CLNT_CONTROL(client
, CLSET_FD_NCLOSE
, NULL
);
404 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
405 clnt_geterr(client
, &rpcerr
);
406 minvers
= rpcerr
.re_vers
.low
;
407 maxvers
= rpcerr
.re_vers
.high
;
408 } else if (rpc_stat
== RPC_SUCCESS
) {
410 * Oh dear, it DOES support version 0.
411 * Let's try version MAX_VERS.
413 CLNT_DESTROY(client
);
414 addr
.sin_port
= htons(portnum
);
415 client
= clnt_com_create(&addr
, prognum
, MAX_VERS
, &fd
, trans
);
416 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
417 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
418 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
419 clnt_geterr(client
, &rpcerr
);
420 minvers
= rpcerr
.re_vers
.low
;
421 maxvers
= rpcerr
.re_vers
.high
;
422 } else if (rpc_stat
== RPC_SUCCESS
) {
424 * It also supports version MAX_VERS.
425 * Looks like we have a wise guy.
426 * OK, we give them information on all
427 * 4 billion versions they support...
432 pstatus(client
, prognum
, MAX_VERS
);
436 pstatus(client
, prognum
, (u_long
)0);
439 CLNT_DESTROY(client
);
440 for (vers
= minvers
; vers
<= maxvers
; vers
++) {
441 addr
.sin_port
= htons(portnum
);
442 client
= clnt_com_create(&addr
, prognum
, vers
, &fd
, trans
);
443 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
444 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
445 if (pstatus(client
, prognum
, vers
) < 0)
447 CLNT_DESTROY(client
);
456 * Dump all the portmapper registerations
459 pmapdump(int argc
, char **argv
)
461 struct sockaddr_in server_addr
;
462 struct pmaplist
*head
= NULL
;
463 int socket
= RPC_ANYSOCK
;
464 struct timeval minutetimeout
;
467 enum clnt_stat clnt_st
;
475 get_inet_address(&server_addr
, host
);
476 server_addr
.sin_port
= htons(PMAPPORT
);
477 client
= clnttcp_create(&server_addr
, PMAPPROG
, PMAPVERS
,
480 client
= local_rpcb(PMAPPROG
, PMAPVERS
);
482 if (client
== NULL
) {
483 if (rpc_createerr
.cf_stat
== RPC_TLIERROR
) {
485 * "Misc. TLI error" is not too helpful. Most likely
486 * the connection to the remote server timed out, so
487 * this error is at least less perplexing.
489 rpc_createerr
.cf_stat
= RPC_PMAPFAILURE
;
490 rpc_createerr
.cf_error
.re_status
= RPC_FAILED
;
492 clnt_pcreateerror("rpcinfo: can't contact portmapper");
496 minutetimeout
.tv_sec
= 60;
497 minutetimeout
.tv_usec
= 0;
499 clnt_st
= CLNT_CALL(client
, PMAPPROC_DUMP
, (xdrproc_t
) xdr_void
,
500 NULL
, (xdrproc_t
) xdr_pmaplist_ptr
, (char *)&head
,
502 if (clnt_st
!= RPC_SUCCESS
) {
503 if ((clnt_st
== RPC_PROGVERSMISMATCH
) ||
504 (clnt_st
== RPC_PROGUNAVAIL
)) {
505 CLNT_GETERR(client
, &err
);
506 if (err
.re_vers
.low
> PMAPVERS
)
508 "%s does not support portmapper. Try rpcinfo %s instead",
512 clnt_perror(client
, "rpcinfo: can't contact portmapper");
516 printf("No remote programs registered.\n");
518 printf(" program vers proto port service\n");
519 for (; head
!= NULL
; head
= head
->pml_next
) {
521 head
->pml_map
.pm_prog
,
522 head
->pml_map
.pm_vers
);
523 if (head
->pml_map
.pm_prot
== IPPROTO_UDP
)
524 printf("%6s", "udp");
525 else if (head
->pml_map
.pm_prot
== IPPROTO_TCP
)
526 printf("%6s", "tcp");
527 else if (head
->pml_map
.pm_prot
== IPPROTO_ST
)
528 printf("%6s", "local");
530 printf("%6ld", head
->pml_map
.pm_prot
);
531 printf("%7ld", head
->pml_map
.pm_port
);
532 rpc
= getrpcbynumber(head
->pml_map
.pm_prog
);
534 printf(" %s\n", rpc
->r_name
);
542 get_inet_address(struct sockaddr_in
*addr
, char *host
)
544 struct netconfig
*nconf
;
545 struct addrinfo hints
, *res
;
548 memset((char *)addr
, 0, sizeof (*addr
));
549 addr
->sin_addr
.s_addr
= inet_addr(host
);
550 if (addr
->sin_addr
.s_addr
== -1 || addr
->sin_addr
.s_addr
== 0) {
551 if ((nconf
= __rpc_getconfip("udp")) == NULL
&&
552 (nconf
= __rpc_getconfip("tcp")) == NULL
)
553 errx(1, "couldn't find a suitable transport");
555 memset(&hints
, 0, sizeof hints
);
556 hints
.ai_family
= AF_INET
;
557 if ((error
= getaddrinfo(host
, "rpcbind", &hints
, &res
))
559 errx(1, "%s: %s", host
, gai_strerror(error
));
561 memcpy(addr
, res
->ai_addr
, res
->ai_addrlen
);
564 freenetconfigent(nconf
);
567 addr
->sin_family
= AF_INET
;
573 * reply_proc collects replies from the broadcast.
574 * to get a unique list of responses the output of rpcinfo should
575 * be piped through sort(1) and then uniq(1).
580 reply_proc(void *res
, struct netbuf
*who
, struct netconfig
*nconf
)
581 /* void *res; Nothing comes back */
582 /* struct netbuf *who; Who sent us the reply */
583 /* struct netconfig *nconf; On which transport the reply came */
586 char hostbuf
[NI_MAXHOST
];
588 struct sockaddr
*sa
= (struct sockaddr
*)who
->buf
;
590 if (getnameinfo(sa
, sa
->sa_len
, hostbuf
, NI_MAXHOST
, NULL
, 0, 0)) {
595 if (!(uaddr
= taddr2uaddr(nconf
, who
))) {
598 printf("%s\t%s\n", uaddr
, hostname
);
599 if (strcmp(uaddr
, UNKNOWN
))
605 brdcst(int argc
, char **argv
)
607 enum clnt_stat rpc_stat
;
608 u_long prognum
, vers
;
612 prognum
= getprognum(argv
[0]);
613 vers
= getvers(argv
[1]);
614 rpc_stat
= rpc_broadcast(prognum
, vers
, NULLPROC
,
615 (xdrproc_t
) xdr_void
, NULL
, (xdrproc_t
) xdr_void
,
616 NULL
, (resultproc_t
) reply_proc
, NULL
);
617 if ((rpc_stat
!= RPC_SUCCESS
) && (rpc_stat
!= RPC_TIMEDOUT
))
618 errx(1, "broadcast failed: %s", clnt_sperrno(rpc_stat
));
623 add_version(struct rpcbdump_short
*rs
, u_long vers
)
627 for (vl
= rs
->vlist
; vl
; vl
= vl
->next
)
628 if (vl
->vers
== vers
)
632 vl
= (struct verslist
*)malloc(sizeof (struct verslist
));
636 vl
->next
= rs
->vlist
;
642 add_netid(struct rpcbdump_short
*rs
, char *netid
)
644 struct netidlist
*nl
;
646 for (nl
= rs
->nlist
; nl
; nl
= nl
->next
)
647 if (strcmp(nl
->netid
, netid
) == 0)
651 nl
= (struct netidlist
*)malloc(sizeof (struct netidlist
));
655 nl
->next
= rs
->nlist
;
661 rpcbdump(int dumptype
, char *netid
, int argc
, char **argv
)
663 rpcblist_ptr head
= NULL
;
664 struct timeval minutetimeout
;
668 struct netidlist
*nl
;
670 struct rpcbdump_short
*rs
, *rs_tail
;
672 enum clnt_stat clnt_st
;
674 struct rpcbdump_short
*rs_head
= NULL
;
681 client
= clnt_rpcbind_create(host
, RPCBVERS
, NULL
);
683 struct netconfig
*nconf
;
685 nconf
= getnetconfigent(netid
);
687 nc_perror("rpcinfo: invalid transport");
690 client
= getclnthandle(host
, nconf
, RPCBVERS
, NULL
);
692 freenetconfigent(nconf
);
695 client
= local_rpcb(PMAPPROG
, RPCBVERS
);
697 if (client
== NULL
) {
698 clnt_pcreateerror("rpcinfo: can't contact rpcbind");
702 minutetimeout
.tv_sec
= 60;
703 minutetimeout
.tv_usec
= 0;
704 clnt_st
= CLNT_CALL(client
, RPCBPROC_DUMP
, (xdrproc_t
) xdr_void
,
705 NULL
, (xdrproc_t
) xdr_rpcblist_ptr
, (char *) &head
,
707 if (clnt_st
!= RPC_SUCCESS
) {
708 if ((clnt_st
== RPC_PROGVERSMISMATCH
) ||
709 (clnt_st
== RPC_PROGUNAVAIL
)) {
712 CLNT_GETERR(client
, &err
);
713 if (err
.re_vers
.low
== RPCBVERS4
) {
715 clnt_control(client
, CLSET_VERS
, (char *)&vers
);
716 clnt_st
= CLNT_CALL(client
, RPCBPROC_DUMP
,
717 (xdrproc_t
) xdr_void
, NULL
,
718 (xdrproc_t
) xdr_rpcblist_ptr
, (char *) &head
,
720 if (clnt_st
!= RPC_SUCCESS
)
723 if (err
.re_vers
.high
== PMAPVERS
) {
725 struct pmaplist
*pmaphead
= NULL
;
726 rpcblist_ptr list
, prev
;
729 clnt_control(client
, CLSET_VERS
, (char *)&vers
);
730 clnt_st
= CLNT_CALL(client
, PMAPPROC_DUMP
,
731 (xdrproc_t
) xdr_void
, NULL
,
732 (xdrproc_t
) xdr_pmaplist_ptr
,
733 (char *)&pmaphead
, minutetimeout
);
734 if (clnt_st
!= RPC_SUCCESS
)
737 * convert to rpcblist_ptr format
739 for (head
= NULL
; pmaphead
!= NULL
;
740 pmaphead
= pmaphead
->pml_next
) {
741 list
= (rpcblist
*)malloc(sizeof (rpcblist
));
747 prev
->rpcb_next
= (rpcblist_ptr
) list
;
749 list
->rpcb_next
= NULL
;
750 list
->rpcb_map
.r_prog
= pmaphead
->pml_map
.pm_prog
;
751 list
->rpcb_map
.r_vers
= pmaphead
->pml_map
.pm_vers
;
752 if (pmaphead
->pml_map
.pm_prot
== IPPROTO_UDP
)
753 list
->rpcb_map
.r_netid
= "udp";
754 else if (pmaphead
->pml_map
.pm_prot
== IPPROTO_TCP
)
755 list
->rpcb_map
.r_netid
= "tcp";
757 #define MAXLONG_AS_STRING "2147483648"
758 list
->rpcb_map
.r_netid
=
759 malloc(strlen(MAXLONG_AS_STRING
) + 1);
760 if (list
->rpcb_map
.r_netid
== NULL
)
762 sprintf(list
->rpcb_map
.r_netid
, "%6ld",
763 pmaphead
->pml_map
.pm_prot
);
765 list
->rpcb_map
.r_owner
= UNKNOWN
;
766 low
= pmaphead
->pml_map
.pm_port
& 0xff;
767 high
= (pmaphead
->pml_map
.pm_port
>> 8) & 0xff;
768 list
->rpcb_map
.r_addr
= strdup("0.0.0.0.XXX.XXX");
769 sprintf(&list
->rpcb_map
.r_addr
[8], "%d.%d",
775 } else { /* any other error */
777 clnt_perror(client
, "rpcinfo: can't contact rpcbind: ");
782 printf("No remote programs registered.\n");
783 } else if (dumptype
== RPCBDUMP
) {
785 " program version netid address service owner\n");
786 for (; head
!= NULL
; head
= head
->rpcb_next
) {
788 head
->rpcb_map
.r_prog
, head
->rpcb_map
.r_vers
);
789 printf("%-9s ", head
->rpcb_map
.r_netid
);
790 printf("%-22s", head
->rpcb_map
.r_addr
);
791 rpc
= getrpcbynumber(head
->rpcb_map
.r_prog
);
793 printf(" %-10s", rpc
->r_name
);
795 printf(" %-10s", "-");
796 printf(" %s\n", head
->rpcb_map
.r_owner
);
798 } else if (dumptype
== RPCBDUMP_SHORT
) {
799 for (; head
!= NULL
; head
= head
->rpcb_next
) {
800 for (rs
= rs_head
; rs
; rs
= rs
->next
)
801 if (head
->rpcb_map
.r_prog
== rs
->prog
)
804 rs
= (struct rpcbdump_short
*)
805 malloc(sizeof (struct rpcbdump_short
));
809 if (rs_head
== NULL
) {
816 rs
->prog
= head
->rpcb_map
.r_prog
;
817 rs
->owner
= head
->rpcb_map
.r_owner
;
821 if (add_version(rs
, head
->rpcb_map
.r_vers
) == FALSE
)
823 if (add_netid(rs
, head
->rpcb_map
.r_netid
) == FALSE
)
827 " program version(s) netid(s) service owner\n");
828 for (rs
= rs_head
; rs
; rs
= rs
->next
) {
831 printf("%10ld ", rs
->prog
);
832 for (vl
= rs
->vlist
; vl
; vl
= vl
->next
) {
833 sprintf(p
, "%d", vl
->vers
);
838 printf("%-10s", buf
);
840 for (nl
= rs
->nlist
; nl
; nl
= nl
->next
) {
841 strcat(buf
, nl
->netid
);
845 printf("%-32s", buf
);
846 rpc
= getrpcbynumber(rs
->prog
);
848 printf(" %-11s", rpc
->r_name
);
850 printf(" %-11s", "-");
851 printf(" %s\n", rs
->owner
);
854 clnt_destroy(client
);
856 error
: warnx("no memory");
860 static char nullstring
[] = "\000";
863 rpcbaddrlist(char *netid
, int argc
, char **argv
)
865 rpcb_entry_list_ptr head
= NULL
;
866 struct timeval minutetimeout
;
871 struct netbuf
*targaddr
;
877 client
= clnt_rpcbind_create(host
, RPCBVERS4
, &targaddr
);
879 struct netconfig
*nconf
;
881 nconf
= getnetconfigent(netid
);
883 nc_perror("rpcinfo: invalid transport");
886 client
= getclnthandle(host
, nconf
, RPCBVERS4
, &targaddr
);
888 freenetconfigent(nconf
);
890 if (client
== NULL
) {
891 clnt_pcreateerror("rpcinfo: can't contact rpcbind");
894 minutetimeout
.tv_sec
= 60;
895 minutetimeout
.tv_usec
= 0;
897 parms
.r_prog
= getprognum(argv
[1]);
898 parms
.r_vers
= getvers(argv
[2]);
899 parms
.r_netid
= client
->cl_netid
;
900 if (targaddr
== NULL
) {
901 parms
.r_addr
= nullstring
; /* for XDRing */
904 * We also send the remote system the address we
905 * used to contact it in case it can help it
906 * connect back with us
908 struct netconfig
*nconf
;
910 nconf
= getnetconfigent(client
->cl_netid
);
912 parms
.r_addr
= taddr2uaddr(nconf
, targaddr
);
913 if (parms
.r_addr
== NULL
)
914 parms
.r_addr
= nullstring
;
915 freenetconfigent(nconf
);
917 parms
.r_addr
= nullstring
; /* for XDRing */
922 parms
.r_owner
= nullstring
;
924 if (CLNT_CALL(client
, RPCBPROC_GETADDRLIST
, (xdrproc_t
) xdr_rpcb
,
925 (char *) &parms
, (xdrproc_t
) xdr_rpcb_entry_list_ptr
,
926 (char *) &head
, minutetimeout
) != RPC_SUCCESS
) {
927 clnt_perror(client
, "rpcinfo: can't contact rpcbind: ");
931 printf("No remote programs registered.\n");
934 " program vers tp_family/name/class address\t\t service\n");
935 for (; head
!= NULL
; head
= head
->rpcb_entry_next
) {
939 re
= &head
->rpcb_entry_map
;
941 parms
.r_prog
, parms
.r_vers
);
942 sprintf(buf
, "%s/%s/%s ",
943 re
->r_nc_protofmly
, re
->r_nc_proto
,
944 re
->r_nc_semantics
== NC_TPI_CLTS
? "clts" :
945 re
->r_nc_semantics
== NC_TPI_COTS
? "cots" :
947 printf("%-24s", buf
);
948 printf("%-24s", re
->r_maddr
);
949 rpc
= getrpcbynumber(parms
.r_prog
);
951 printf(" %-13s", rpc
->r_name
);
953 printf(" %-13s", "-");
957 clnt_destroy(client
);
965 rpcbgetstat(int argc
, char **argv
)
967 rpcb_stat_byvers inf
;
968 struct timeval minutetimeout
;
973 rpcbs_rmtcalllist
*pr
;
976 char fieldbuf
[MAXFIELD
];
978 char linebuf
[MAXLINE
];
981 "NULL", "SET", "UNSET", "GETPORT",
985 "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
989 "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
990 "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
997 client
= clnt_rpcbind_create(host
, RPCBVERS4
, NULL
);
999 client
= local_rpcb(PMAPPROG
, RPCBVERS4
);
1000 if (client
== NULL
) {
1001 clnt_pcreateerror("rpcinfo: can't contact rpcbind");
1004 minutetimeout
.tv_sec
= 60;
1005 minutetimeout
.tv_usec
= 0;
1006 memset((char *)&inf
, 0, sizeof (rpcb_stat_byvers
));
1007 if (CLNT_CALL(client
, RPCBPROC_GETSTAT
, (xdrproc_t
) xdr_void
, NULL
,
1008 (xdrproc_t
) xdr_rpcb_stat_byvers
, (char *)&inf
, minutetimeout
)
1010 clnt_perror(client
, "rpcinfo: can't contact rpcbind: ");
1013 printf("PORTMAP (version 2) statistics\n");
1015 for (i
= 0; i
<= rpcb_highproc_2
; i
++) {
1019 sprintf(fieldbuf
, "%d/", inf
[RPCBVERS_2_STAT
].setinfo
);
1021 case PMAPPROC_UNSET
:
1022 sprintf(fieldbuf
, "%d/",
1023 inf
[RPCBVERS_2_STAT
].unsetinfo
);
1025 case PMAPPROC_GETPORT
:
1027 for (pa
= inf
[RPCBVERS_2_STAT
].addrinfo
; pa
;
1030 sprintf(fieldbuf
, "%d/", cnt
);
1032 case PMAPPROC_CALLIT
:
1034 for (pr
= inf
[RPCBVERS_2_STAT
].rmtinfo
; pr
;
1037 sprintf(fieldbuf
, "%d/", cnt
);
1039 default: break; /* For the remaining ones */
1041 cp
= &fieldbuf
[0] + strlen(fieldbuf
);
1042 sprintf(cp
, "%d", inf
[RPCBVERS_2_STAT
].info
[i
]);
1043 flen
= strlen(fieldbuf
);
1044 printf("%s%s", pmaphdr
[i
],
1045 spaces((TABSTOP
* (1 + flen
/ TABSTOP
))
1046 - strlen(pmaphdr
[i
])));
1047 sprintf(lp
, "%s%s", fieldbuf
,
1048 spaces(cnt
= ((TABSTOP
* (1 + flen
/ TABSTOP
))
1052 printf("\n%s\n\n", linebuf
);
1054 if (inf
[RPCBVERS_2_STAT
].info
[PMAPPROC_CALLIT
]) {
1055 printf("PMAP_RMTCALL call statistics\n");
1056 print_rmtcallstat(RPCBVERS_2_STAT
, &inf
[RPCBVERS_2_STAT
]);
1060 if (inf
[RPCBVERS_2_STAT
].info
[PMAPPROC_GETPORT
]) {
1061 printf("PMAP_GETPORT call statistics\n");
1062 print_getaddrstat(RPCBVERS_2_STAT
, &inf
[RPCBVERS_2_STAT
]);
1066 printf("RPCBIND (version 3) statistics\n");
1068 for (i
= 0; i
<= rpcb_highproc_3
; i
++) {
1072 sprintf(fieldbuf
, "%d/", inf
[RPCBVERS_3_STAT
].setinfo
);
1074 case RPCBPROC_UNSET
:
1075 sprintf(fieldbuf
, "%d/",
1076 inf
[RPCBVERS_3_STAT
].unsetinfo
);
1078 case RPCBPROC_GETADDR
:
1080 for (pa
= inf
[RPCBVERS_3_STAT
].addrinfo
; pa
;
1083 sprintf(fieldbuf
, "%d/", cnt
);
1085 case RPCBPROC_CALLIT
:
1087 for (pr
= inf
[RPCBVERS_3_STAT
].rmtinfo
; pr
;
1090 sprintf(fieldbuf
, "%d/", cnt
);
1092 default: break; /* For the remaining ones */
1094 cp
= &fieldbuf
[0] + strlen(fieldbuf
);
1095 sprintf(cp
, "%d", inf
[RPCBVERS_3_STAT
].info
[i
]);
1096 flen
= strlen(fieldbuf
);
1097 printf("%s%s", rpcb3hdr
[i
],
1098 spaces((TABSTOP
* (1 + flen
/ TABSTOP
))
1099 - strlen(rpcb3hdr
[i
])));
1100 sprintf(lp
, "%s%s", fieldbuf
,
1101 spaces(cnt
= ((TABSTOP
* (1 + flen
/ TABSTOP
))
1105 printf("\n%s\n\n", linebuf
);
1107 if (inf
[RPCBVERS_3_STAT
].info
[RPCBPROC_CALLIT
]) {
1108 printf("RPCB_RMTCALL (version 3) call statistics\n");
1109 print_rmtcallstat(RPCBVERS_3_STAT
, &inf
[RPCBVERS_3_STAT
]);
1113 if (inf
[RPCBVERS_3_STAT
].info
[RPCBPROC_GETADDR
]) {
1114 printf("RPCB_GETADDR (version 3) call statistics\n");
1115 print_getaddrstat(RPCBVERS_3_STAT
, &inf
[RPCBVERS_3_STAT
]);
1119 printf("RPCBIND (version 4) statistics\n");
1121 for (j
= 0; j
<= 9; j
+= 9) { /* Just two iterations for printing */
1123 for (i
= j
; i
<= MAX(8, rpcb_highproc_4
- 9 + j
); i
++) {
1127 sprintf(fieldbuf
, "%d/",
1128 inf
[RPCBVERS_4_STAT
].setinfo
);
1130 case RPCBPROC_UNSET
:
1131 sprintf(fieldbuf
, "%d/",
1132 inf
[RPCBVERS_4_STAT
].unsetinfo
);
1134 case RPCBPROC_GETADDR
:
1136 for (pa
= inf
[RPCBVERS_4_STAT
].addrinfo
; pa
;
1139 sprintf(fieldbuf
, "%d/", cnt
);
1141 case RPCBPROC_CALLIT
:
1143 for (pr
= inf
[RPCBVERS_4_STAT
].rmtinfo
; pr
;
1146 sprintf(fieldbuf
, "%d/", cnt
);
1148 default: break; /* For the remaining ones */
1150 cp
= &fieldbuf
[0] + strlen(fieldbuf
);
1152 * XXX: We also add RPCBPROC_GETADDRLIST queries to
1153 * RPCB_GETADDR because rpcbind includes the
1154 * RPCB_GETADDRLIST successes in RPCB_GETADDR.
1156 if (i
!= RPCBPROC_GETADDR
)
1157 sprintf(cp
, "%d", inf
[RPCBVERS_4_STAT
].info
[i
]);
1159 sprintf(cp
, "%d", inf
[RPCBVERS_4_STAT
].info
[i
] +
1160 inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_GETADDRLIST
]);
1161 flen
= strlen(fieldbuf
);
1162 printf("%s%s", rpcb4hdr
[i
],
1163 spaces((TABSTOP
* (1 + flen
/ TABSTOP
))
1164 - strlen(rpcb4hdr
[i
])));
1165 sprintf(lp
, "%s%s", fieldbuf
,
1166 spaces(cnt
= ((TABSTOP
* (1 + flen
/ TABSTOP
))
1170 printf("\n%s\n", linebuf
);
1173 if (inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_CALLIT
] ||
1174 inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_INDIRECT
]) {
1176 printf("RPCB_RMTCALL (version 4) call statistics\n");
1177 print_rmtcallstat(RPCBVERS_4_STAT
, &inf
[RPCBVERS_4_STAT
]);
1180 if (inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_GETADDR
]) {
1182 printf("RPCB_GETADDR (version 4) call statistics\n");
1183 print_getaddrstat(RPCBVERS_4_STAT
, &inf
[RPCBVERS_4_STAT
]);
1185 clnt_destroy(client
);
1189 * Delete registeration for this (prog, vers, netid)
1192 deletereg(char *netid
, int argc
, char **argv
)
1194 struct netconfig
*nconf
= NULL
;
1199 nconf
= getnetconfigent(netid
);
1201 errx(1, "netid %s not supported", netid
);
1203 if ((rpcb_unset(getprognum(argv
[0]), getvers(argv
[1]), nconf
)) == 0)
1205 "could not delete registration for prog %s version %s",
1210 * Create and return a handle for the given nconf.
1211 * Exit if cannot create handle.
1214 clnt_addr_create(char *address
, struct netconfig
*nconf
,
1215 u_long prog
, u_long vers
)
1218 static struct netbuf
*nbuf
;
1219 static int fd
= RPC_ANYFD
;
1221 if (fd
== RPC_ANYFD
) {
1222 if ((fd
= __rpc_nconf2fd(nconf
)) == -1) {
1223 rpc_createerr
.cf_stat
= RPC_TLIERROR
;
1224 clnt_pcreateerror("rpcinfo");
1227 /* Convert the uaddr to taddr */
1228 nbuf
= uaddr2taddr(nconf
, address
);
1230 errx(1, "no address for client handle");
1232 client
= clnt_tli_create(fd
, nconf
, nbuf
, prog
, vers
, 0, 0);
1233 if (client
== NULL
) {
1234 clnt_pcreateerror("rpcinfo");
1241 * If the version number is given, ping that (prog, vers); else try to find
1242 * the version numbers supported for that prog and ping all the versions.
1243 * Remote rpcbind is not contacted for this service. The requests are
1244 * sent directly to the services themselves.
1247 addrping(char *address
, char *netid
, int argc
, char **argv
)
1251 enum clnt_stat rpc_stat
;
1252 u_long prognum
, versnum
, minvers
, maxvers
;
1253 struct rpc_err rpcerr
;
1255 struct netconfig
*nconf
;
1258 if (argc
< 1 || argc
> 2 || (netid
== NULL
))
1260 nconf
= getnetconfigent(netid
);
1262 errx(1, "could not find %s", netid
);
1265 prognum
= getprognum(argv
[0]);
1266 if (argc
== 1) { /* Version number not known */
1268 * A call to version 0 should fail with a program/version
1269 * mismatch, and give us the range of versions supported.
1273 versnum
= getvers(argv
[1]);
1275 client
= clnt_addr_create(address
, nconf
, prognum
, versnum
);
1276 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1277 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1279 /* Version number was known */
1280 if (pstatus(client
, prognum
, versnum
) < 0)
1282 CLNT_DESTROY(client
);
1287 /* Version number not known */
1288 CLNT_CONTROL(client
, CLSET_FD_NCLOSE
, NULL
);
1289 CLNT_CONTROL(client
, CLGET_FD
, (char *)&fd
);
1290 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1291 clnt_geterr(client
, &rpcerr
);
1292 minvers
= rpcerr
.re_vers
.low
;
1293 maxvers
= rpcerr
.re_vers
.high
;
1294 } else if (rpc_stat
== RPC_SUCCESS
) {
1296 * Oh dear, it DOES support version 0.
1297 * Let's try version MAX_VERS.
1299 CLNT_DESTROY(client
);
1300 client
= clnt_addr_create(address
, nconf
, prognum
, MAX_VERS
);
1301 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1302 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1303 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1304 clnt_geterr(client
, &rpcerr
);
1305 minvers
= rpcerr
.re_vers
.low
;
1306 maxvers
= rpcerr
.re_vers
.high
;
1307 } else if (rpc_stat
== RPC_SUCCESS
) {
1309 * It also supports version MAX_VERS.
1310 * Looks like we have a wise guy.
1311 * OK, we give them information on all
1312 * 4 billion versions they support...
1317 pstatus(client
, prognum
, MAX_VERS
);
1321 pstatus(client
, prognum
, (u_long
)0);
1324 CLNT_DESTROY(client
);
1325 for (versnum
= minvers
; versnum
<= maxvers
; versnum
++) {
1326 client
= clnt_addr_create(address
, nconf
, prognum
, versnum
);
1327 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1328 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1329 if (pstatus(client
, prognum
, versnum
) < 0)
1331 CLNT_DESTROY(client
);
1340 * If the version number is given, ping that (prog, vers); else try to find
1341 * the version numbers supported for that prog and ping all the versions.
1342 * Remote rpcbind is *contacted* for this service. The requests are
1343 * then sent directly to the services themselves.
1346 progping(char *netid
, int argc
, char **argv
)
1350 enum clnt_stat rpc_stat
;
1351 u_long prognum
, versnum
, minvers
, maxvers
;
1352 struct rpc_err rpcerr
;
1354 struct netconfig
*nconf
;
1356 if (argc
< 2 || argc
> 3 || (netid
== NULL
))
1358 prognum
= getprognum(argv
[1]);
1359 if (argc
== 2) { /* Version number not known */
1361 * A call to version 0 should fail with a program/version
1362 * mismatch, and give us the range of versions supported.
1366 versnum
= getvers(argv
[2]);
1369 nconf
= getnetconfigent(netid
);
1371 errx(1, "could not find %s", netid
);
1372 client
= clnt_tp_create(argv
[0], prognum
, versnum
, nconf
);
1374 client
= clnt_create(argv
[0], prognum
, versnum
, "NETPATH");
1376 if (client
== NULL
) {
1377 clnt_pcreateerror("rpcinfo");
1382 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1383 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1385 /* Version number was known */
1386 if (pstatus(client
, prognum
, versnum
) < 0)
1388 CLNT_DESTROY(client
);
1393 /* Version number not known */
1394 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1395 clnt_geterr(client
, &rpcerr
);
1396 minvers
= rpcerr
.re_vers
.low
;
1397 maxvers
= rpcerr
.re_vers
.high
;
1398 } else if (rpc_stat
== RPC_SUCCESS
) {
1400 * Oh dear, it DOES support version 0.
1401 * Let's try version MAX_VERS.
1404 CLNT_CONTROL(client
, CLSET_VERS
, (char *)&versnum
);
1405 rpc_stat
= CLNT_CALL(client
, NULLPROC
,
1406 (xdrproc_t
) xdr_void
, NULL
,
1407 (xdrproc_t
) xdr_void
, NULL
, to
);
1408 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1409 clnt_geterr(client
, &rpcerr
);
1410 minvers
= rpcerr
.re_vers
.low
;
1411 maxvers
= rpcerr
.re_vers
.high
;
1412 } else if (rpc_stat
== RPC_SUCCESS
) {
1414 * It also supports version MAX_VERS.
1415 * Looks like we have a wise guy.
1416 * OK, we give them information on all
1417 * 4 billion versions they support...
1422 pstatus(client
, prognum
, MAX_VERS
);
1426 pstatus(client
, prognum
, (u_long
)0);
1429 for (versnum
= minvers
; versnum
<= maxvers
; versnum
++) {
1430 CLNT_CONTROL(client
, CLSET_VERS
, (char *)&versnum
);
1431 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1432 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1433 if (pstatus(client
, prognum
, versnum
) < 0)
1436 CLNT_DESTROY(client
);
1445 fprintf(stderr
, "usage: rpcinfo [-m | -s] [host]\n");
1447 fprintf(stderr
, " rpcinfo -p [host]\n");
1449 fprintf(stderr
, " rpcinfo -T netid host prognum [versnum]\n");
1450 fprintf(stderr
, " rpcinfo -l host prognum versnum\n");
1453 " rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
1456 " rpcinfo -a serv_address -T netid prognum [version]\n");
1457 fprintf(stderr
, " rpcinfo -b prognum versnum\n");
1458 fprintf(stderr
, " rpcinfo -d [-T netid] prognum versnum\n");
1463 getprognum(char *arg
)
1470 while (*tptr
&& isdigit(*tptr
++));
1471 if (*tptr
|| isalpha(*(tptr
- 1))) {
1472 rpc
= getrpcbyname(arg
);
1474 errx(1, "%s is unknown service", arg
);
1475 prognum
= rpc
->r_number
;
1477 prognum
= strtol(arg
, &strptr
, 10);
1478 if (strptr
== arg
|| *strptr
!= '\0')
1479 errx(1, "%s is illegal program number", arg
);
1490 vers
= (int) strtol(arg
, &strptr
, 10);
1491 if (strptr
== arg
|| *strptr
!= '\0')
1492 errx(1, "%s is illegal version number", arg
);
1497 * This routine should take a pointer to an "rpc_err" structure, rather than
1498 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
1499 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
1500 * As such, we have to keep the CLIENT structure around in order to print
1501 * a good error message.
1504 pstatus(CLIENT
*client
, u_long prog
, u_long vers
)
1506 struct rpc_err rpcerr
;
1508 clnt_geterr(client
, &rpcerr
);
1509 if (rpcerr
.re_status
!= RPC_SUCCESS
) {
1510 clnt_perror(client
, "rpcinfo");
1511 printf("program %lu version %lu is not available\n",
1515 printf("program %lu version %lu ready and waiting\n",
1522 clnt_rpcbind_create(char *host
, int rpcbversnum
, struct netbuf
**targaddr
)
1524 static char *tlist
[3] = {
1525 "circuit_n", "circuit_v", "datagram_v"
1528 struct netconfig
*nconf
;
1529 CLIENT
*clnt
= NULL
;
1532 rpc_createerr
.cf_stat
= RPC_SUCCESS
;
1533 for (i
= 0; i
< 3; i
++) {
1534 if ((handle
= __rpc_setconf(tlist
[i
])) == NULL
)
1536 while (clnt
== NULL
) {
1537 if ((nconf
= __rpc_getconf(handle
)) == NULL
) {
1538 if (rpc_createerr
.cf_stat
== RPC_SUCCESS
)
1539 rpc_createerr
.cf_stat
= RPC_UNKNOWNPROTO
;
1542 clnt
= getclnthandle(host
, nconf
, rpcbversnum
,
1547 __rpc_endconf(handle
);
1553 getclnthandle(char *host
, struct netconfig
*nconf
,
1554 u_long rpcbversnum
, struct netbuf
**targaddr
)
1557 struct addrinfo hints
, *res
;
1558 CLIENT
*client
= NULL
;
1560 /* Get the address of the rpcbind */
1561 memset(&hints
, 0, sizeof hints
);
1562 if (getaddrinfo(host
, "rpcbind", &hints
, &res
) != 0) {
1563 rpc_createerr
.cf_stat
= RPC_N2AXLATEFAILURE
;
1566 addr
.len
= addr
.maxlen
= res
->ai_addrlen
;
1567 addr
.buf
= res
->ai_addr
;
1568 client
= clnt_tli_create(RPC_ANYFD
, nconf
, &addr
, RPCBPROG
,
1571 if (targaddr
!= NULL
) {
1573 (struct netbuf
*)malloc(sizeof (struct netbuf
));
1574 if (*targaddr
!= NULL
) {
1575 (*targaddr
)->maxlen
= addr
.maxlen
;
1576 (*targaddr
)->len
= addr
.len
;
1577 (*targaddr
)->buf
= (char *)malloc(addr
.len
);
1578 if ((*targaddr
)->buf
!= NULL
) {
1579 memcpy((*targaddr
)->buf
, addr
.buf
,
1585 if (rpc_createerr
.cf_stat
== RPC_TLIERROR
) {
1587 * Assume that the other system is dead; this is a
1588 * better error to display to the user.
1590 rpc_createerr
.cf_stat
= RPC_RPCBFAILURE
;
1591 rpc_createerr
.cf_error
.re_status
= RPC_FAILED
;
1599 print_rmtcallstat(int rtype
, rpcb_stat
*infp
)
1601 rpcbs_rmtcalllist_ptr pr
;
1604 if (rtype
== RPCBVERS_4_STAT
)
1606 "prog\t\tvers\tproc\tnetid\tindirect success failure\n");
1608 printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
1609 for (pr
= infp
->rmtinfo
; pr
; pr
= pr
->next
) {
1610 rpc
= getrpcbynumber(pr
->prog
);
1612 printf("%-16s", rpc
->r_name
);
1614 printf("%-16d", pr
->prog
);
1615 printf("%d\t%d\t%s\t",
1616 pr
->vers
, pr
->proc
, pr
->netid
);
1617 if (rtype
== RPCBVERS_4_STAT
)
1618 printf("%d\t ", pr
->indirect
);
1619 printf("%d\t%d\n", pr
->success
, pr
->failure
);
1624 print_getaddrstat(int rtype
, rpcb_stat
*infp
)
1626 rpcbs_addrlist_ptr al
;
1629 printf("prog\t\tvers\tnetid\t success\tfailure\n");
1630 for (al
= infp
->addrinfo
; al
; al
= al
->next
) {
1631 rpc
= getrpcbynumber(al
->prog
);
1633 printf("%-16s", rpc
->r_name
);
1635 printf("%-16d", al
->prog
);
1636 printf("%d\t%s\t %-12d\t%d\n",
1637 al
->vers
, al
->netid
,
1638 al
->success
, al
->failure
);
1645 static char space_array
[] = /* 64 spaces */
1648 if (howmany
<= 0 || howmany
> sizeof (space_array
)) {
1651 return (&space_array
[sizeof (space_array
) - howmany
- 1]);