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