174462Salfred/* $NetBSD: rpcinfo.c,v 1.15 2000/10/04 20:09:05 mjl Exp $ */ 21900Swollman 31900Swollman/* 41900Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 51900Swollman * unrestricted use provided that this legend is included on all tape 61900Swollman * media and as a part of the software program in whole or part. Users 71900Swollman * may copy or modify Sun RPC without charge, but are not authorized 81900Swollman * to license or distribute it to anyone else except as part of a product or 91900Swollman * program developed by the user. 108874Srgrimes * 111900Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 121900Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 131900Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 148874Srgrimes * 151900Swollman * Sun RPC is provided with no support and without any obligation on the 161900Swollman * part of Sun Microsystems, Inc. to assist in its use, correction, 171900Swollman * modification or enhancement. 188874Srgrimes * 191900Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 201900Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 211900Swollman * OR ANY PART THEREOF. 228874Srgrimes * 231900Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 241900Swollman * or profits or other special, indirect and consequential damages, even if 251900Swollman * Sun has been advised of the possibility of such damages. 268874Srgrimes * 271900Swollman * Sun Microsystems, Inc. 281900Swollman * 2550 Garcia Avenue 291900Swollman * Mountain View, California 94043 301900Swollman */ 311900Swollman 3274462Salfred/* 3374462Salfred * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. 3474462Salfred */ 3574462Salfred 3674462Salfred/* #ident "@(#)rpcinfo.c 1.18 93/07/05 SMI" */ 3774462Salfred 3874462Salfred#if 0 3974462Salfred#ifndef lint 4074462Salfredstatic char sccsid[] = "@(#)rpcinfo.c 1.16 89/04/05 Copyr 1986 Sun Micro"; 4174462Salfred#endif 4274462Salfred#endif 4374462Salfred 44119849Scharnier#include <sys/cdefs.h> 45119849Scharnier__FBSDID("$FreeBSD: stable/10/usr.bin/rpcinfo/rpcinfo.c 319256 2017-05-30 21:58:53Z asomers $"); 46119849Scharnier 4774462Salfred/* 4874462Salfred * rpcinfo: ping a particular rpc program 49218909Sbrucec * or dump the registered programs on the remote machine. 5074462Salfred */ 5174462Salfred 5274462Salfred/* 53228992Suqs * We are for now defining PORTMAP here. It doesn't even compile 5474462Salfred * unless it is defined. 5574462Salfred */ 5674462Salfred#ifndef PORTMAP 5774462Salfred#define PORTMAP 5874462Salfred#endif 5974462Salfred 6074462Salfred/* 6174462Salfred * If PORTMAP is defined, rpcinfo will talk to both portmapper and 6274462Salfred * rpcbind programs; else it talks only to rpcbind. In the latter case 6374462Salfred * all the portmapper specific options such as -u, -t, -p become void. 6474462Salfred */ 6574462Salfred#include <sys/types.h> 6674462Salfred#include <sys/param.h> 6774462Salfred#include <sys/socket.h> 6874462Salfred#include <sys/un.h> 6974462Salfred#include <rpc/rpc.h> 7074462Salfred#include <stdio.h> 7174462Salfred#include <rpc/rpcb_prot.h> 7274462Salfred#include <rpc/rpcent.h> 7374462Salfred#include <rpc/nettype.h> 7474462Salfred#include <rpc/rpc_com.h> 7574462Salfred#include <stdlib.h> 7674462Salfred#include <string.h> 7774462Salfred#include <unistd.h> 7827936Scharnier#include <err.h> 7927936Scharnier#include <ctype.h> 8074462Salfred 8174462Salfred#ifdef PORTMAP /* Support for version 2 portmapper */ 8274462Salfred#include <netinet/in.h> 831900Swollman#include <netdb.h> 8474462Salfred#include <arpa/inet.h> 851900Swollman#include <rpc/pmap_prot.h> 861900Swollman#include <rpc/pmap_clnt.h> 8774462Salfred#endif 881900Swollman 891900Swollman#define MAXHOSTLEN 256 901900Swollman#define MIN_VERS ((u_long) 0) 911900Swollman#define MAX_VERS ((u_long) 4294967295UL) 9274462Salfred#define UNKNOWN "unknown" 931900Swollman 941900Swollman/* 951900Swollman * Functions to be performed. 961900Swollman */ 971900Swollman#define NONE 0 /* no function */ 981900Swollman#define PMAPDUMP 1 /* dump portmapper registrations */ 991900Swollman#define TCPPING 2 /* ping TCP service */ 1001900Swollman#define UDPPING 3 /* ping UDP service */ 10174462Salfred#define BROADCAST 4 /* ping broadcast service */ 10274462Salfred#define DELETES 5 /* delete registration for the service */ 10374462Salfred#define ADDRPING 6 /* pings at the given address */ 10474462Salfred#define PROGPING 7 /* pings a program on a given host */ 10574462Salfred#define RPCBDUMP 8 /* dump rpcbind registrations */ 10674462Salfred#define RPCBDUMP_SHORT 9 /* dump rpcbind registrations - short version */ 10774462Salfred#define RPCBADDRLIST 10 /* dump addr list about one prog */ 10874462Salfred#define RPCBGETSTAT 11 /* Get statistics */ 1091900Swollman 11074462Salfredstruct netidlist { 11174462Salfred char *netid; 11274462Salfred struct netidlist *next; 11374462Salfred}; 11474462Salfred 11574462Salfredstruct verslist { 11674462Salfred int vers; 11774462Salfred struct verslist *next; 11874462Salfred}; 11974462Salfred 12074462Salfredstruct rpcbdump_short { 12174462Salfred u_long prog; 12274462Salfred struct verslist *vlist; 12374462Salfred struct netidlist *nlist; 12474462Salfred struct rpcbdump_short *next; 12574462Salfred char *owner; 12674462Salfred}; 12774462Salfred 12874462Salfred 12974462Salfred 13074462Salfred#ifdef PORTMAP 131221860Sdelphijstatic void ip_ping(u_short, const char *, int, char **); 13274462Salfredstatic CLIENT *clnt_com_create(struct sockaddr_in *, u_long, u_long, int *, 133221860Sdelphij const char *); 13474462Salfredstatic void pmapdump(int, char **); 13574462Salfredstatic void get_inet_address(struct sockaddr_in *, char *); 13674462Salfred#endif 13774462Salfred 13874462Salfredstatic bool_t reply_proc(void *, struct netbuf *, struct netconfig *); 13974462Salfredstatic void brdcst(int, char **); 14074462Salfredstatic void addrping(char *, char *, int, char **); 14174462Salfredstatic void progping(char *, int, char **); 14274462Salfredstatic CLIENT *clnt_addr_create(char *, struct netconfig *, u_long, u_long); 14374462Salfredstatic CLIENT *clnt_rpcbind_create(char *, int, struct netbuf **); 14474462Salfredstatic CLIENT *getclnthandle(char *, struct netconfig *, u_long, 14574462Salfred struct netbuf **); 14674462Salfredstatic CLIENT *local_rpcb(u_long, u_long); 14774462Salfredstatic int pstatus(CLIENT *, u_long, u_long); 14874462Salfredstatic void rpcbdump(int, char *, int, char **); 14974462Salfredstatic void rpcbgetstat(int, char **); 15074462Salfredstatic void rpcbaddrlist(char *, int, char **); 15174462Salfredstatic void deletereg(char *, int, char **); 15274462Salfredstatic void print_rmtcallstat(int, rpcb_stat *); 15374462Salfredstatic void print_getaddrstat(int, rpcb_stat *); 15474462Salfredstatic void usage(void); 15574462Salfredstatic u_long getprognum(char *); 15674462Salfredstatic u_long getvers(char *); 15774462Salfredstatic char *spaces(int); 15874462Salfredstatic bool_t add_version(struct rpcbdump_short *, u_long); 15974462Salfredstatic bool_t add_netid(struct rpcbdump_short *, char *); 16074462Salfred 1611900Swollmanint 16274462Salfredmain(int argc, char **argv) 1631900Swollman{ 1641900Swollman register int c; 1651900Swollman int errflg; 1661900Swollman int function; 16774462Salfred char *netid = NULL; 16874462Salfred char *address = NULL; 16974462Salfred#ifdef PORTMAP 17074462Salfred char *strptr; 17174462Salfred u_short portnum = 0; 17274462Salfred#endif 1731900Swollman 1741900Swollman function = NONE; 1751900Swollman errflg = 0; 17674462Salfred#ifdef PORTMAP 17774462Salfred while ((c = getopt(argc, argv, "a:bdlmn:pstT:u")) != -1) { 17874462Salfred#else 17974462Salfred while ((c = getopt(argc, argv, "a:bdlmn:sT:")) != -1) { 18074462Salfred#endif 1811900Swollman switch (c) { 18274462Salfred#ifdef PORTMAP 1831900Swollman case 'p': 1841900Swollman if (function != NONE) 1851900Swollman errflg = 1; 1861900Swollman else 1871900Swollman function = PMAPDUMP; 1881900Swollman break; 1891900Swollman 1901900Swollman case 't': 1911900Swollman if (function != NONE) 1921900Swollman errflg = 1; 1931900Swollman else 1941900Swollman function = TCPPING; 1951900Swollman break; 1961900Swollman 1971900Swollman case 'u': 1981900Swollman if (function != NONE) 1991900Swollman errflg = 1; 2001900Swollman else 2011900Swollman function = UDPPING; 2021900Swollman break; 2031900Swollman 20474462Salfred case 'n': 20574462Salfred portnum = (u_short) strtol(optarg, &strptr, 10); 206119849Scharnier if (strptr == optarg || *strptr != '\0') 207119849Scharnier errx(1, "%s is illegal port number", optarg); 20874462Salfred break; 20974462Salfred#endif 21074462Salfred case 'a': 21174462Salfred address = optarg; 21274462Salfred if (function != NONE) 21374462Salfred errflg = 1; 21474462Salfred else 21574462Salfred function = ADDRPING; 21674462Salfred break; 2171900Swollman case 'b': 2181900Swollman if (function != NONE) 2191900Swollman errflg = 1; 2201900Swollman else 22174462Salfred function = BROADCAST; 2221900Swollman break; 2231900Swollman 2241900Swollman case 'd': 2251900Swollman if (function != NONE) 2261900Swollman errflg = 1; 2271900Swollman else 2281900Swollman function = DELETES; 2291900Swollman break; 2301900Swollman 23174462Salfred case 'l': 23274462Salfred if (function != NONE) 23374462Salfred errflg = 1; 23474462Salfred else 23574462Salfred function = RPCBADDRLIST; 23674462Salfred break; 23774462Salfred 23874462Salfred case 'm': 23974462Salfred if (function != NONE) 24074462Salfred errflg = 1; 24174462Salfred else 24274462Salfred function = RPCBGETSTAT; 24374462Salfred break; 24474462Salfred 24574462Salfred case 's': 24674462Salfred if (function != NONE) 24774462Salfred errflg = 1; 24874462Salfred else 24974462Salfred function = RPCBDUMP_SHORT; 25074462Salfred break; 25174462Salfred 25274462Salfred case 'T': 25374462Salfred netid = optarg; 25474462Salfred break; 2551900Swollman case '?': 2561900Swollman errflg = 1; 25774462Salfred break; 2581900Swollman } 2591900Swollman } 2601900Swollman 261119849Scharnier if (errflg || ((function == ADDRPING) && !netid)) 2621900Swollman usage(); 2631900Swollman 26474462Salfred if (function == NONE) { 26574462Salfred if (argc - optind > 1) 26674462Salfred function = PROGPING; 26774462Salfred else 26874462Salfred function = RPCBDUMP; 26974462Salfred } 27074462Salfred 2711900Swollman switch (function) { 27274462Salfred#ifdef PORTMAP 2731900Swollman case PMAPDUMP: 274119849Scharnier if (portnum != 0) 2751900Swollman usage(); 2761900Swollman pmapdump(argc - optind, argv + optind); 2771900Swollman break; 2781900Swollman 2791900Swollman case UDPPING: 28074462Salfred ip_ping(portnum, "udp", argc - optind, argv + optind); 2811900Swollman break; 2821900Swollman 2831900Swollman case TCPPING: 28474462Salfred ip_ping(portnum, "tcp", argc - optind, argv + optind); 2851900Swollman break; 28674462Salfred#endif 28774462Salfred case BROADCAST: 2881900Swollman brdcst(argc - optind, argv + optind); 2891900Swollman break; 2901900Swollman case DELETES: 29174462Salfred deletereg(netid, argc - optind, argv + optind); 2921900Swollman break; 29374462Salfred case ADDRPING: 29474462Salfred addrping(address, netid, argc - optind, argv + optind); 29574462Salfred break; 29674462Salfred case PROGPING: 29774462Salfred progping(netid, argc - optind, argv + optind); 29874462Salfred break; 29974462Salfred case RPCBDUMP: 30074462Salfred case RPCBDUMP_SHORT: 30174462Salfred rpcbdump(function, netid, argc - optind, argv + optind); 30274462Salfred break; 30374462Salfred case RPCBGETSTAT: 30474462Salfred rpcbgetstat(argc - optind, argv + optind); 30574462Salfred break; 30674462Salfred case RPCBADDRLIST: 30774462Salfred rpcbaddrlist(netid, argc - optind, argv + optind); 30874462Salfred break; 3091900Swollman } 3101900Swollman return (0); 3111900Swollman} 3128874Srgrimes 31374462Salfredstatic CLIENT * 31474462Salfredlocal_rpcb(u_long prog, u_long vers) 3151900Swollman{ 31690256Salfred void *localhandle; 31790256Salfred struct netconfig *nconf; 31890256Salfred CLIENT *clnt; 3198874Srgrimes 32090256Salfred localhandle = setnetconfig(); 32190256Salfred while ((nconf = getnetconfig(localhandle)) != NULL) { 32290256Salfred if (nconf->nc_protofmly != NULL && 32390256Salfred strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) 32490256Salfred break; 32590256Salfred } 32690256Salfred if (nconf == NULL) { 32790256Salfred warnx("getnetconfig: %s", nc_sperror()); 32890256Salfred return (NULL); 32990256Salfred } 33074462Salfred 33190256Salfred clnt = clnt_tp_create(NULL, prog, vers, nconf); 33290256Salfred endnetconfig(localhandle); 33390256Salfred return clnt; 33474462Salfred} 33574462Salfred 33674462Salfred#ifdef PORTMAP 33774462Salfredstatic CLIENT * 33874462Salfredclnt_com_create(struct sockaddr_in *addr, u_long prog, u_long vers, 339221860Sdelphij int *fdp, const char *trans) 34074462Salfred{ 34174462Salfred CLIENT *clnt; 34274462Salfred 34374462Salfred if (strcmp(trans, "tcp") == 0) { 34474462Salfred clnt = clnttcp_create(addr, prog, vers, fdp, 0, 0); 34574462Salfred } else { 34674462Salfred struct timeval to; 34774462Salfred 3481900Swollman to.tv_sec = 5; 3491900Swollman to.tv_usec = 0; 35074462Salfred clnt = clntudp_create(addr, prog, vers, to, fdp); 3511900Swollman } 35274462Salfred if (clnt == (CLIENT *)NULL) { 35374462Salfred clnt_pcreateerror("rpcinfo"); 35474462Salfred if (vers == MIN_VERS) 35574462Salfred printf("program %lu is not available\n", prog); 35674462Salfred else 3571900Swollman printf("program %lu version %lu is not available\n", 35874462Salfred prog, vers); 35974462Salfred exit(1); 3601900Swollman } 36174462Salfred return (clnt); 3621900Swollman} 3631900Swollman 36474462Salfred/* 36574462Salfred * If portnum is 0, then go and get the address from portmapper, which happens 36674462Salfred * transparently through clnt*_create(); If version number is not given, it 36774462Salfred * tries to find out the version number by making a call to version 0 and if 36874462Salfred * that fails, it obtains the high order and the low order version number. If 36974462Salfred * version 0 calls succeeds, it tries for MAXVERS call and repeats the same. 37074462Salfred */ 3711900Swollmanstatic void 372221860Sdelphijip_ping(u_short portnum, const char *trans, int argc, char **argv) 3731900Swollman{ 37474462Salfred CLIENT *client; 37574462Salfred int fd = RPC_ANYFD; 3761900Swollman struct timeval to; 3771900Swollman struct sockaddr_in addr; 3781900Swollman enum clnt_stat rpc_stat; 3791900Swollman u_long prognum, vers, minvers, maxvers; 3801900Swollman struct rpc_err rpcerr; 38174462Salfred int failure = 0; 3821900Swollman 383119849Scharnier if (argc < 2 || argc > 3) 3841900Swollman usage(); 38574462Salfred to.tv_sec = 10; 38674462Salfred to.tv_usec = 0; 3871900Swollman prognum = getprognum(argv[1]); 3881900Swollman get_inet_address(&addr, argv[0]); 38974462Salfred if (argc == 2) { /* Version number not known */ 3901900Swollman /* 3911900Swollman * A call to version 0 should fail with a program/version 3921900Swollman * mismatch, and give us the range of versions supported. 3931900Swollman */ 39474462Salfred vers = MIN_VERS; 39574462Salfred } else { 39674462Salfred vers = getvers(argv[2]); 39774462Salfred } 39874462Salfred addr.sin_port = htons(portnum); 39974462Salfred client = clnt_com_create(&addr, prognum, vers, &fd, trans); 40074462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 40174462Salfred (char *)NULL, (xdrproc_t) xdr_void, (char *)NULL, 40274462Salfred to); 40374462Salfred if (argc != 2) { 40474462Salfred /* Version number was known */ 40574462Salfred if (pstatus(client, prognum, vers) < 0) 40674462Salfred exit(1); 40774462Salfred (void) CLNT_DESTROY(client); 40874462Salfred return; 40974462Salfred } 41074462Salfred /* Version number not known */ 41174462Salfred (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL); 41274462Salfred if (rpc_stat == RPC_PROGVERSMISMATCH) { 41374462Salfred clnt_geterr(client, &rpcerr); 41474462Salfred minvers = rpcerr.re_vers.low; 41574462Salfred maxvers = rpcerr.re_vers.high; 41674462Salfred } else if (rpc_stat == RPC_SUCCESS) { 41774462Salfred /* 41874462Salfred * Oh dear, it DOES support version 0. 41974462Salfred * Let's try version MAX_VERS. 42074462Salfred */ 42174462Salfred (void) CLNT_DESTROY(client); 4221900Swollman addr.sin_port = htons(portnum); 42374462Salfred client = clnt_com_create(&addr, prognum, MAX_VERS, &fd, trans); 42474462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 42574462Salfred (char *)NULL, (xdrproc_t) xdr_void, 42674462Salfred (char *)NULL, to); 4271900Swollman if (rpc_stat == RPC_PROGVERSMISMATCH) { 4281900Swollman clnt_geterr(client, &rpcerr); 4291900Swollman minvers = rpcerr.re_vers.low; 4301900Swollman maxvers = rpcerr.re_vers.high; 4311900Swollman } else if (rpc_stat == RPC_SUCCESS) { 4321900Swollman /* 43374462Salfred * It also supports version MAX_VERS. 43474462Salfred * Looks like we have a wise guy. 43574462Salfred * OK, we give them information on all 43674462Salfred * 4 billion versions they support... 4371900Swollman */ 43874462Salfred minvers = 0; 43974462Salfred maxvers = MAX_VERS; 4401900Swollman } else { 44174462Salfred (void) pstatus(client, prognum, MAX_VERS); 4421900Swollman exit(1); 4431900Swollman } 44474462Salfred } else { 44574462Salfred (void) pstatus(client, prognum, (u_long)0); 44674462Salfred exit(1); 4471900Swollman } 44874462Salfred (void) CLNT_DESTROY(client); 44974462Salfred for (vers = minvers; vers <= maxvers; vers++) { 4501900Swollman addr.sin_port = htons(portnum); 45174462Salfred client = clnt_com_create(&addr, prognum, vers, &fd, trans); 45274462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 45374462Salfred (char *)NULL, (xdrproc_t) xdr_void, 45474462Salfred (char *)NULL, to); 4551900Swollman if (pstatus(client, prognum, vers) < 0) 45674462Salfred failure = 1; 45774462Salfred (void) CLNT_DESTROY(client); 4581900Swollman } 4591900Swollman if (failure) 4601900Swollman exit(1); 46174462Salfred (void) close(fd); 46274462Salfred return; 4631900Swollman} 4641900Swollman 4651900Swollman/* 46674462Salfred * Dump all the portmapper registerations 4671900Swollman */ 4681900Swollmanstatic void 46974462Salfredpmapdump(int argc, char **argv) 4701900Swollman{ 4711900Swollman struct sockaddr_in server_addr; 4721900Swollman struct pmaplist *head = NULL; 4731900Swollman int socket = RPC_ANYSOCK; 4741900Swollman struct timeval minutetimeout; 4751900Swollman register CLIENT *client; 4761900Swollman struct rpcent *rpc; 47774462Salfred enum clnt_stat clnt_st; 47874462Salfred struct rpc_err err; 479239373Skevlo char *host = NULL; 4808874Srgrimes 481119849Scharnier if (argc > 1) 4821900Swollman usage(); 48374462Salfred if (argc == 1) { 48474462Salfred host = argv[0]; 48574462Salfred get_inet_address(&server_addr, host); 48674462Salfred server_addr.sin_port = htons(PMAPPORT); 48774462Salfred client = clnttcp_create(&server_addr, PMAPPROG, PMAPVERS, 48874462Salfred &socket, 50, 500); 48974462Salfred } else 49074462Salfred client = local_rpcb(PMAPPROG, PMAPVERS); 49174462Salfred 49274462Salfred if (client == NULL) { 49374462Salfred if (rpc_createerr.cf_stat == RPC_TLIERROR) { 49474462Salfred /* 49574462Salfred * "Misc. TLI error" is not too helpful. Most likely 49674462Salfred * the connection to the remote server timed out, so 49774462Salfred * this error is at least less perplexing. 49874462Salfred */ 49974462Salfred rpc_createerr.cf_stat = RPC_PMAPFAILURE; 50074462Salfred rpc_createerr.cf_error.re_status = RPC_FAILED; 50174462Salfred } 50274462Salfred clnt_pcreateerror("rpcinfo: can't contact portmapper"); 50374462Salfred exit(1); 5041900Swollman } 50574462Salfred 5061900Swollman minutetimeout.tv_sec = 60; 5071900Swollman minutetimeout.tv_usec = 0; 50874462Salfred 50974462Salfred clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, 51074462Salfred NULL, (xdrproc_t) xdr_pmaplist_ptr, (char *)&head, 51174462Salfred minutetimeout); 51274462Salfred if (clnt_st != RPC_SUCCESS) { 51374462Salfred if ((clnt_st == RPC_PROGVERSMISMATCH) || 51474462Salfred (clnt_st == RPC_PROGUNAVAIL)) { 51574462Salfred CLNT_GETERR(client, &err); 516239373Skevlo if (err.re_vers.low > PMAPVERS) { 517239373Skevlo if (host) 518239373Skevlo warnx("%s does not support portmapper." 519239373Skevlo "Try rpcinfo %s instead", host, 520239373Skevlo host); 521239373Skevlo else 522239373Skevlo warnx("local host does not support " 523239373Skevlo "portmapper. Try 'rpcinfo' " 524239373Skevlo "instead"); 525239373Skevlo } 52674462Salfred exit(1); 52774462Salfred } 52874462Salfred clnt_perror(client, "rpcinfo: can't contact portmapper"); 5291900Swollman exit(1); 5301900Swollman } 5311900Swollman if (head == NULL) { 5321900Swollman printf("No remote programs registered.\n"); 5331900Swollman } else { 53474462Salfred printf(" program vers proto port service\n"); 5351900Swollman for (; head != NULL; head = head->pml_next) { 5361900Swollman printf("%10ld%5ld", 53774462Salfred head->pml_map.pm_prog, 53874462Salfred head->pml_map.pm_vers); 5391900Swollman if (head->pml_map.pm_prot == IPPROTO_UDP) 54074462Salfred printf("%6s", "udp"); 5411900Swollman else if (head->pml_map.pm_prot == IPPROTO_TCP) 5421900Swollman printf("%6s", "tcp"); 54374462Salfred else if (head->pml_map.pm_prot == IPPROTO_ST) 544107952Smbr printf("%6s", "local"); 5451900Swollman else 54674462Salfred printf("%6ld", head->pml_map.pm_prot); 54774462Salfred printf("%7ld", head->pml_map.pm_port); 5481900Swollman rpc = getrpcbynumber(head->pml_map.pm_prog); 5491900Swollman if (rpc) 5501900Swollman printf(" %s\n", rpc->r_name); 5511900Swollman else 5521900Swollman printf("\n"); 5531900Swollman } 5541900Swollman } 5551900Swollman} 5561900Swollman 55774462Salfredstatic void 55874462Salfredget_inet_address(struct sockaddr_in *addr, char *host) 55974462Salfred{ 56074462Salfred struct netconfig *nconf; 56174462Salfred struct addrinfo hints, *res; 56274462Salfred int error; 56374462Salfred 56474462Salfred (void) memset((char *)addr, 0, sizeof (*addr)); 56574462Salfred addr->sin_addr.s_addr = inet_addr(host); 56674462Salfred if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) { 56774462Salfred if ((nconf = __rpc_getconfip("udp")) == NULL && 568119849Scharnier (nconf = __rpc_getconfip("tcp")) == NULL) 569119849Scharnier errx(1, "couldn't find a suitable transport"); 570119849Scharnier else { 57174462Salfred memset(&hints, 0, sizeof hints); 57274462Salfred hints.ai_family = AF_INET; 57374462Salfred if ((error = getaddrinfo(host, "rpcbind", &hints, &res)) 574119849Scharnier != 0) 575119849Scharnier errx(1, "%s: %s", host, gai_strerror(error)); 576119849Scharnier else { 57774462Salfred memcpy(addr, res->ai_addr, res->ai_addrlen); 57874462Salfred freeaddrinfo(res); 57974462Salfred } 58074462Salfred (void) freenetconfigent(nconf); 58174462Salfred } 58274462Salfred } else { 58374462Salfred addr->sin_family = AF_INET; 58474462Salfred } 58574462Salfred} 58674462Salfred#endif /* PORTMAP */ 58774462Salfred 5888874Srgrimes/* 5898874Srgrimes * reply_proc collects replies from the broadcast. 5901900Swollman * to get a unique list of responses the output of rpcinfo should 5911900Swollman * be piped through sort(1) and then uniq(1). 5921900Swollman */ 5931900Swollman 5941900Swollman/*ARGSUSED*/ 5951900Swollmanstatic bool_t 59674462Salfredreply_proc(void *res, struct netbuf *who, struct netconfig *nconf) 59774462Salfred /* void *res; Nothing comes back */ 59874462Salfred /* struct netbuf *who; Who sent us the reply */ 59974462Salfred /* struct netconfig *nconf; On which transport the reply came */ 6001900Swollman{ 60174462Salfred char *uaddr; 60274462Salfred char hostbuf[NI_MAXHOST]; 603221860Sdelphij const char *hostname; 60474462Salfred struct sockaddr *sa = (struct sockaddr *)who->buf; 6051900Swollman 60674462Salfred if (getnameinfo(sa, sa->sa_len, hostbuf, NI_MAXHOST, NULL, 0, 0)) { 60774462Salfred hostname = UNKNOWN; 60874462Salfred } else { 60974462Salfred hostname = hostbuf; 61074462Salfred } 61174462Salfred if (!(uaddr = taddr2uaddr(nconf, who))) { 61274462Salfred uaddr = UNKNOWN; 61374462Salfred } 61474462Salfred printf("%s\t%s\n", uaddr, hostname); 61574462Salfred if (strcmp(uaddr, UNKNOWN)) 61674462Salfred free((char *)uaddr); 61774462Salfred return (FALSE); 6181900Swollman} 6191900Swollman 6201900Swollmanstatic void 62174462Salfredbrdcst(int argc, char **argv) 6221900Swollman{ 6231900Swollman enum clnt_stat rpc_stat; 6241900Swollman u_long prognum, vers; 6251900Swollman 626119849Scharnier if (argc != 2) 6271900Swollman usage(); 6281900Swollman prognum = getprognum(argv[0]); 6291900Swollman vers = getvers(argv[1]); 63074462Salfred rpc_stat = rpc_broadcast(prognum, vers, NULLPROC, 63174462Salfred (xdrproc_t) xdr_void, (char *)NULL, (xdrproc_t) xdr_void, 63274462Salfred (char *)NULL, (resultproc_t) reply_proc, NULL); 633119849Scharnier if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) 634119849Scharnier errx(1, "broadcast failed: %s", clnt_sperrno(rpc_stat)); 6351900Swollman exit(0); 6361900Swollman} 6371900Swollman 63874462Salfredstatic bool_t 63974462Salfredadd_version(struct rpcbdump_short *rs, u_long vers) 64074462Salfred{ 64174462Salfred struct verslist *vl; 64274462Salfred 64374462Salfred for (vl = rs->vlist; vl; vl = vl->next) 64474462Salfred if (vl->vers == vers) 64574462Salfred break; 64674462Salfred if (vl) 64774462Salfred return (TRUE); 64874462Salfred vl = (struct verslist *)malloc(sizeof (struct verslist)); 64974462Salfred if (vl == NULL) 65074462Salfred return (FALSE); 65174462Salfred vl->vers = vers; 65274462Salfred vl->next = rs->vlist; 65374462Salfred rs->vlist = vl; 65474462Salfred return (TRUE); 65574462Salfred} 65674462Salfred 65774462Salfredstatic bool_t 65874462Salfredadd_netid(struct rpcbdump_short *rs, char *netid) 65974462Salfred{ 66074462Salfred struct netidlist *nl; 66174462Salfred 66274462Salfred for (nl = rs->nlist; nl; nl = nl->next) 66374462Salfred if (strcmp(nl->netid, netid) == 0) 66474462Salfred break; 66574462Salfred if (nl) 66674462Salfred return (TRUE); 66774462Salfred nl = (struct netidlist *)malloc(sizeof (struct netidlist)); 66874462Salfred if (nl == NULL) 66974462Salfred return (FALSE); 67074462Salfred nl->netid = netid; 67174462Salfred nl->next = rs->nlist; 67274462Salfred rs->nlist = nl; 67374462Salfred return (TRUE); 67474462Salfred} 67574462Salfred 6761900Swollmanstatic void 67774462Salfredrpcbdump(int dumptype, char *netid, int argc, char **argv) 67874462Salfred{ 67974462Salfred rpcblist_ptr head = NULL; 68074462Salfred struct timeval minutetimeout; 68174462Salfred register CLIENT *client; 68274462Salfred struct rpcent *rpc; 68374462Salfred char *host; 68474462Salfred struct netidlist *nl; 68574462Salfred struct verslist *vl; 68674462Salfred struct rpcbdump_short *rs, *rs_tail; 68774462Salfred char buf[256]; 68874462Salfred enum clnt_stat clnt_st; 68974462Salfred struct rpc_err err; 69074462Salfred struct rpcbdump_short *rs_head = NULL; 6911900Swollman 692119849Scharnier if (argc > 1) 69374462Salfred usage(); 69474462Salfred if (argc == 1) { 69574462Salfred host = argv[0]; 69674462Salfred if (netid == NULL) { 69774462Salfred client = clnt_rpcbind_create(host, RPCBVERS, NULL); 69874462Salfred } else { 69974462Salfred struct netconfig *nconf; 70074462Salfred 70174462Salfred nconf = getnetconfigent(netid); 70274462Salfred if (nconf == NULL) { 70374462Salfred nc_perror("rpcinfo: invalid transport"); 70474462Salfred exit(1); 70574462Salfred } 70674462Salfred client = getclnthandle(host, nconf, RPCBVERS, NULL); 70774462Salfred if (nconf) 70874462Salfred (void) freenetconfigent(nconf); 70974462Salfred } 71074462Salfred } else 71174462Salfred client = local_rpcb(PMAPPROG, RPCBVERS); 71274462Salfred 71374462Salfred if (client == (CLIENT *)NULL) { 71474462Salfred clnt_pcreateerror("rpcinfo: can't contact rpcbind"); 71574462Salfred exit(1); 71674462Salfred } 71774462Salfred 71874462Salfred minutetimeout.tv_sec = 60; 71974462Salfred minutetimeout.tv_usec = 0; 72074462Salfred clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, (xdrproc_t) xdr_void, 72174462Salfred NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *) &head, 72274462Salfred minutetimeout); 72374462Salfred if (clnt_st != RPC_SUCCESS) { 72474462Salfred if ((clnt_st == RPC_PROGVERSMISMATCH) || 72574462Salfred (clnt_st == RPC_PROGUNAVAIL)) { 72674462Salfred int vers; 72774462Salfred 72874462Salfred CLNT_GETERR(client, &err); 72974462Salfred if (err.re_vers.low == RPCBVERS4) { 73074462Salfred vers = RPCBVERS4; 73174462Salfred clnt_control(client, CLSET_VERS, (char *)&vers); 73274462Salfred clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, 73374462Salfred (xdrproc_t) xdr_void, NULL, 73474462Salfred (xdrproc_t) xdr_rpcblist_ptr, (char *) &head, 73574462Salfred minutetimeout); 73674462Salfred if (clnt_st != RPC_SUCCESS) 73774462Salfred goto failed; 73874462Salfred } else { 73974462Salfred if (err.re_vers.high == PMAPVERS) { 74074462Salfred int high, low; 74174462Salfred struct pmaplist *pmaphead = NULL; 74274462Salfred rpcblist_ptr list, prev; 74374462Salfred 74474462Salfred vers = PMAPVERS; 74574462Salfred clnt_control(client, CLSET_VERS, (char *)&vers); 74674462Salfred clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, 74774462Salfred (xdrproc_t) xdr_void, NULL, 74874462Salfred (xdrproc_t) xdr_pmaplist_ptr, 74974462Salfred (char *)&pmaphead, minutetimeout); 75074462Salfred if (clnt_st != RPC_SUCCESS) 75174462Salfred goto failed; 75274462Salfred /* 75374462Salfred * convert to rpcblist_ptr format 75474462Salfred */ 75574462Salfred for (head = NULL; pmaphead != NULL; 75674462Salfred pmaphead = pmaphead->pml_next) { 75774462Salfred list = (rpcblist *)malloc(sizeof (rpcblist)); 75874462Salfred if (list == NULL) 75974462Salfred goto error; 76074462Salfred if (head == NULL) 76174462Salfred head = list; 76274462Salfred else 76374462Salfred prev->rpcb_next = (rpcblist_ptr) list; 76474462Salfred 76574462Salfred list->rpcb_next = NULL; 76674462Salfred list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog; 76774462Salfred list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers; 76874462Salfred if (pmaphead->pml_map.pm_prot == IPPROTO_UDP) 76974462Salfred list->rpcb_map.r_netid = "udp"; 77074462Salfred else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP) 77174462Salfred list->rpcb_map.r_netid = "tcp"; 77274462Salfred else { 77374462Salfred#define MAXLONG_AS_STRING "2147483648" 77474462Salfred list->rpcb_map.r_netid = 77574462Salfred malloc(strlen(MAXLONG_AS_STRING) + 1); 77674462Salfred if (list->rpcb_map.r_netid == NULL) 77774462Salfred goto error; 77874462Salfred sprintf(list->rpcb_map.r_netid, "%6ld", 77974462Salfred pmaphead->pml_map.pm_prot); 78074462Salfred } 78174462Salfred list->rpcb_map.r_owner = UNKNOWN; 78274462Salfred low = pmaphead->pml_map.pm_port & 0xff; 78374462Salfred high = (pmaphead->pml_map.pm_port >> 8) & 0xff; 78474462Salfred list->rpcb_map.r_addr = strdup("0.0.0.0.XXX.XXX"); 78574462Salfred sprintf(&list->rpcb_map.r_addr[8], "%d.%d", 78674462Salfred high, low); 78774462Salfred prev = list; 78874462Salfred } 78974462Salfred } 79074462Salfred } 79174462Salfred } else { /* any other error */ 79274462Salfredfailed: 79374462Salfred clnt_perror(client, "rpcinfo: can't contact rpcbind: "); 79474462Salfred exit(1); 79574462Salfred } 79674462Salfred } 79774462Salfred if (head == NULL) { 79874462Salfred printf("No remote programs registered.\n"); 79974462Salfred } else if (dumptype == RPCBDUMP) { 80074462Salfred printf( 80174462Salfred" program version netid address service owner\n"); 80274462Salfred for (; head != NULL; head = head->rpcb_next) { 80374462Salfred printf("%10u%5u ", 80474462Salfred head->rpcb_map.r_prog, head->rpcb_map.r_vers); 80574462Salfred printf("%-9s ", head->rpcb_map.r_netid); 80674462Salfred printf("%-22s", head->rpcb_map.r_addr); 80774462Salfred rpc = getrpcbynumber(head->rpcb_map.r_prog); 80874462Salfred if (rpc) 80974462Salfred printf(" %-10s", rpc->r_name); 81074462Salfred else 81174462Salfred printf(" %-10s", "-"); 81274462Salfred printf(" %s\n", head->rpcb_map.r_owner); 81374462Salfred } 81474462Salfred } else if (dumptype == RPCBDUMP_SHORT) { 81574462Salfred for (; head != NULL; head = head->rpcb_next) { 81674462Salfred for (rs = rs_head; rs; rs = rs->next) 81774462Salfred if (head->rpcb_map.r_prog == rs->prog) 81874462Salfred break; 81974462Salfred if (rs == NULL) { 82074462Salfred rs = (struct rpcbdump_short *) 82174462Salfred malloc(sizeof (struct rpcbdump_short)); 82274462Salfred if (rs == NULL) 82374462Salfred goto error; 82474462Salfred rs->next = NULL; 82574462Salfred if (rs_head == NULL) { 82674462Salfred rs_head = rs; 82774462Salfred rs_tail = rs; 82874462Salfred } else { 82974462Salfred rs_tail->next = rs; 83074462Salfred rs_tail = rs; 83174462Salfred } 83274462Salfred rs->prog = head->rpcb_map.r_prog; 83374462Salfred rs->owner = head->rpcb_map.r_owner; 83474462Salfred rs->nlist = NULL; 83574462Salfred rs->vlist = NULL; 83674462Salfred } 83774462Salfred if (add_version(rs, head->rpcb_map.r_vers) == FALSE) 83874462Salfred goto error; 83974462Salfred if (add_netid(rs, head->rpcb_map.r_netid) == FALSE) 84074462Salfred goto error; 84174462Salfred } 84274462Salfred printf( 84374462Salfred" program version(s) netid(s) service owner\n"); 84474462Salfred for (rs = rs_head; rs; rs = rs->next) { 84574462Salfred char *p = buf; 84674462Salfred 84774462Salfred printf("%10ld ", rs->prog); 84874462Salfred for (vl = rs->vlist; vl; vl = vl->next) { 84974462Salfred sprintf(p, "%d", vl->vers); 85074462Salfred p = p + strlen(p); 85174462Salfred if (vl->next) 85274462Salfred sprintf(p++, ","); 85374462Salfred } 85474462Salfred printf("%-10s", buf); 855126840Sbde buf[0] = '\0'; 85674462Salfred for (nl = rs->nlist; nl; nl = nl->next) { 857319256Sasomers strlcat(buf, nl->netid, sizeof(buf)); 85874462Salfred if (nl->next) 859319256Sasomers strlcat(buf, ",", sizeof(buf)); 86074462Salfred } 86174462Salfred printf("%-32s", buf); 86274462Salfred rpc = getrpcbynumber(rs->prog); 86374462Salfred if (rpc) 86474462Salfred printf(" %-11s", rpc->r_name); 86574462Salfred else 86674462Salfred printf(" %-11s", "-"); 86774462Salfred printf(" %s\n", rs->owner); 86874462Salfred } 86974462Salfred } 87074462Salfred clnt_destroy(client); 87174462Salfred return; 872119849Scharniererror: warnx("no memory"); 87374462Salfred return; 87474462Salfred} 87574462Salfred 87674462Salfredstatic char nullstring[] = "\000"; 87774462Salfred 87874462Salfredstatic void 87974462Salfredrpcbaddrlist(char *netid, int argc, char **argv) 88074462Salfred{ 88174462Salfred rpcb_entry_list_ptr head = NULL; 88274462Salfred struct timeval minutetimeout; 88374462Salfred register CLIENT *client; 88474462Salfred struct rpcent *rpc; 88574462Salfred char *host; 88674462Salfred RPCB parms; 88774462Salfred struct netbuf *targaddr; 88874462Salfred 889119849Scharnier if (argc != 3) 89074462Salfred usage(); 89174462Salfred host = argv[0]; 89274462Salfred if (netid == NULL) { 89374462Salfred client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr); 89474462Salfred } else { 89574462Salfred struct netconfig *nconf; 89674462Salfred 89774462Salfred nconf = getnetconfigent(netid); 89874462Salfred if (nconf == NULL) { 89974462Salfred nc_perror("rpcinfo: invalid transport"); 90074462Salfred exit(1); 90174462Salfred } 90274462Salfred client = getclnthandle(host, nconf, RPCBVERS4, &targaddr); 90374462Salfred if (nconf) 90474462Salfred (void) freenetconfigent(nconf); 90574462Salfred } 90674462Salfred if (client == (CLIENT *)NULL) { 90774462Salfred clnt_pcreateerror("rpcinfo: can't contact rpcbind"); 90874462Salfred exit(1); 90974462Salfred } 91074462Salfred minutetimeout.tv_sec = 60; 91174462Salfred minutetimeout.tv_usec = 0; 91274462Salfred 91374462Salfred parms.r_prog = getprognum(argv[1]); 91474462Salfred parms.r_vers = getvers(argv[2]); 91574462Salfred parms.r_netid = client->cl_netid; 91674462Salfred if (targaddr == NULL) { 91774462Salfred parms.r_addr = nullstring; /* for XDRing */ 91874462Salfred } else { 91974462Salfred /* 92074462Salfred * We also send the remote system the address we 92174462Salfred * used to contact it in case it can help it 92274462Salfred * connect back with us 92374462Salfred */ 92474462Salfred struct netconfig *nconf; 92574462Salfred 92674462Salfred nconf = getnetconfigent(client->cl_netid); 92774462Salfred if (nconf != NULL) { 92874462Salfred parms.r_addr = taddr2uaddr(nconf, targaddr); 92974462Salfred if (parms.r_addr == NULL) 93074462Salfred parms.r_addr = nullstring; 93174462Salfred freenetconfigent(nconf); 93274462Salfred } else { 93374462Salfred parms.r_addr = nullstring; /* for XDRing */ 93474462Salfred } 93574462Salfred free(targaddr->buf); 93674462Salfred free(targaddr); 93774462Salfred } 93874462Salfred parms.r_owner = nullstring; 93974462Salfred 94074462Salfred if (CLNT_CALL(client, RPCBPROC_GETADDRLIST, (xdrproc_t) xdr_rpcb, 94174462Salfred (char *) &parms, (xdrproc_t) xdr_rpcb_entry_list_ptr, 94274462Salfred (char *) &head, minutetimeout) != RPC_SUCCESS) { 94374462Salfred clnt_perror(client, "rpcinfo: can't contact rpcbind: "); 94474462Salfred exit(1); 94574462Salfred } 94674462Salfred if (head == NULL) { 94774462Salfred printf("No remote programs registered.\n"); 94874462Salfred } else { 94974462Salfred printf( 95074462Salfred " program vers tp_family/name/class address\t\t service\n"); 95174462Salfred for (; head != NULL; head = head->rpcb_entry_next) { 95274462Salfred rpcb_entry *re; 95374462Salfred char buf[128]; 95474462Salfred 95574462Salfred re = &head->rpcb_entry_map; 95674462Salfred printf("%10u%3u ", 95774462Salfred parms.r_prog, parms.r_vers); 95874462Salfred sprintf(buf, "%s/%s/%s ", 95974462Salfred re->r_nc_protofmly, re->r_nc_proto, 96074462Salfred re->r_nc_semantics == NC_TPI_CLTS ? "clts" : 96174462Salfred re->r_nc_semantics == NC_TPI_COTS ? "cots" : 96274462Salfred "cots_ord"); 96374462Salfred printf("%-24s", buf); 96474462Salfred printf("%-24s", re->r_maddr); 96574462Salfred rpc = getrpcbynumber(parms.r_prog); 96674462Salfred if (rpc) 96774462Salfred printf(" %-13s", rpc->r_name); 96874462Salfred else 96974462Salfred printf(" %-13s", "-"); 97074462Salfred printf("\n"); 97174462Salfred } 97274462Salfred } 97374462Salfred clnt_destroy(client); 97474462Salfred return; 97574462Salfred} 97674462Salfred 97774462Salfred/* 97874462Salfred * monitor rpcbind 97974462Salfred */ 98074462Salfredstatic void 98174462Salfredrpcbgetstat(int argc, char **argv) 98274462Salfred{ 98374462Salfred rpcb_stat_byvers inf; 98474462Salfred struct timeval minutetimeout; 98574462Salfred register CLIENT *client; 98674462Salfred char *host; 98774462Salfred int i, j; 98874462Salfred rpcbs_addrlist *pa; 98974462Salfred rpcbs_rmtcalllist *pr; 99074462Salfred int cnt, flen; 99174462Salfred#define MAXFIELD 64 99274462Salfred char fieldbuf[MAXFIELD]; 99374462Salfred#define MAXLINE 256 99474462Salfred char linebuf[MAXLINE]; 99574462Salfred char *cp, *lp; 996221860Sdelphij const char *pmaphdr[] = { 99774462Salfred "NULL", "SET", "UNSET", "GETPORT", 99874462Salfred "DUMP", "CALLIT" 99974462Salfred }; 1000221860Sdelphij const char *rpcb3hdr[] = { 100174462Salfred "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME", 100274462Salfred "U2T", "T2U" 100374462Salfred }; 1004221860Sdelphij const char *rpcb4hdr[] = { 100574462Salfred "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME", 100674462Salfred "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT" 100774462Salfred }; 100874462Salfred 100974462Salfred#define TABSTOP 8 101074462Salfred 101174462Salfred if (argc >= 1) { 101274462Salfred host = argv[0]; 101374462Salfred client = clnt_rpcbind_create(host, RPCBVERS4, NULL); 101474462Salfred } else 101574462Salfred client = local_rpcb(PMAPPROG, RPCBVERS4); 101674462Salfred if (client == (CLIENT *)NULL) { 101774462Salfred clnt_pcreateerror("rpcinfo: can't contact rpcbind"); 101874462Salfred exit(1); 101974462Salfred } 102074462Salfred minutetimeout.tv_sec = 60; 102174462Salfred minutetimeout.tv_usec = 0; 102274462Salfred memset((char *)&inf, 0, sizeof (rpcb_stat_byvers)); 102374462Salfred if (CLNT_CALL(client, RPCBPROC_GETSTAT, (xdrproc_t) xdr_void, NULL, 102474462Salfred (xdrproc_t) xdr_rpcb_stat_byvers, (char *)&inf, minutetimeout) 102574462Salfred != RPC_SUCCESS) { 102674462Salfred clnt_perror(client, "rpcinfo: can't contact rpcbind: "); 102774462Salfred exit(1); 102874462Salfred } 102974462Salfred printf("PORTMAP (version 2) statistics\n"); 103074462Salfred lp = linebuf; 103174462Salfred for (i = 0; i <= rpcb_highproc_2; i++) { 103274462Salfred fieldbuf[0] = '\0'; 103374462Salfred switch (i) { 103474462Salfred case PMAPPROC_SET: 103574462Salfred sprintf(fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo); 103674462Salfred break; 103774462Salfred case PMAPPROC_UNSET: 103874462Salfred sprintf(fieldbuf, "%d/", 103974462Salfred inf[RPCBVERS_2_STAT].unsetinfo); 104074462Salfred break; 104174462Salfred case PMAPPROC_GETPORT: 104274462Salfred cnt = 0; 104374462Salfred for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa; 104474462Salfred pa = pa->next) 104574462Salfred cnt += pa->success; 104674462Salfred sprintf(fieldbuf, "%d/", cnt); 104774462Salfred break; 104874462Salfred case PMAPPROC_CALLIT: 104974462Salfred cnt = 0; 105074462Salfred for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr; 105174462Salfred pr = pr->next) 105274462Salfred cnt += pr->success; 105374462Salfred sprintf(fieldbuf, "%d/", cnt); 105474462Salfred break; 105574462Salfred default: break; /* For the remaining ones */ 105674462Salfred } 105774462Salfred cp = &fieldbuf[0] + strlen(fieldbuf); 105874462Salfred sprintf(cp, "%d", inf[RPCBVERS_2_STAT].info[i]); 105974462Salfred flen = strlen(fieldbuf); 106074462Salfred printf("%s%s", pmaphdr[i], 106174462Salfred spaces((TABSTOP * (1 + flen / TABSTOP)) 106274462Salfred - strlen(pmaphdr[i]))); 106374462Salfred sprintf(lp, "%s%s", fieldbuf, 106474462Salfred spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) 106574462Salfred - flen))); 106674462Salfred lp += (flen + cnt); 106774462Salfred } 106874462Salfred printf("\n%s\n\n", linebuf); 106974462Salfred 107074462Salfred if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT]) { 107174462Salfred printf("PMAP_RMTCALL call statistics\n"); 107274462Salfred print_rmtcallstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]); 107374462Salfred printf("\n"); 107474462Salfred } 107574462Salfred 107674462Salfred if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT]) { 107774462Salfred printf("PMAP_GETPORT call statistics\n"); 107874462Salfred print_getaddrstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]); 107974462Salfred printf("\n"); 108074462Salfred } 108174462Salfred 108274462Salfred printf("RPCBIND (version 3) statistics\n"); 108374462Salfred lp = linebuf; 108474462Salfred for (i = 0; i <= rpcb_highproc_3; i++) { 108574462Salfred fieldbuf[0] = '\0'; 108674462Salfred switch (i) { 108774462Salfred case RPCBPROC_SET: 108874462Salfred sprintf(fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo); 108974462Salfred break; 109074462Salfred case RPCBPROC_UNSET: 109174462Salfred sprintf(fieldbuf, "%d/", 109274462Salfred inf[RPCBVERS_3_STAT].unsetinfo); 109374462Salfred break; 109474462Salfred case RPCBPROC_GETADDR: 109574462Salfred cnt = 0; 109674462Salfred for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa; 109774462Salfred pa = pa->next) 109874462Salfred cnt += pa->success; 109974462Salfred sprintf(fieldbuf, "%d/", cnt); 110074462Salfred break; 110174462Salfred case RPCBPROC_CALLIT: 110274462Salfred cnt = 0; 110374462Salfred for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr; 110474462Salfred pr = pr->next) 110574462Salfred cnt += pr->success; 110674462Salfred sprintf(fieldbuf, "%d/", cnt); 110774462Salfred break; 110874462Salfred default: break; /* For the remaining ones */ 110974462Salfred } 111074462Salfred cp = &fieldbuf[0] + strlen(fieldbuf); 111174462Salfred sprintf(cp, "%d", inf[RPCBVERS_3_STAT].info[i]); 111274462Salfred flen = strlen(fieldbuf); 111374462Salfred printf("%s%s", rpcb3hdr[i], 111474462Salfred spaces((TABSTOP * (1 + flen / TABSTOP)) 111574462Salfred - strlen(rpcb3hdr[i]))); 111674462Salfred sprintf(lp, "%s%s", fieldbuf, 111774462Salfred spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) 111874462Salfred - flen))); 111974462Salfred lp += (flen + cnt); 112074462Salfred } 112174462Salfred printf("\n%s\n\n", linebuf); 112274462Salfred 112374462Salfred if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT]) { 112474462Salfred printf("RPCB_RMTCALL (version 3) call statistics\n"); 112574462Salfred print_rmtcallstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]); 112674462Salfred printf("\n"); 112774462Salfred } 112874462Salfred 112974462Salfred if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR]) { 113074462Salfred printf("RPCB_GETADDR (version 3) call statistics\n"); 113174462Salfred print_getaddrstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]); 113274462Salfred printf("\n"); 113374462Salfred } 113474462Salfred 113574462Salfred printf("RPCBIND (version 4) statistics\n"); 113674462Salfred 113774462Salfred for (j = 0; j <= 9; j += 9) { /* Just two iterations for printing */ 113874462Salfred lp = linebuf; 113974462Salfred for (i = j; i <= MAX(8, rpcb_highproc_4 - 9 + j); i++) { 114074462Salfred fieldbuf[0] = '\0'; 114174462Salfred switch (i) { 114274462Salfred case RPCBPROC_SET: 114374462Salfred sprintf(fieldbuf, "%d/", 114474462Salfred inf[RPCBVERS_4_STAT].setinfo); 114574462Salfred break; 114674462Salfred case RPCBPROC_UNSET: 114774462Salfred sprintf(fieldbuf, "%d/", 114874462Salfred inf[RPCBVERS_4_STAT].unsetinfo); 114974462Salfred break; 115074462Salfred case RPCBPROC_GETADDR: 115174462Salfred cnt = 0; 115274462Salfred for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa; 115374462Salfred pa = pa->next) 115474462Salfred cnt += pa->success; 115574462Salfred sprintf(fieldbuf, "%d/", cnt); 115674462Salfred break; 115774462Salfred case RPCBPROC_CALLIT: 115874462Salfred cnt = 0; 115974462Salfred for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr; 116074462Salfred pr = pr->next) 116174462Salfred cnt += pr->success; 116274462Salfred sprintf(fieldbuf, "%d/", cnt); 116374462Salfred break; 116474462Salfred default: break; /* For the remaining ones */ 116574462Salfred } 116674462Salfred cp = &fieldbuf[0] + strlen(fieldbuf); 116774462Salfred /* 116874462Salfred * XXX: We also add RPCBPROC_GETADDRLIST queries to 116974462Salfred * RPCB_GETADDR because rpcbind includes the 117074462Salfred * RPCB_GETADDRLIST successes in RPCB_GETADDR. 117174462Salfred */ 117274462Salfred if (i != RPCBPROC_GETADDR) 117374462Salfred sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i]); 117474462Salfred else 117574462Salfred sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i] + 117674462Salfred inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]); 117774462Salfred flen = strlen(fieldbuf); 117874462Salfred printf("%s%s", rpcb4hdr[i], 117974462Salfred spaces((TABSTOP * (1 + flen / TABSTOP)) 118074462Salfred - strlen(rpcb4hdr[i]))); 118174462Salfred sprintf(lp, "%s%s", fieldbuf, 118274462Salfred spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) 118374462Salfred - flen))); 118474462Salfred lp += (flen + cnt); 118574462Salfred } 118674462Salfred printf("\n%s\n", linebuf); 118774462Salfred } 118874462Salfred 118974462Salfred if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] || 119074462Salfred inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT]) { 119174462Salfred printf("\n"); 119274462Salfred printf("RPCB_RMTCALL (version 4) call statistics\n"); 119374462Salfred print_rmtcallstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]); 119474462Salfred } 119574462Salfred 119674462Salfred if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR]) { 119774462Salfred printf("\n"); 119874462Salfred printf("RPCB_GETADDR (version 4) call statistics\n"); 119974462Salfred print_getaddrstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]); 120074462Salfred } 120174462Salfred clnt_destroy(client); 120274462Salfred} 120374462Salfred 120474462Salfred/* 120574462Salfred * Delete registeration for this (prog, vers, netid) 120674462Salfred */ 120774462Salfredstatic void 120874462Salfreddeletereg(char *netid, int argc, char **argv) 120974462Salfred{ 121074462Salfred struct netconfig *nconf = NULL; 121174462Salfred 1212119849Scharnier if (argc != 2) 121374462Salfred usage(); 121474462Salfred if (netid) { 121574462Salfred nconf = getnetconfigent(netid); 1216119849Scharnier if (nconf == NULL) 1217119849Scharnier errx(1, "netid %s not supported", netid); 121874462Salfred } 1219119849Scharnier if ((rpcb_unset(getprognum(argv[0]), getvers(argv[1]), nconf)) == 0) 1220119849Scharnier errx(1, 1221119849Scharnier "could not delete registration for prog %s version %s", 122274462Salfred argv[0], argv[1]); 12231900Swollman} 12241900Swollman 122574462Salfred/* 122674462Salfred * Create and return a handle for the given nconf. 122774462Salfred * Exit if cannot create handle. 122874462Salfred */ 122974462Salfredstatic CLIENT * 123074462Salfredclnt_addr_create(char *address, struct netconfig *nconf, 123174462Salfred u_long prog, u_long vers) 123274462Salfred{ 123374462Salfred CLIENT *client; 123474462Salfred static struct netbuf *nbuf; 123574462Salfred static int fd = RPC_ANYFD; 123674462Salfred 123774462Salfred if (fd == RPC_ANYFD) { 123874462Salfred if ((fd = __rpc_nconf2fd(nconf)) == -1) { 123974462Salfred rpc_createerr.cf_stat = RPC_TLIERROR; 124074462Salfred clnt_pcreateerror("rpcinfo"); 124174462Salfred exit(1); 124274462Salfred } 124374462Salfred /* Convert the uaddr to taddr */ 124474462Salfred nbuf = uaddr2taddr(nconf, address); 1245119849Scharnier if (nbuf == NULL) 1246119849Scharnier errx(1, "no address for client handle"); 124774462Salfred } 124874462Salfred client = clnt_tli_create(fd, nconf, nbuf, prog, vers, 0, 0); 124974462Salfred if (client == (CLIENT *)NULL) { 125074462Salfred clnt_pcreateerror("rpcinfo"); 125174462Salfred exit(1); 125274462Salfred } 125374462Salfred return (client); 125474462Salfred} 125574462Salfred 125674462Salfred/* 125774462Salfred * If the version number is given, ping that (prog, vers); else try to find 125874462Salfred * the version numbers supported for that prog and ping all the versions. 125974462Salfred * Remote rpcbind is not contacted for this service. The requests are 126074462Salfred * sent directly to the services themselves. 126174462Salfred */ 12621900Swollmanstatic void 126374462Salfredaddrping(char *address, char *netid, int argc, char **argv) 126474462Salfred{ 126574462Salfred CLIENT *client; 126674462Salfred struct timeval to; 126774462Salfred enum clnt_stat rpc_stat; 126874462Salfred u_long prognum, versnum, minvers, maxvers; 126974462Salfred struct rpc_err rpcerr; 127074462Salfred int failure = 0; 127174462Salfred struct netconfig *nconf; 127274462Salfred int fd; 127374462Salfred 1274119849Scharnier if (argc < 1 || argc > 2 || (netid == NULL)) 127574462Salfred usage(); 127674462Salfred nconf = getnetconfigent(netid); 1277119849Scharnier if (nconf == (struct netconfig *)NULL) 1278119849Scharnier errx(1, "could not find %s", netid); 127974462Salfred to.tv_sec = 10; 128074462Salfred to.tv_usec = 0; 128174462Salfred prognum = getprognum(argv[0]); 128274462Salfred if (argc == 1) { /* Version number not known */ 128374462Salfred /* 128474462Salfred * A call to version 0 should fail with a program/version 128574462Salfred * mismatch, and give us the range of versions supported. 128674462Salfred */ 128774462Salfred versnum = MIN_VERS; 128874462Salfred } else { 128974462Salfred versnum = getvers(argv[1]); 129074462Salfred } 129174462Salfred client = clnt_addr_create(address, nconf, prognum, versnum); 129274462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 129374462Salfred (char *)NULL, (xdrproc_t) xdr_void, 129474462Salfred (char *)NULL, to); 129574462Salfred if (argc == 2) { 129674462Salfred /* Version number was known */ 129774462Salfred if (pstatus(client, prognum, versnum) < 0) 129874462Salfred failure = 1; 129974462Salfred (void) CLNT_DESTROY(client); 130074462Salfred if (failure) 130174462Salfred exit(1); 130274462Salfred return; 130374462Salfred } 130474462Salfred /* Version number not known */ 130574462Salfred (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL); 130674462Salfred (void) CLNT_CONTROL(client, CLGET_FD, (char *)&fd); 130774462Salfred if (rpc_stat == RPC_PROGVERSMISMATCH) { 130874462Salfred clnt_geterr(client, &rpcerr); 130974462Salfred minvers = rpcerr.re_vers.low; 131074462Salfred maxvers = rpcerr.re_vers.high; 131174462Salfred } else if (rpc_stat == RPC_SUCCESS) { 131274462Salfred /* 131374462Salfred * Oh dear, it DOES support version 0. 131474462Salfred * Let's try version MAX_VERS. 131574462Salfred */ 131674462Salfred (void) CLNT_DESTROY(client); 131774462Salfred client = clnt_addr_create(address, nconf, prognum, MAX_VERS); 131874462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 131974462Salfred (char *)NULL, (xdrproc_t) xdr_void, 132074462Salfred (char *)NULL, to); 132174462Salfred if (rpc_stat == RPC_PROGVERSMISMATCH) { 132274462Salfred clnt_geterr(client, &rpcerr); 132374462Salfred minvers = rpcerr.re_vers.low; 132474462Salfred maxvers = rpcerr.re_vers.high; 132574462Salfred } else if (rpc_stat == RPC_SUCCESS) { 132674462Salfred /* 132774462Salfred * It also supports version MAX_VERS. 132874462Salfred * Looks like we have a wise guy. 132974462Salfred * OK, we give them information on all 133074462Salfred * 4 billion versions they support... 133174462Salfred */ 133274462Salfred minvers = 0; 133374462Salfred maxvers = MAX_VERS; 133474462Salfred } else { 133574462Salfred (void) pstatus(client, prognum, MAX_VERS); 133674462Salfred exit(1); 133774462Salfred } 133874462Salfred } else { 133974462Salfred (void) pstatus(client, prognum, (u_long)0); 134074462Salfred exit(1); 134174462Salfred } 134274462Salfred (void) CLNT_DESTROY(client); 134374462Salfred for (versnum = minvers; versnum <= maxvers; versnum++) { 134474462Salfred client = clnt_addr_create(address, nconf, prognum, versnum); 134574462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 134674462Salfred (char *)NULL, (xdrproc_t) xdr_void, 134774462Salfred (char *)NULL, to); 134874462Salfred if (pstatus(client, prognum, versnum) < 0) 134974462Salfred failure = 1; 135074462Salfred (void) CLNT_DESTROY(client); 135174462Salfred } 135274462Salfred (void) close(fd); 135374462Salfred if (failure) 135474462Salfred exit(1); 135574462Salfred return; 135674462Salfred} 135774462Salfred 135874462Salfred/* 135974462Salfred * If the version number is given, ping that (prog, vers); else try to find 136074462Salfred * the version numbers supported for that prog and ping all the versions. 136174462Salfred * Remote rpcbind is *contacted* for this service. The requests are 136274462Salfred * then sent directly to the services themselves. 136374462Salfred */ 136474462Salfredstatic void 136574462Salfredprogping(char *netid, int argc, char **argv) 136674462Salfred{ 136774462Salfred CLIENT *client; 136874462Salfred struct timeval to; 136974462Salfred enum clnt_stat rpc_stat; 137074462Salfred u_long prognum, versnum, minvers, maxvers; 137174462Salfred struct rpc_err rpcerr; 137274462Salfred int failure = 0; 137374462Salfred struct netconfig *nconf; 137474462Salfred 1375119849Scharnier if (argc < 2 || argc > 3 || (netid == NULL)) 137674462Salfred usage(); 137774462Salfred prognum = getprognum(argv[1]); 137874462Salfred if (argc == 2) { /* Version number not known */ 137974462Salfred /* 138074462Salfred * A call to version 0 should fail with a program/version 138174462Salfred * mismatch, and give us the range of versions supported. 138274462Salfred */ 138374462Salfred versnum = MIN_VERS; 138474462Salfred } else { 138574462Salfred versnum = getvers(argv[2]); 138674462Salfred } 138774462Salfred if (netid) { 138874462Salfred nconf = getnetconfigent(netid); 1389119849Scharnier if (nconf == (struct netconfig *)NULL) 1390119849Scharnier errx(1, "could not find %s", netid); 139174462Salfred client = clnt_tp_create(argv[0], prognum, versnum, nconf); 139274462Salfred } else { 139374462Salfred client = clnt_create(argv[0], prognum, versnum, "NETPATH"); 139474462Salfred } 139574462Salfred if (client == (CLIENT *)NULL) { 139674462Salfred clnt_pcreateerror("rpcinfo"); 139774462Salfred exit(1); 139874462Salfred } 139974462Salfred to.tv_sec = 10; 140074462Salfred to.tv_usec = 0; 140174462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 140274462Salfred (char *)NULL, (xdrproc_t) xdr_void, 140374462Salfred (char *)NULL, to); 140474462Salfred if (argc == 3) { 140574462Salfred /* Version number was known */ 140674462Salfred if (pstatus(client, prognum, versnum) < 0) 140774462Salfred failure = 1; 140874462Salfred (void) CLNT_DESTROY(client); 140974462Salfred if (failure) 141074462Salfred exit(1); 141174462Salfred return; 141274462Salfred } 141374462Salfred /* Version number not known */ 141474462Salfred if (rpc_stat == RPC_PROGVERSMISMATCH) { 141574462Salfred clnt_geterr(client, &rpcerr); 141674462Salfred minvers = rpcerr.re_vers.low; 141774462Salfred maxvers = rpcerr.re_vers.high; 141874462Salfred } else if (rpc_stat == RPC_SUCCESS) { 141974462Salfred /* 142074462Salfred * Oh dear, it DOES support version 0. 142174462Salfred * Let's try version MAX_VERS. 142274462Salfred */ 142374462Salfred versnum = MAX_VERS; 142474462Salfred (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum); 142574462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, 142674462Salfred (xdrproc_t) xdr_void, (char *)NULL, 142774462Salfred (xdrproc_t) xdr_void, (char *)NULL, to); 142874462Salfred if (rpc_stat == RPC_PROGVERSMISMATCH) { 142974462Salfred clnt_geterr(client, &rpcerr); 143074462Salfred minvers = rpcerr.re_vers.low; 143174462Salfred maxvers = rpcerr.re_vers.high; 143274462Salfred } else if (rpc_stat == RPC_SUCCESS) { 143374462Salfred /* 143474462Salfred * It also supports version MAX_VERS. 143574462Salfred * Looks like we have a wise guy. 143674462Salfred * OK, we give them information on all 143774462Salfred * 4 billion versions they support... 143874462Salfred */ 143974462Salfred minvers = 0; 144074462Salfred maxvers = MAX_VERS; 144174462Salfred } else { 144274462Salfred (void) pstatus(client, prognum, MAX_VERS); 144374462Salfred exit(1); 144474462Salfred } 144574462Salfred } else { 144674462Salfred (void) pstatus(client, prognum, (u_long)0); 144774462Salfred exit(1); 144874462Salfred } 144974462Salfred for (versnum = minvers; versnum <= maxvers; versnum++) { 145074462Salfred (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum); 145174462Salfred rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 145274462Salfred (char *)NULL, (xdrproc_t) xdr_void, 145374462Salfred (char *)NULL, to); 145474462Salfred if (pstatus(client, prognum, versnum) < 0) 145574462Salfred failure = 1; 145674462Salfred } 145774462Salfred (void) CLNT_DESTROY(client); 145874462Salfred if (failure) 145974462Salfred exit(1); 146074462Salfred return; 146174462Salfred} 146274462Salfred 146374462Salfredstatic void 1464221860Sdelphijusage(void) 14651900Swollman{ 146695258Sdes fprintf(stderr, "usage: rpcinfo [-m | -s] [host]\n"); 146774462Salfred#ifdef PORTMAP 146874462Salfred fprintf(stderr, " rpcinfo -p [host]\n"); 146974462Salfred#endif 147074462Salfred fprintf(stderr, " rpcinfo -T netid host prognum [versnum]\n"); 147174462Salfred fprintf(stderr, " rpcinfo -l host prognum versnum\n"); 147274462Salfred#ifdef PORTMAP 147374462Salfred fprintf(stderr, 147474462Salfred" rpcinfo [-n portnum] -u | -t host prognum [versnum]\n"); 147574462Salfred#endif 147674462Salfred fprintf(stderr, 147774462Salfred" rpcinfo -a serv_address -T netid prognum [version]\n"); 147874462Salfred fprintf(stderr, " rpcinfo -b prognum versnum\n"); 147974462Salfred fprintf(stderr, " rpcinfo -d [-T netid] prognum versnum\n"); 1480119849Scharnier exit(1); 14811900Swollman} 14821900Swollman 14831900Swollmanstatic u_long 148474462Salfredgetprognum (char *arg) 14851900Swollman{ 148674462Salfred char *strptr; 14871900Swollman register struct rpcent *rpc; 14881900Swollman register u_long prognum; 148974462Salfred char *tptr = arg; 14901900Swollman 149174462Salfred while (*tptr && isdigit(*tptr++)); 149274462Salfred if (*tptr || isalpha(*(tptr - 1))) { 14931900Swollman rpc = getrpcbyname(arg); 1494119849Scharnier if (rpc == NULL) 1495119849Scharnier errx(1, "%s is unknown service", arg); 14961900Swollman prognum = rpc->r_number; 14971900Swollman } else { 149874462Salfred prognum = strtol(arg, &strptr, 10); 1499119849Scharnier if (strptr == arg || *strptr != '\0') 1500119849Scharnier errx(1, "%s is illegal program number", arg); 15011900Swollman } 15021900Swollman return (prognum); 15031900Swollman} 15041900Swollman 15051900Swollmanstatic u_long 150674462Salfredgetvers(char *arg) 15071900Swollman{ 150874462Salfred char *strptr; 15091900Swollman register u_long vers; 15101900Swollman 151174462Salfred vers = (int) strtol(arg, &strptr, 10); 1512119849Scharnier if (strptr == arg || *strptr != '\0') 1513119849Scharnier errx(1, "%s is illegal version number", arg); 15141900Swollman return (vers); 15151900Swollman} 15161900Swollman 151774462Salfred/* 151874462Salfred * This routine should take a pointer to an "rpc_err" structure, rather than 151974462Salfred * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to 152074462Salfred * a CLIENT structure rather than a pointer to an "rpc_err" structure. 152174462Salfred * As such, we have to keep the CLIENT structure around in order to print 152274462Salfred * a good error message. 152374462Salfred */ 152474462Salfredstatic int 152574462Salfredpstatus(register CLIENT *client, u_long prog, u_long vers) 152674462Salfred{ 152774462Salfred struct rpc_err rpcerr; 152874462Salfred 152974462Salfred clnt_geterr(client, &rpcerr); 153074462Salfred if (rpcerr.re_status != RPC_SUCCESS) { 153174462Salfred clnt_perror(client, "rpcinfo"); 153274462Salfred printf("program %lu version %lu is not available\n", 153374462Salfred prog, vers); 153474462Salfred return (-1); 153574462Salfred } else { 153674462Salfred printf("program %lu version %lu ready and waiting\n", 153774462Salfred prog, vers); 153874462Salfred return (0); 153974462Salfred } 154074462Salfred} 154174462Salfred 154274462Salfredstatic CLIENT * 154374462Salfredclnt_rpcbind_create(char *host, int rpcbversnum, struct netbuf **targaddr) 154474462Salfred{ 1545221860Sdelphij static const char *tlist[3] = { 154674462Salfred "circuit_n", "circuit_v", "datagram_v" 154774462Salfred }; 154874462Salfred int i; 154974462Salfred struct netconfig *nconf; 155074462Salfred CLIENT *clnt = NULL; 155174462Salfred void *handle; 155274462Salfred 155374462Salfred rpc_createerr.cf_stat = RPC_SUCCESS; 155474462Salfred for (i = 0; i < 3; i++) { 155574462Salfred if ((handle = __rpc_setconf(tlist[i])) == NULL) 155674462Salfred continue; 155774462Salfred while (clnt == (CLIENT *)NULL) { 155874462Salfred if ((nconf = __rpc_getconf(handle)) == NULL) { 155974462Salfred if (rpc_createerr.cf_stat == RPC_SUCCESS) 156074462Salfred rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 156174462Salfred break; 156274462Salfred } 156374462Salfred clnt = getclnthandle(host, nconf, rpcbversnum, 156474462Salfred targaddr); 156574462Salfred } 156674462Salfred if (clnt) 156774462Salfred break; 156874462Salfred __rpc_endconf(handle); 156974462Salfred } 157074462Salfred return (clnt); 157174462Salfred} 157274462Salfred 157374462Salfredstatic CLIENT* 157474462Salfredgetclnthandle(char *host, struct netconfig *nconf, 157574462Salfred u_long rpcbversnum, struct netbuf **targaddr) 157674462Salfred{ 157774462Salfred struct netbuf addr; 157874462Salfred struct addrinfo hints, *res; 157974462Salfred CLIENT *client = NULL; 158074462Salfred 158174462Salfred /* Get the address of the rpcbind */ 158274462Salfred memset(&hints, 0, sizeof hints); 158374462Salfred if (getaddrinfo(host, "rpcbind", &hints, &res) != 0) { 158474462Salfred rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 158574462Salfred return (NULL); 158674462Salfred } 158774462Salfred addr.len = addr.maxlen = res->ai_addrlen; 158874462Salfred addr.buf = res->ai_addr; 158974462Salfred client = clnt_tli_create(RPC_ANYFD, nconf, &addr, RPCBPROG, 159074462Salfred rpcbversnum, 0, 0); 159174462Salfred if (client) { 159274462Salfred if (targaddr != NULL) { 159374462Salfred *targaddr = 159474462Salfred (struct netbuf *)malloc(sizeof (struct netbuf)); 159574462Salfred if (*targaddr != NULL) { 159674462Salfred (*targaddr)->maxlen = addr.maxlen; 159774462Salfred (*targaddr)->len = addr.len; 159874462Salfred (*targaddr)->buf = (char *)malloc(addr.len); 159974462Salfred if ((*targaddr)->buf != NULL) { 160074462Salfred memcpy((*targaddr)->buf, addr.buf, 160174462Salfred addr.len); 160274462Salfred } 160374462Salfred } 160474462Salfred } 160574462Salfred } else { 160674462Salfred if (rpc_createerr.cf_stat == RPC_TLIERROR) { 160774462Salfred /* 160874462Salfred * Assume that the other system is dead; this is a 160974462Salfred * better error to display to the user. 161074462Salfred */ 161174462Salfred rpc_createerr.cf_stat = RPC_RPCBFAILURE; 161274462Salfred rpc_createerr.cf_error.re_status = RPC_FAILED; 161374462Salfred } 161474462Salfred } 161574462Salfred freeaddrinfo(res); 161674462Salfred return (client); 161774462Salfred} 161874462Salfred 16191900Swollmanstatic void 162074462Salfredprint_rmtcallstat(int rtype, rpcb_stat *infp) 16211900Swollman{ 162274462Salfred register rpcbs_rmtcalllist_ptr pr; 162374462Salfred struct rpcent *rpc; 16241900Swollman 162574462Salfred if (rtype == RPCBVERS_4_STAT) 162674462Salfred printf( 162774462Salfred "prog\t\tvers\tproc\tnetid\tindirect success failure\n"); 162874462Salfred else 162974462Salfred printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n"); 163074462Salfred for (pr = infp->rmtinfo; pr; pr = pr->next) { 163174462Salfred rpc = getrpcbynumber(pr->prog); 163274462Salfred if (rpc) 163374462Salfred printf("%-16s", rpc->r_name); 163474462Salfred else 163574462Salfred printf("%-16d", pr->prog); 163674462Salfred printf("%d\t%d\t%s\t", 163774462Salfred pr->vers, pr->proc, pr->netid); 163874462Salfred if (rtype == RPCBVERS_4_STAT) 163974462Salfred printf("%d\t ", pr->indirect); 164074462Salfred printf("%d\t%d\n", pr->success, pr->failure); 16411900Swollman } 16421900Swollman} 164374462Salfred 164474462Salfredstatic void 164574462Salfredprint_getaddrstat(int rtype, rpcb_stat *infp) 164674462Salfred{ 164774462Salfred rpcbs_addrlist_ptr al; 164874462Salfred register struct rpcent *rpc; 164974462Salfred 165074462Salfred printf("prog\t\tvers\tnetid\t success\tfailure\n"); 165174462Salfred for (al = infp->addrinfo; al; al = al->next) { 165274462Salfred rpc = getrpcbynumber(al->prog); 165374462Salfred if (rpc) 165474462Salfred printf("%-16s", rpc->r_name); 165574462Salfred else 165674462Salfred printf("%-16d", al->prog); 165774462Salfred printf("%d\t%s\t %-12d\t%d\n", 165874462Salfred al->vers, al->netid, 165974462Salfred al->success, al->failure); 166074462Salfred } 166174462Salfred} 166274462Salfred 166374462Salfredstatic char * 166474462Salfredspaces(int howmany) 166574462Salfred{ 166674462Salfred static char space_array[] = /* 64 spaces */ 166774462Salfred " "; 166874462Salfred 166974462Salfred if (howmany <= 0 || howmany > sizeof (space_array)) { 167074462Salfred return (""); 167174462Salfred } 167274462Salfred return (&space_array[sizeof (space_array) - howmany - 1]); 167374462Salfred} 1674