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