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, MERCHANTABILITY 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 $
36 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
40 * rpcinfo: ping a particular rpc program
41 * or dump the the registered programs on the remote machine.
45 * We are for now defining PORTMAP here. It doesnt even compile
46 * unless it is defined.
53 * If PORTMAP is defined, rpcinfo will talk to both portmapper and
54 * rpcbind programs; else it talks only to rpcbind. In the latter case
55 * all the portmapper specific options such as -u, -t, -p become void.
57 #include <sys/types.h>
58 #include <sys/param.h>
59 #include <sys/socket.h>
63 #include <rpc/rpcb_prot.h>
64 #include <rpc/rpcent.h>
65 #include <rpc/nettype.h>
66 #include <rpc/rpc_com.h>
73 #ifdef PORTMAP /* Support for version 2 portmapper */
74 #include <netinet/in.h>
76 #include <arpa/inet.h>
77 #include <rpc/pmap_prot.h>
78 #include <rpc/pmap_clnt.h>
81 #define MAXHOSTLEN 256
82 #define MIN_VERS ((u_long) 0)
83 #define MAX_VERS ((u_long) 4294967295UL)
84 #define UNKNOWN "unknown"
87 * Functions to be performed.
89 #define NONE 0 /* no function */
90 #define PMAPDUMP 1 /* dump portmapper registrations */
91 #define TCPPING 2 /* ping TCP service */
92 #define UDPPING 3 /* ping UDP service */
93 #define BROADCAST 4 /* ping broadcast service */
94 #define DELETES 5 /* delete registration for the service */
95 #define ADDRPING 6 /* pings at the given address */
96 #define PROGPING 7 /* pings a program on a given host */
97 #define RPCBDUMP 8 /* dump rpcbind registrations */
98 #define RPCBDUMP_SHORT 9 /* dump rpcbind registrations - short version */
99 #define RPCBADDRLIST 10 /* dump addr list about one prog */
100 #define RPCBGETSTAT 11 /* Get statistics */
104 struct netidlist
*next
;
109 struct verslist
*next
;
112 struct rpcbdump_short
{
114 struct verslist
*vlist
;
115 struct netidlist
*nlist
;
116 struct rpcbdump_short
*next
;
123 static void ip_ping(u_short
, char *, int, char **);
124 static CLIENT
*clnt_com_create(struct sockaddr_in
*, u_long
, u_long
, int *,
126 static void pmapdump(int, char **);
127 static void get_inet_address(struct sockaddr_in
*, char *);
130 static bool_t
reply_proc(void *, struct netbuf
*, struct netconfig
*);
131 static void brdcst(int, char **);
132 static void addrping(char *, char *, int, char **);
133 static void progping(char *, int, char **);
134 static CLIENT
*clnt_addr_create(char *, struct netconfig
*, u_long
, u_long
);
135 static CLIENT
*clnt_rpcbind_create(char *, int, struct netbuf
**);
136 static CLIENT
*getclnthandle(char *, struct netconfig
*, u_long
,
138 static CLIENT
*local_rpcb(u_long
, u_long
);
139 static int pstatus(CLIENT
*, u_long
, u_long
);
140 static void rpcbdump(int, char *, int, char **);
141 static void rpcbgetstat(int, char **);
142 static void rpcbaddrlist(char *, int, char **);
143 static void deletereg(char *, int, char **);
144 static void print_rmtcallstat(int, rpcb_stat
*);
145 static void print_getaddrstat(int, rpcb_stat
*);
146 static void usage(void);
147 static u_long
getprognum(char *);
148 static u_long
getvers(char *);
149 static char *spaces(int);
150 static bool_t
add_version(struct rpcbdump_short
*, u_long
);
151 static bool_t
add_netid(struct rpcbdump_short
*, char *);
154 main(int argc
, char **argv
)
160 char *address
= NULL
;
169 while ((c
= getopt(argc
, argv
, "a:bdlmn:pstT:u")) != -1) {
171 while ((c
= getopt(argc
, argv
, "a:bdlmn:sT:")) != -1) {
176 if (function
!= NONE
)
183 if (function
!= NONE
)
190 if (function
!= NONE
)
197 portnum
= (u_short
) strtol(optarg
, &strptr
, 10);
198 if (strptr
== optarg
|| *strptr
!= '\0')
199 errx(1, "%s is illegal port number", optarg
);
204 if (function
!= NONE
)
210 if (function
!= NONE
)
213 function
= BROADCAST
;
217 if (function
!= NONE
)
224 if (function
!= NONE
)
227 function
= RPCBADDRLIST
;
231 if (function
!= NONE
)
234 function
= RPCBGETSTAT
;
238 if (function
!= NONE
)
241 function
= RPCBDUMP_SHORT
;
253 if (errflg
|| ((function
== ADDRPING
) && !netid
))
256 if (function
== NONE
) {
257 if (argc
- optind
> 1)
268 pmapdump(argc
- optind
, argv
+ optind
);
272 ip_ping(portnum
, "udp", argc
- optind
, argv
+ optind
);
276 ip_ping(portnum
, "tcp", argc
- optind
, argv
+ optind
);
280 brdcst(argc
- optind
, argv
+ optind
);
283 deletereg(netid
, argc
- optind
, argv
+ optind
);
286 addrping(address
, netid
, argc
- optind
, argv
+ optind
);
289 progping(netid
, argc
- optind
, argv
+ optind
);
293 rpcbdump(function
, netid
, argc
- optind
, argv
+ optind
);
296 rpcbgetstat(argc
- optind
, argv
+ optind
);
299 rpcbaddrlist(netid
, argc
- optind
, argv
+ optind
);
306 local_rpcb(u_long prog
, u_long vers
)
309 struct netconfig
*nconf
;
312 localhandle
= setnetconfig();
313 while ((nconf
= getnetconfig(localhandle
)) != NULL
) {
314 if (nconf
->nc_protofmly
!= NULL
&&
315 strcmp(nconf
->nc_protofmly
, NC_LOOPBACK
) == 0)
319 warnx("getnetconfig: %s", nc_sperror());
323 clnt
= clnt_tp_create(NULL
, prog
, vers
, nconf
);
324 endnetconfig(localhandle
);
330 clnt_com_create(struct sockaddr_in
*addr
, u_long prog
, u_long vers
,
331 int *fdp
, char *trans
)
335 if (strcmp(trans
, "tcp") == 0) {
336 clnt
= clnttcp_create(addr
, prog
, vers
, fdp
, 0, 0);
342 clnt
= clntudp_create(addr
, prog
, vers
, to
, fdp
);
345 clnt_pcreateerror("rpcinfo");
346 if (vers
== MIN_VERS
)
347 printf("program %lu is not available\n", prog
);
349 printf("program %lu version %lu is not available\n",
357 * If portnum is 0, then go and get the address from portmapper, which happens
358 * transparently through clnt*_create(); If version number is not given, it
359 * tries to find out the version number by making a call to version 0 and if
360 * that fails, it obtains the high order and the low order version number. If
361 * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
364 ip_ping(u_short portnum
, char *trans
, int argc
, char **argv
)
369 struct sockaddr_in addr
;
370 enum clnt_stat rpc_stat
;
371 u_long prognum
, vers
, minvers
, maxvers
;
372 struct rpc_err rpcerr
;
375 if (argc
< 2 || argc
> 3)
379 prognum
= getprognum(argv
[1]);
380 get_inet_address(&addr
, argv
[0]);
381 if (argc
== 2) { /* Version number not known */
383 * A call to version 0 should fail with a program/version
384 * mismatch, and give us the range of versions supported.
388 vers
= getvers(argv
[2]);
390 addr
.sin_port
= htons(portnum
);
391 client
= clnt_com_create(&addr
, prognum
, vers
, &fd
, trans
);
392 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
393 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
395 /* Version number was known */
396 if (pstatus(client
, prognum
, vers
) < 0)
398 CLNT_DESTROY(client
);
401 /* Version number not known */
402 CLNT_CONTROL(client
, CLSET_FD_NCLOSE
, NULL
);
403 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
404 clnt_geterr(client
, &rpcerr
);
405 minvers
= rpcerr
.re_vers
.low
;
406 maxvers
= rpcerr
.re_vers
.high
;
407 } else if (rpc_stat
== RPC_SUCCESS
) {
409 * Oh dear, it DOES support version 0.
410 * Let's try version MAX_VERS.
412 CLNT_DESTROY(client
);
413 addr
.sin_port
= htons(portnum
);
414 client
= clnt_com_create(&addr
, prognum
, MAX_VERS
, &fd
, trans
);
415 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
416 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
417 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
418 clnt_geterr(client
, &rpcerr
);
419 minvers
= rpcerr
.re_vers
.low
;
420 maxvers
= rpcerr
.re_vers
.high
;
421 } else if (rpc_stat
== RPC_SUCCESS
) {
423 * It also supports version MAX_VERS.
424 * Looks like we have a wise guy.
425 * OK, we give them information on all
426 * 4 billion versions they support...
431 pstatus(client
, prognum
, MAX_VERS
);
435 pstatus(client
, prognum
, (u_long
)0);
438 CLNT_DESTROY(client
);
439 for (vers
= minvers
; vers
<= maxvers
; vers
++) {
440 addr
.sin_port
= htons(portnum
);
441 client
= clnt_com_create(&addr
, prognum
, vers
, &fd
, trans
);
442 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
443 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
444 if (pstatus(client
, prognum
, vers
) < 0)
446 CLNT_DESTROY(client
);
455 * Dump all the portmapper registerations
458 pmapdump(int argc
, char **argv
)
460 struct sockaddr_in server_addr
;
461 struct pmaplist
*head
= NULL
;
462 int socket
= RPC_ANYSOCK
;
463 struct timeval minutetimeout
;
466 enum clnt_stat clnt_st
;
474 get_inet_address(&server_addr
, host
);
475 server_addr
.sin_port
= htons(PMAPPORT
);
476 client
= clnttcp_create(&server_addr
, PMAPPROG
, PMAPVERS
,
479 client
= local_rpcb(PMAPPROG
, PMAPVERS
);
481 if (client
== NULL
) {
482 if (rpc_createerr
.cf_stat
== RPC_TLIERROR
) {
484 * "Misc. TLI error" is not too helpful. Most likely
485 * the connection to the remote server timed out, so
486 * this error is at least less perplexing.
488 rpc_createerr
.cf_stat
= RPC_PMAPFAILURE
;
489 rpc_createerr
.cf_error
.re_status
= RPC_FAILED
;
491 clnt_pcreateerror("rpcinfo: can't contact portmapper");
495 minutetimeout
.tv_sec
= 60;
496 minutetimeout
.tv_usec
= 0;
498 clnt_st
= CLNT_CALL(client
, PMAPPROC_DUMP
, (xdrproc_t
) xdr_void
,
499 NULL
, (xdrproc_t
) xdr_pmaplist_ptr
, (char *)&head
,
501 if (clnt_st
!= RPC_SUCCESS
) {
502 if ((clnt_st
== RPC_PROGVERSMISMATCH
) ||
503 (clnt_st
== RPC_PROGUNAVAIL
)) {
504 CLNT_GETERR(client
, &err
);
505 if (err
.re_vers
.low
> PMAPVERS
)
507 "%s does not support portmapper. Try rpcinfo %s instead",
511 clnt_perror(client
, "rpcinfo: can't contact portmapper");
515 printf("No remote programs registered.\n");
517 printf(" program vers proto port service\n");
518 for (; head
!= NULL
; head
= head
->pml_next
) {
520 head
->pml_map
.pm_prog
,
521 head
->pml_map
.pm_vers
);
522 if (head
->pml_map
.pm_prot
== IPPROTO_UDP
)
523 printf("%6s", "udp");
524 else if (head
->pml_map
.pm_prot
== IPPROTO_TCP
)
525 printf("%6s", "tcp");
526 else if (head
->pml_map
.pm_prot
== IPPROTO_ST
)
527 printf("%6s", "local");
529 printf("%6ld", head
->pml_map
.pm_prot
);
530 printf("%7ld", head
->pml_map
.pm_port
);
531 rpc
= getrpcbynumber(head
->pml_map
.pm_prog
);
533 printf(" %s\n", rpc
->r_name
);
541 get_inet_address(struct sockaddr_in
*addr
, char *host
)
543 struct netconfig
*nconf
;
544 struct addrinfo hints
, *res
;
547 memset((char *)addr
, 0, sizeof (*addr
));
548 addr
->sin_addr
.s_addr
= inet_addr(host
);
549 if (addr
->sin_addr
.s_addr
== -1 || addr
->sin_addr
.s_addr
== 0) {
550 if ((nconf
= __rpc_getconfip("udp")) == NULL
&&
551 (nconf
= __rpc_getconfip("tcp")) == NULL
)
552 errx(1, "couldn't find a suitable transport");
554 memset(&hints
, 0, sizeof hints
);
555 hints
.ai_family
= AF_INET
;
556 if ((error
= getaddrinfo(host
, "rpcbind", &hints
, &res
))
558 errx(1, "%s: %s", host
, gai_strerror(error
));
560 memcpy(addr
, res
->ai_addr
, res
->ai_addrlen
);
563 freenetconfigent(nconf
);
566 addr
->sin_family
= AF_INET
;
572 * reply_proc collects replies from the broadcast.
573 * to get a unique list of responses the output of rpcinfo should
574 * be piped through sort(1) and then uniq(1).
579 reply_proc(void *res
, struct netbuf
*who
, struct netconfig
*nconf
)
580 /* void *res; Nothing comes back */
581 /* struct netbuf *who; Who sent us the reply */
582 /* struct netconfig *nconf; On which transport the reply came */
585 char hostbuf
[NI_MAXHOST
];
587 struct sockaddr
*sa
= (struct sockaddr
*)who
->buf
;
589 if (getnameinfo(sa
, sa
->sa_len
, hostbuf
, NI_MAXHOST
, NULL
, 0, 0)) {
594 if (!(uaddr
= taddr2uaddr(nconf
, who
))) {
597 printf("%s\t%s\n", uaddr
, hostname
);
598 if (strcmp(uaddr
, UNKNOWN
))
604 brdcst(int argc
, char **argv
)
606 enum clnt_stat rpc_stat
;
607 u_long prognum
, vers
;
611 prognum
= getprognum(argv
[0]);
612 vers
= getvers(argv
[1]);
613 rpc_stat
= rpc_broadcast(prognum
, vers
, NULLPROC
,
614 (xdrproc_t
) xdr_void
, NULL
, (xdrproc_t
) xdr_void
,
615 NULL
, (resultproc_t
) reply_proc
, NULL
);
616 if ((rpc_stat
!= RPC_SUCCESS
) && (rpc_stat
!= RPC_TIMEDOUT
))
617 errx(1, "broadcast failed: %s", clnt_sperrno(rpc_stat
));
622 add_version(struct rpcbdump_short
*rs
, u_long vers
)
626 for (vl
= rs
->vlist
; vl
; vl
= vl
->next
)
627 if (vl
->vers
== vers
)
631 vl
= (struct verslist
*)malloc(sizeof (struct verslist
));
635 vl
->next
= rs
->vlist
;
641 add_netid(struct rpcbdump_short
*rs
, char *netid
)
643 struct netidlist
*nl
;
645 for (nl
= rs
->nlist
; nl
; nl
= nl
->next
)
646 if (strcmp(nl
->netid
, netid
) == 0)
650 nl
= (struct netidlist
*)malloc(sizeof (struct netidlist
));
654 nl
->next
= rs
->nlist
;
660 rpcbdump(int dumptype
, char *netid
, int argc
, char **argv
)
662 rpcblist_ptr head
= NULL
;
663 struct timeval minutetimeout
;
667 struct netidlist
*nl
;
669 struct rpcbdump_short
*rs
, *rs_tail
;
671 enum clnt_stat clnt_st
;
673 struct rpcbdump_short
*rs_head
= NULL
;
680 client
= clnt_rpcbind_create(host
, RPCBVERS
, NULL
);
682 struct netconfig
*nconf
;
684 nconf
= getnetconfigent(netid
);
686 nc_perror("rpcinfo: invalid transport");
689 client
= getclnthandle(host
, nconf
, RPCBVERS
, NULL
);
691 freenetconfigent(nconf
);
694 client
= local_rpcb(PMAPPROG
, RPCBVERS
);
696 if (client
== NULL
) {
697 clnt_pcreateerror("rpcinfo: can't contact rpcbind");
701 minutetimeout
.tv_sec
= 60;
702 minutetimeout
.tv_usec
= 0;
703 clnt_st
= CLNT_CALL(client
, RPCBPROC_DUMP
, (xdrproc_t
) xdr_void
,
704 NULL
, (xdrproc_t
) xdr_rpcblist_ptr
, (char *) &head
,
706 if (clnt_st
!= RPC_SUCCESS
) {
707 if ((clnt_st
== RPC_PROGVERSMISMATCH
) ||
708 (clnt_st
== RPC_PROGUNAVAIL
)) {
711 CLNT_GETERR(client
, &err
);
712 if (err
.re_vers
.low
== RPCBVERS4
) {
714 clnt_control(client
, CLSET_VERS
, (char *)&vers
);
715 clnt_st
= CLNT_CALL(client
, RPCBPROC_DUMP
,
716 (xdrproc_t
) xdr_void
, NULL
,
717 (xdrproc_t
) xdr_rpcblist_ptr
, (char *) &head
,
719 if (clnt_st
!= RPC_SUCCESS
)
722 if (err
.re_vers
.high
== PMAPVERS
) {
724 struct pmaplist
*pmaphead
= NULL
;
725 rpcblist_ptr list
, prev
;
728 clnt_control(client
, CLSET_VERS
, (char *)&vers
);
729 clnt_st
= CLNT_CALL(client
, PMAPPROC_DUMP
,
730 (xdrproc_t
) xdr_void
, NULL
,
731 (xdrproc_t
) xdr_pmaplist_ptr
,
732 (char *)&pmaphead
, minutetimeout
);
733 if (clnt_st
!= RPC_SUCCESS
)
736 * convert to rpcblist_ptr format
738 for (head
= NULL
; pmaphead
!= NULL
;
739 pmaphead
= pmaphead
->pml_next
) {
740 list
= (rpcblist
*)malloc(sizeof (rpcblist
));
746 prev
->rpcb_next
= (rpcblist_ptr
) list
;
748 list
->rpcb_next
= NULL
;
749 list
->rpcb_map
.r_prog
= pmaphead
->pml_map
.pm_prog
;
750 list
->rpcb_map
.r_vers
= pmaphead
->pml_map
.pm_vers
;
751 if (pmaphead
->pml_map
.pm_prot
== IPPROTO_UDP
)
752 list
->rpcb_map
.r_netid
= "udp";
753 else if (pmaphead
->pml_map
.pm_prot
== IPPROTO_TCP
)
754 list
->rpcb_map
.r_netid
= "tcp";
756 #define MAXLONG_AS_STRING "2147483648"
757 list
->rpcb_map
.r_netid
=
758 malloc(strlen(MAXLONG_AS_STRING
) + 1);
759 if (list
->rpcb_map
.r_netid
== NULL
)
761 sprintf(list
->rpcb_map
.r_netid
, "%6ld",
762 pmaphead
->pml_map
.pm_prot
);
764 list
->rpcb_map
.r_owner
= UNKNOWN
;
765 low
= pmaphead
->pml_map
.pm_port
& 0xff;
766 high
= (pmaphead
->pml_map
.pm_port
>> 8) & 0xff;
767 list
->rpcb_map
.r_addr
= strdup("0.0.0.0.XXX.XXX");
768 sprintf(&list
->rpcb_map
.r_addr
[8], "%d.%d",
774 } else { /* any other error */
776 clnt_perror(client
, "rpcinfo: can't contact rpcbind: ");
781 printf("No remote programs registered.\n");
782 } else if (dumptype
== RPCBDUMP
) {
784 " program version netid address service owner\n");
785 for (; head
!= NULL
; head
= head
->rpcb_next
) {
787 head
->rpcb_map
.r_prog
, head
->rpcb_map
.r_vers
);
788 printf("%-9s ", head
->rpcb_map
.r_netid
);
789 printf("%-22s", head
->rpcb_map
.r_addr
);
790 rpc
= getrpcbynumber(head
->rpcb_map
.r_prog
);
792 printf(" %-10s", rpc
->r_name
);
794 printf(" %-10s", "-");
795 printf(" %s\n", head
->rpcb_map
.r_owner
);
797 } else if (dumptype
== RPCBDUMP_SHORT
) {
798 for (; head
!= NULL
; head
= head
->rpcb_next
) {
799 for (rs
= rs_head
; rs
; rs
= rs
->next
)
800 if (head
->rpcb_map
.r_prog
== rs
->prog
)
803 rs
= (struct rpcbdump_short
*)
804 malloc(sizeof (struct rpcbdump_short
));
808 if (rs_head
== NULL
) {
815 rs
->prog
= head
->rpcb_map
.r_prog
;
816 rs
->owner
= head
->rpcb_map
.r_owner
;
820 if (add_version(rs
, head
->rpcb_map
.r_vers
) == FALSE
)
822 if (add_netid(rs
, head
->rpcb_map
.r_netid
) == FALSE
)
826 " program version(s) netid(s) service owner\n");
827 for (rs
= rs_head
; rs
; rs
= rs
->next
) {
830 printf("%10ld ", rs
->prog
);
831 for (vl
= rs
->vlist
; vl
; vl
= vl
->next
) {
832 sprintf(p
, "%d", vl
->vers
);
837 printf("%-10s", buf
);
839 for (nl
= rs
->nlist
; nl
; nl
= nl
->next
) {
840 strcat(buf
, nl
->netid
);
844 printf("%-32s", buf
);
845 rpc
= getrpcbynumber(rs
->prog
);
847 printf(" %-11s", rpc
->r_name
);
849 printf(" %-11s", "-");
850 printf(" %s\n", rs
->owner
);
853 clnt_destroy(client
);
855 error
: warnx("no memory");
859 static char nullstring
[] = "\000";
862 rpcbaddrlist(char *netid
, int argc
, char **argv
)
864 rpcb_entry_list_ptr head
= NULL
;
865 struct timeval minutetimeout
;
870 struct netbuf
*targaddr
;
876 client
= clnt_rpcbind_create(host
, RPCBVERS4
, &targaddr
);
878 struct netconfig
*nconf
;
880 nconf
= getnetconfigent(netid
);
882 nc_perror("rpcinfo: invalid transport");
885 client
= getclnthandle(host
, nconf
, RPCBVERS4
, &targaddr
);
887 freenetconfigent(nconf
);
889 if (client
== NULL
) {
890 clnt_pcreateerror("rpcinfo: can't contact rpcbind");
893 minutetimeout
.tv_sec
= 60;
894 minutetimeout
.tv_usec
= 0;
896 parms
.r_prog
= getprognum(argv
[1]);
897 parms
.r_vers
= getvers(argv
[2]);
898 parms
.r_netid
= client
->cl_netid
;
899 if (targaddr
== NULL
) {
900 parms
.r_addr
= nullstring
; /* for XDRing */
903 * We also send the remote system the address we
904 * used to contact it in case it can help it
905 * connect back with us
907 struct netconfig
*nconf
;
909 nconf
= getnetconfigent(client
->cl_netid
);
911 parms
.r_addr
= taddr2uaddr(nconf
, targaddr
);
912 if (parms
.r_addr
== NULL
)
913 parms
.r_addr
= nullstring
;
914 freenetconfigent(nconf
);
916 parms
.r_addr
= nullstring
; /* for XDRing */
921 parms
.r_owner
= nullstring
;
923 if (CLNT_CALL(client
, RPCBPROC_GETADDRLIST
, (xdrproc_t
) xdr_rpcb
,
924 (char *) &parms
, (xdrproc_t
) xdr_rpcb_entry_list_ptr
,
925 (char *) &head
, minutetimeout
) != RPC_SUCCESS
) {
926 clnt_perror(client
, "rpcinfo: can't contact rpcbind: ");
930 printf("No remote programs registered.\n");
933 " program vers tp_family/name/class address\t\t service\n");
934 for (; head
!= NULL
; head
= head
->rpcb_entry_next
) {
938 re
= &head
->rpcb_entry_map
;
940 parms
.r_prog
, parms
.r_vers
);
941 sprintf(buf
, "%s/%s/%s ",
942 re
->r_nc_protofmly
, re
->r_nc_proto
,
943 re
->r_nc_semantics
== NC_TPI_CLTS
? "clts" :
944 re
->r_nc_semantics
== NC_TPI_COTS
? "cots" :
946 printf("%-24s", buf
);
947 printf("%-24s", re
->r_maddr
);
948 rpc
= getrpcbynumber(parms
.r_prog
);
950 printf(" %-13s", rpc
->r_name
);
952 printf(" %-13s", "-");
956 clnt_destroy(client
);
964 rpcbgetstat(int argc
, char **argv
)
966 rpcb_stat_byvers inf
;
967 struct timeval minutetimeout
;
972 rpcbs_rmtcalllist
*pr
;
975 char fieldbuf
[MAXFIELD
];
977 char linebuf
[MAXLINE
];
980 "NULL", "SET", "UNSET", "GETPORT",
984 "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
988 "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
989 "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
996 client
= clnt_rpcbind_create(host
, RPCBVERS4
, NULL
);
998 client
= local_rpcb(PMAPPROG
, RPCBVERS4
);
999 if (client
== NULL
) {
1000 clnt_pcreateerror("rpcinfo: can't contact rpcbind");
1003 minutetimeout
.tv_sec
= 60;
1004 minutetimeout
.tv_usec
= 0;
1005 memset((char *)&inf
, 0, sizeof (rpcb_stat_byvers
));
1006 if (CLNT_CALL(client
, RPCBPROC_GETSTAT
, (xdrproc_t
) xdr_void
, NULL
,
1007 (xdrproc_t
) xdr_rpcb_stat_byvers
, (char *)&inf
, minutetimeout
)
1009 clnt_perror(client
, "rpcinfo: can't contact rpcbind: ");
1012 printf("PORTMAP (version 2) statistics\n");
1014 for (i
= 0; i
<= rpcb_highproc_2
; i
++) {
1018 sprintf(fieldbuf
, "%d/", inf
[RPCBVERS_2_STAT
].setinfo
);
1020 case PMAPPROC_UNSET
:
1021 sprintf(fieldbuf
, "%d/",
1022 inf
[RPCBVERS_2_STAT
].unsetinfo
);
1024 case PMAPPROC_GETPORT
:
1026 for (pa
= inf
[RPCBVERS_2_STAT
].addrinfo
; pa
;
1029 sprintf(fieldbuf
, "%d/", cnt
);
1031 case PMAPPROC_CALLIT
:
1033 for (pr
= inf
[RPCBVERS_2_STAT
].rmtinfo
; pr
;
1036 sprintf(fieldbuf
, "%d/", cnt
);
1038 default: break; /* For the remaining ones */
1040 cp
= &fieldbuf
[0] + strlen(fieldbuf
);
1041 sprintf(cp
, "%d", inf
[RPCBVERS_2_STAT
].info
[i
]);
1042 flen
= strlen(fieldbuf
);
1043 printf("%s%s", pmaphdr
[i
],
1044 spaces((TABSTOP
* (1 + flen
/ TABSTOP
))
1045 - strlen(pmaphdr
[i
])));
1046 sprintf(lp
, "%s%s", fieldbuf
,
1047 spaces(cnt
= ((TABSTOP
* (1 + flen
/ TABSTOP
))
1051 printf("\n%s\n\n", linebuf
);
1053 if (inf
[RPCBVERS_2_STAT
].info
[PMAPPROC_CALLIT
]) {
1054 printf("PMAP_RMTCALL call statistics\n");
1055 print_rmtcallstat(RPCBVERS_2_STAT
, &inf
[RPCBVERS_2_STAT
]);
1059 if (inf
[RPCBVERS_2_STAT
].info
[PMAPPROC_GETPORT
]) {
1060 printf("PMAP_GETPORT call statistics\n");
1061 print_getaddrstat(RPCBVERS_2_STAT
, &inf
[RPCBVERS_2_STAT
]);
1065 printf("RPCBIND (version 3) statistics\n");
1067 for (i
= 0; i
<= rpcb_highproc_3
; i
++) {
1071 sprintf(fieldbuf
, "%d/", inf
[RPCBVERS_3_STAT
].setinfo
);
1073 case RPCBPROC_UNSET
:
1074 sprintf(fieldbuf
, "%d/",
1075 inf
[RPCBVERS_3_STAT
].unsetinfo
);
1077 case RPCBPROC_GETADDR
:
1079 for (pa
= inf
[RPCBVERS_3_STAT
].addrinfo
; pa
;
1082 sprintf(fieldbuf
, "%d/", cnt
);
1084 case RPCBPROC_CALLIT
:
1086 for (pr
= inf
[RPCBVERS_3_STAT
].rmtinfo
; pr
;
1089 sprintf(fieldbuf
, "%d/", cnt
);
1091 default: break; /* For the remaining ones */
1093 cp
= &fieldbuf
[0] + strlen(fieldbuf
);
1094 sprintf(cp
, "%d", inf
[RPCBVERS_3_STAT
].info
[i
]);
1095 flen
= strlen(fieldbuf
);
1096 printf("%s%s", rpcb3hdr
[i
],
1097 spaces((TABSTOP
* (1 + flen
/ TABSTOP
))
1098 - strlen(rpcb3hdr
[i
])));
1099 sprintf(lp
, "%s%s", fieldbuf
,
1100 spaces(cnt
= ((TABSTOP
* (1 + flen
/ TABSTOP
))
1104 printf("\n%s\n\n", linebuf
);
1106 if (inf
[RPCBVERS_3_STAT
].info
[RPCBPROC_CALLIT
]) {
1107 printf("RPCB_RMTCALL (version 3) call statistics\n");
1108 print_rmtcallstat(RPCBVERS_3_STAT
, &inf
[RPCBVERS_3_STAT
]);
1112 if (inf
[RPCBVERS_3_STAT
].info
[RPCBPROC_GETADDR
]) {
1113 printf("RPCB_GETADDR (version 3) call statistics\n");
1114 print_getaddrstat(RPCBVERS_3_STAT
, &inf
[RPCBVERS_3_STAT
]);
1118 printf("RPCBIND (version 4) statistics\n");
1120 for (j
= 0; j
<= 9; j
+= 9) { /* Just two iterations for printing */
1122 for (i
= j
; i
<= MAX(8, rpcb_highproc_4
- 9 + j
); i
++) {
1126 sprintf(fieldbuf
, "%d/",
1127 inf
[RPCBVERS_4_STAT
].setinfo
);
1129 case RPCBPROC_UNSET
:
1130 sprintf(fieldbuf
, "%d/",
1131 inf
[RPCBVERS_4_STAT
].unsetinfo
);
1133 case RPCBPROC_GETADDR
:
1135 for (pa
= inf
[RPCBVERS_4_STAT
].addrinfo
; pa
;
1138 sprintf(fieldbuf
, "%d/", cnt
);
1140 case RPCBPROC_CALLIT
:
1142 for (pr
= inf
[RPCBVERS_4_STAT
].rmtinfo
; pr
;
1145 sprintf(fieldbuf
, "%d/", cnt
);
1147 default: break; /* For the remaining ones */
1149 cp
= &fieldbuf
[0] + strlen(fieldbuf
);
1151 * XXX: We also add RPCBPROC_GETADDRLIST queries to
1152 * RPCB_GETADDR because rpcbind includes the
1153 * RPCB_GETADDRLIST successes in RPCB_GETADDR.
1155 if (i
!= RPCBPROC_GETADDR
)
1156 sprintf(cp
, "%d", inf
[RPCBVERS_4_STAT
].info
[i
]);
1158 sprintf(cp
, "%d", inf
[RPCBVERS_4_STAT
].info
[i
] +
1159 inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_GETADDRLIST
]);
1160 flen
= strlen(fieldbuf
);
1161 printf("%s%s", rpcb4hdr
[i
],
1162 spaces((TABSTOP
* (1 + flen
/ TABSTOP
))
1163 - strlen(rpcb4hdr
[i
])));
1164 sprintf(lp
, "%s%s", fieldbuf
,
1165 spaces(cnt
= ((TABSTOP
* (1 + flen
/ TABSTOP
))
1169 printf("\n%s\n", linebuf
);
1172 if (inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_CALLIT
] ||
1173 inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_INDIRECT
]) {
1175 printf("RPCB_RMTCALL (version 4) call statistics\n");
1176 print_rmtcallstat(RPCBVERS_4_STAT
, &inf
[RPCBVERS_4_STAT
]);
1179 if (inf
[RPCBVERS_4_STAT
].info
[RPCBPROC_GETADDR
]) {
1181 printf("RPCB_GETADDR (version 4) call statistics\n");
1182 print_getaddrstat(RPCBVERS_4_STAT
, &inf
[RPCBVERS_4_STAT
]);
1184 clnt_destroy(client
);
1188 * Delete registeration for this (prog, vers, netid)
1191 deletereg(char *netid
, int argc
, char **argv
)
1193 struct netconfig
*nconf
= NULL
;
1198 nconf
= getnetconfigent(netid
);
1200 errx(1, "netid %s not supported", netid
);
1202 if ((rpcb_unset(getprognum(argv
[0]), getvers(argv
[1]), nconf
)) == 0)
1204 "could not delete registration for prog %s version %s",
1209 * Create and return a handle for the given nconf.
1210 * Exit if cannot create handle.
1213 clnt_addr_create(char *address
, struct netconfig
*nconf
,
1214 u_long prog
, u_long vers
)
1217 static struct netbuf
*nbuf
;
1218 static int fd
= RPC_ANYFD
;
1220 if (fd
== RPC_ANYFD
) {
1221 if ((fd
= __rpc_nconf2fd(nconf
)) == -1) {
1222 rpc_createerr
.cf_stat
= RPC_TLIERROR
;
1223 clnt_pcreateerror("rpcinfo");
1226 /* Convert the uaddr to taddr */
1227 nbuf
= uaddr2taddr(nconf
, address
);
1229 errx(1, "no address for client handle");
1231 client
= clnt_tli_create(fd
, nconf
, nbuf
, prog
, vers
, 0, 0);
1232 if (client
== NULL
) {
1233 clnt_pcreateerror("rpcinfo");
1240 * If the version number is given, ping that (prog, vers); else try to find
1241 * the version numbers supported for that prog and ping all the versions.
1242 * Remote rpcbind is not contacted for this service. The requests are
1243 * sent directly to the services themselves.
1246 addrping(char *address
, char *netid
, int argc
, char **argv
)
1250 enum clnt_stat rpc_stat
;
1251 u_long prognum
, versnum
, minvers
, maxvers
;
1252 struct rpc_err rpcerr
;
1254 struct netconfig
*nconf
;
1257 if (argc
< 1 || argc
> 2 || (netid
== NULL
))
1259 nconf
= getnetconfigent(netid
);
1261 errx(1, "could not find %s", netid
);
1264 prognum
= getprognum(argv
[0]);
1265 if (argc
== 1) { /* Version number not known */
1267 * A call to version 0 should fail with a program/version
1268 * mismatch, and give us the range of versions supported.
1272 versnum
= getvers(argv
[1]);
1274 client
= clnt_addr_create(address
, nconf
, prognum
, versnum
);
1275 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1276 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1278 /* Version number was known */
1279 if (pstatus(client
, prognum
, versnum
) < 0)
1281 CLNT_DESTROY(client
);
1286 /* Version number not known */
1287 CLNT_CONTROL(client
, CLSET_FD_NCLOSE
, NULL
);
1288 CLNT_CONTROL(client
, CLGET_FD
, (char *)&fd
);
1289 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1290 clnt_geterr(client
, &rpcerr
);
1291 minvers
= rpcerr
.re_vers
.low
;
1292 maxvers
= rpcerr
.re_vers
.high
;
1293 } else if (rpc_stat
== RPC_SUCCESS
) {
1295 * Oh dear, it DOES support version 0.
1296 * Let's try version MAX_VERS.
1298 CLNT_DESTROY(client
);
1299 client
= clnt_addr_create(address
, nconf
, prognum
, MAX_VERS
);
1300 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1301 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1302 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1303 clnt_geterr(client
, &rpcerr
);
1304 minvers
= rpcerr
.re_vers
.low
;
1305 maxvers
= rpcerr
.re_vers
.high
;
1306 } else if (rpc_stat
== RPC_SUCCESS
) {
1308 * It also supports version MAX_VERS.
1309 * Looks like we have a wise guy.
1310 * OK, we give them information on all
1311 * 4 billion versions they support...
1316 pstatus(client
, prognum
, MAX_VERS
);
1320 pstatus(client
, prognum
, (u_long
)0);
1323 CLNT_DESTROY(client
);
1324 for (versnum
= minvers
; versnum
<= maxvers
; versnum
++) {
1325 client
= clnt_addr_create(address
, nconf
, prognum
, versnum
);
1326 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1327 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1328 if (pstatus(client
, prognum
, versnum
) < 0)
1330 CLNT_DESTROY(client
);
1339 * If the version number is given, ping that (prog, vers); else try to find
1340 * the version numbers supported for that prog and ping all the versions.
1341 * Remote rpcbind is *contacted* for this service. The requests are
1342 * then sent directly to the services themselves.
1345 progping(char *netid
, int argc
, char **argv
)
1349 enum clnt_stat rpc_stat
;
1350 u_long prognum
, versnum
, minvers
, maxvers
;
1351 struct rpc_err rpcerr
;
1353 struct netconfig
*nconf
;
1355 if (argc
< 2 || argc
> 3 || (netid
== NULL
))
1357 prognum
= getprognum(argv
[1]);
1358 if (argc
== 2) { /* Version number not known */
1360 * A call to version 0 should fail with a program/version
1361 * mismatch, and give us the range of versions supported.
1365 versnum
= getvers(argv
[2]);
1368 nconf
= getnetconfigent(netid
);
1370 errx(1, "could not find %s", netid
);
1371 client
= clnt_tp_create(argv
[0], prognum
, versnum
, nconf
);
1373 client
= clnt_create(argv
[0], prognum
, versnum
, "NETPATH");
1375 if (client
== NULL
) {
1376 clnt_pcreateerror("rpcinfo");
1381 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1382 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1384 /* Version number was known */
1385 if (pstatus(client
, prognum
, versnum
) < 0)
1387 CLNT_DESTROY(client
);
1392 /* Version number not known */
1393 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1394 clnt_geterr(client
, &rpcerr
);
1395 minvers
= rpcerr
.re_vers
.low
;
1396 maxvers
= rpcerr
.re_vers
.high
;
1397 } else if (rpc_stat
== RPC_SUCCESS
) {
1399 * Oh dear, it DOES support version 0.
1400 * Let's try version MAX_VERS.
1403 CLNT_CONTROL(client
, CLSET_VERS
, (char *)&versnum
);
1404 rpc_stat
= CLNT_CALL(client
, NULLPROC
,
1405 (xdrproc_t
) xdr_void
, NULL
,
1406 (xdrproc_t
) xdr_void
, NULL
, to
);
1407 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
1408 clnt_geterr(client
, &rpcerr
);
1409 minvers
= rpcerr
.re_vers
.low
;
1410 maxvers
= rpcerr
.re_vers
.high
;
1411 } else if (rpc_stat
== RPC_SUCCESS
) {
1413 * It also supports version MAX_VERS.
1414 * Looks like we have a wise guy.
1415 * OK, we give them information on all
1416 * 4 billion versions they support...
1421 pstatus(client
, prognum
, MAX_VERS
);
1425 pstatus(client
, prognum
, (u_long
)0);
1428 for (versnum
= minvers
; versnum
<= maxvers
; versnum
++) {
1429 CLNT_CONTROL(client
, CLSET_VERS
, (char *)&versnum
);
1430 rpc_stat
= CLNT_CALL(client
, NULLPROC
, (xdrproc_t
) xdr_void
,
1431 NULL
, (xdrproc_t
) xdr_void
, NULL
, to
);
1432 if (pstatus(client
, prognum
, versnum
) < 0)
1435 CLNT_DESTROY(client
);
1444 fprintf(stderr
, "usage: rpcinfo [-m | -s] [host]\n");
1446 fprintf(stderr
, " rpcinfo -p [host]\n");
1448 fprintf(stderr
, " rpcinfo -T netid host prognum [versnum]\n");
1449 fprintf(stderr
, " rpcinfo -l host prognum versnum\n");
1452 " rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
1455 " rpcinfo -a serv_address -T netid prognum [version]\n");
1456 fprintf(stderr
, " rpcinfo -b prognum versnum\n");
1457 fprintf(stderr
, " rpcinfo -d [-T netid] prognum versnum\n");
1462 getprognum(char *arg
)
1469 while (*tptr
&& isdigit(*tptr
++));
1470 if (*tptr
|| isalpha(*(tptr
- 1))) {
1471 rpc
= getrpcbyname(arg
);
1473 errx(1, "%s is unknown service", arg
);
1474 prognum
= rpc
->r_number
;
1476 prognum
= strtol(arg
, &strptr
, 10);
1477 if (strptr
== arg
|| *strptr
!= '\0')
1478 errx(1, "%s is illegal program number", arg
);
1489 vers
= (int) strtol(arg
, &strptr
, 10);
1490 if (strptr
== arg
|| *strptr
!= '\0')
1491 errx(1, "%s is illegal version number", arg
);
1496 * This routine should take a pointer to an "rpc_err" structure, rather than
1497 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
1498 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
1499 * As such, we have to keep the CLIENT structure around in order to print
1500 * a good error message.
1503 pstatus(CLIENT
*client
, u_long prog
, u_long vers
)
1505 struct rpc_err rpcerr
;
1507 clnt_geterr(client
, &rpcerr
);
1508 if (rpcerr
.re_status
!= RPC_SUCCESS
) {
1509 clnt_perror(client
, "rpcinfo");
1510 printf("program %lu version %lu is not available\n",
1514 printf("program %lu version %lu ready and waiting\n",
1521 clnt_rpcbind_create(char *host
, int rpcbversnum
, struct netbuf
**targaddr
)
1523 static char *tlist
[3] = {
1524 "circuit_n", "circuit_v", "datagram_v"
1527 struct netconfig
*nconf
;
1528 CLIENT
*clnt
= NULL
;
1531 rpc_createerr
.cf_stat
= RPC_SUCCESS
;
1532 for (i
= 0; i
< 3; i
++) {
1533 if ((handle
= __rpc_setconf(tlist
[i
])) == NULL
)
1535 while (clnt
== NULL
) {
1536 if ((nconf
= __rpc_getconf(handle
)) == NULL
) {
1537 if (rpc_createerr
.cf_stat
== RPC_SUCCESS
)
1538 rpc_createerr
.cf_stat
= RPC_UNKNOWNPROTO
;
1541 clnt
= getclnthandle(host
, nconf
, rpcbversnum
,
1546 __rpc_endconf(handle
);
1552 getclnthandle(char *host
, struct netconfig
*nconf
,
1553 u_long rpcbversnum
, struct netbuf
**targaddr
)
1556 struct addrinfo hints
, *res
;
1557 CLIENT
*client
= NULL
;
1559 /* Get the address of the rpcbind */
1560 memset(&hints
, 0, sizeof hints
);
1561 if (getaddrinfo(host
, "rpcbind", &hints
, &res
) != 0) {
1562 rpc_createerr
.cf_stat
= RPC_N2AXLATEFAILURE
;
1565 addr
.len
= addr
.maxlen
= res
->ai_addrlen
;
1566 addr
.buf
= res
->ai_addr
;
1567 client
= clnt_tli_create(RPC_ANYFD
, nconf
, &addr
, RPCBPROG
,
1570 if (targaddr
!= NULL
) {
1572 (struct netbuf
*)malloc(sizeof (struct netbuf
));
1573 if (*targaddr
!= NULL
) {
1574 (*targaddr
)->maxlen
= addr
.maxlen
;
1575 (*targaddr
)->len
= addr
.len
;
1576 (*targaddr
)->buf
= (char *)malloc(addr
.len
);
1577 if ((*targaddr
)->buf
!= NULL
) {
1578 memcpy((*targaddr
)->buf
, addr
.buf
,
1584 if (rpc_createerr
.cf_stat
== RPC_TLIERROR
) {
1586 * Assume that the other system is dead; this is a
1587 * better error to display to the user.
1589 rpc_createerr
.cf_stat
= RPC_RPCBFAILURE
;
1590 rpc_createerr
.cf_error
.re_status
= RPC_FAILED
;
1598 print_rmtcallstat(int rtype
, rpcb_stat
*infp
)
1600 rpcbs_rmtcalllist_ptr pr
;
1603 if (rtype
== RPCBVERS_4_STAT
)
1605 "prog\t\tvers\tproc\tnetid\tindirect success failure\n");
1607 printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
1608 for (pr
= infp
->rmtinfo
; pr
; pr
= pr
->next
) {
1609 rpc
= getrpcbynumber(pr
->prog
);
1611 printf("%-16s", rpc
->r_name
);
1613 printf("%-16d", pr
->prog
);
1614 printf("%d\t%d\t%s\t",
1615 pr
->vers
, pr
->proc
, pr
->netid
);
1616 if (rtype
== RPCBVERS_4_STAT
)
1617 printf("%d\t ", pr
->indirect
);
1618 printf("%d\t%d\n", pr
->success
, pr
->failure
);
1623 print_getaddrstat(int rtype
, rpcb_stat
*infp
)
1625 rpcbs_addrlist_ptr al
;
1628 printf("prog\t\tvers\tnetid\t success\tfailure\n");
1629 for (al
= infp
->addrinfo
; al
; al
= al
->next
) {
1630 rpc
= getrpcbynumber(al
->prog
);
1632 printf("%-16s", rpc
->r_name
);
1634 printf("%-16d", al
->prog
);
1635 printf("%d\t%s\t %-12d\t%d\n",
1636 al
->vers
, al
->netid
,
1637 al
->success
, al
->failure
);
1644 static char space_array
[] = /* 64 spaces */
1647 if (howmany
<= 0 || howmany
> sizeof (space_array
)) {
1650 return (&space_array
[sizeof (space_array
) - howmany
- 1]);