2 /*static char sccsid[] = "from: @(#)rpcinfo.c 1.22 87/08/12 SMI";*/
3 /*static char sccsid[] = "from: @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC";*/
9 * Copyright (C) 1986, Sun Microsystems, Inc.
13 * rpcinfo: ping a particular rpc program
14 * or dump the portmapper
18 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
19 * unrestricted use provided that this legend is included on all tape
20 * media and as a part of the software program in whole or part. Users
21 * may copy or modify Sun RPC without charge, but are not authorized
22 * to license or distribute it to anyone else except as part of a product or
23 * program developed by the user.
25 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
26 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
29 * Sun RPC is provided with no support and without any obligation on the
30 * part of Sun Microsystems, Inc. to assist in its use, correction,
31 * modification or enhancement.
33 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
34 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
35 * OR ANY PART THEREOF.
37 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
38 * or profits or other special, indirect and consequential damages, even if
39 * Sun has been advised of the possibility of such damages.
41 * Sun Microsystems, Inc.
43 * Mountain View, California 94043
50 #include <sys/socket.h>
52 #include <rpc/pmap_prot.h>
53 #include <rpc/pmap_clnt.h>
56 #include <sys/param.h>
57 #include <arpa/inet.h>
59 #define MAXHOSTLEN 256
61 #define MIN_VERS ((u_long) 0)
62 #define MAX_VERS ((u_long) 4294967295UL)
64 static void udpping(/*u_short portflag, int argc, char **argv*/);
65 static void tcpping(/*u_short portflag, int argc, char **argv*/);
66 static int pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
67 static void pmapdump(/*int argc, char **argv*/);
68 static bool_t reply_proc(/*void *res, struct sockaddr_in *who*/);
69 static void brdcst(/*int argc, char **argv*/);
70 static void deletereg(/* int argc, char **argv */) ;
71 static void usage(/*void*/);
72 static u_long getprognum(/*char *arg*/);
73 static u_long getvers(/*char *arg*/);
74 static void get_inet_address(/*struct sockaddr_in *addr, char *host*/);
77 * Functions to be performed.
79 #define NONE 0 /* no function */
80 #define PMAPDUMP 1 /* dump portmapper registrations */
81 #define TCPPING 2 /* ping TCP service */
82 #define UDPPING 3 /* ping UDP service */
83 #define BRDCST 4 /* ping broadcast UDP service */
84 #define DELETES 5 /* delete registration for the service */
101 while ((c = getopt(argc, argv, "ptubdn:")) != -1) {
105 if (function != NONE)
112 if (function != NONE)
119 if (function != NONE)
126 if (function != NONE)
133 portnum = (u_short) atoi(optarg); /* hope we don't get bogus # */
137 if (function != NONE)
148 if (errflg || function == NONE) {
160 pmapdump(argc - optind, argv + optind);
164 udpping(portnum, argc - optind, argv + optind);
168 tcpping(portnum, argc - optind, argv + optind);
176 brdcst(argc - optind, argv + optind);
180 deletereg(argc - optind, argv + optind);
188 udpping(portnum, argc, argv)
194 struct sockaddr_in addr;
195 enum clnt_stat rpc_stat;
197 u_long prognum, vers, minvers, maxvers;
198 int sock = RPC_ANYSOCK;
199 struct rpc_err rpcerr;
202 if (argc < 2 || argc > 3) {
206 prognum = getprognum(argv[1]);
207 get_inet_address(&addr, argv[0]);
208 /* Open the socket here so it will survive calls to clnt_destroy */
209 sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
211 perror("rpcinfo: socket");
217 * A call to version 0 should fail with a program/version
218 * mismatch, and give us the range of versions supported.
220 addr.sin_port = htons(portnum);
223 if ((client = clntudp_create(&addr, prognum, (u_long)0,
224 to, &sock)) == NULL) {
225 clnt_pcreateerror("rpcinfo");
226 printf("program %lu is not available\n",
232 rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
233 xdr_void, (char *)NULL, to);
234 if (rpc_stat == RPC_PROGVERSMISMATCH) {
235 clnt_geterr(client, &rpcerr);
236 minvers = rpcerr.re_vers.low;
237 maxvers = rpcerr.re_vers.high;
238 } else if (rpc_stat == RPC_SUCCESS) {
240 * Oh dear, it DOES support version 0.
241 * Let's try version MAX_VERS.
243 addr.sin_port = htons(portnum);
246 if ((client = clntudp_create(&addr, prognum, MAX_VERS,
247 to, &sock)) == NULL) {
248 clnt_pcreateerror("rpcinfo");
249 printf("program %lu version %lu is not available\n",
255 rpc_stat = clnt_call(client, NULLPROC, xdr_void,
256 (char *)NULL, xdr_void, (char *)NULL, to);
257 if (rpc_stat == RPC_PROGVERSMISMATCH) {
258 clnt_geterr(client, &rpcerr);
259 minvers = rpcerr.re_vers.low;
260 maxvers = rpcerr.re_vers.high;
261 } else if (rpc_stat == RPC_SUCCESS) {
263 * It also supports version MAX_VERS.
264 * Looks like we have a wise guy.
265 * OK, we give them information on all
266 * 4 billion versions they support...
271 (void) pstatus(client, prognum, MAX_VERS);
275 (void) pstatus(client, prognum, (u_long)0);
278 clnt_destroy(client);
279 for (vers = minvers; vers <= maxvers; vers++) {
280 addr.sin_port = htons(portnum);
283 if ((client = clntudp_create(&addr, prognum, vers,
284 to, &sock)) == NULL) {
285 clnt_pcreateerror("rpcinfo");
286 printf("program %lu version %lu is not available\n",
292 rpc_stat = clnt_call(client, NULLPROC, xdr_void,
293 (char *)NULL, xdr_void, (char *)NULL, to);
294 if (pstatus(client, prognum, vers) < 0)
296 clnt_destroy(client);
300 vers = getvers(argv[2]);
301 addr.sin_port = htons(portnum);
304 if ((client = clntudp_create(&addr, prognum, vers,
305 to, &sock)) == NULL) {
306 clnt_pcreateerror("rpcinfo");
307 printf("program %lu version %lu is not available\n",
313 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
314 xdr_void, (char *)NULL, to);
315 if (pstatus(client, prognum, vers) < 0)
318 (void) close(sock); /* Close it up again */
324 tcpping(portnum, argc, argv)
330 struct sockaddr_in addr;
331 enum clnt_stat rpc_stat;
333 u_long prognum, vers, minvers, maxvers;
334 int sock = RPC_ANYSOCK;
335 struct rpc_err rpcerr;
338 if (argc < 2 || argc > 3) {
342 prognum = getprognum(argv[1]);
343 get_inet_address(&addr, argv[0]);
347 * A call to version 0 should fail with a program/version
348 * mismatch, and give us the range of versions supported.
350 addr.sin_port = htons(portnum);
351 if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
352 &sock, 0, 0)) == NULL) {
353 clnt_pcreateerror("rpcinfo");
354 printf("program %lu is not available\n",
360 rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
361 xdr_void, (char *)NULL, to);
362 if (rpc_stat == RPC_PROGVERSMISMATCH) {
363 clnt_geterr(client, &rpcerr);
364 minvers = rpcerr.re_vers.low;
365 maxvers = rpcerr.re_vers.high;
366 } else if (rpc_stat == RPC_SUCCESS) {
368 * Oh dear, it DOES support version 0.
369 * Let's try version MAX_VERS.
371 addr.sin_port = htons(portnum);
372 if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
373 &sock, 0, 0)) == NULL) {
374 clnt_pcreateerror("rpcinfo");
375 printf("program %lu version %lu is not available\n",
381 rpc_stat = clnt_call(client, NULLPROC, xdr_void,
382 (char *)NULL, xdr_void, (char *)NULL, to);
383 if (rpc_stat == RPC_PROGVERSMISMATCH) {
384 clnt_geterr(client, &rpcerr);
385 minvers = rpcerr.re_vers.low;
386 maxvers = rpcerr.re_vers.high;
387 } else if (rpc_stat == RPC_SUCCESS) {
389 * It also supports version MAX_VERS.
390 * Looks like we have a wise guy.
391 * OK, we give them information on all
392 * 4 billion versions they support...
397 (void) pstatus(client, prognum, MAX_VERS);
401 (void) pstatus(client, prognum, MIN_VERS);
404 clnt_destroy(client);
406 sock = RPC_ANYSOCK; /* Re-initialize it for later */
407 for (vers = minvers; vers <= maxvers; vers++) {
408 addr.sin_port = htons(portnum);
409 if ((client = clnttcp_create(&addr, prognum, vers,
410 &sock, 0, 0)) == NULL) {
411 clnt_pcreateerror("rpcinfo");
412 printf("program %lu version %lu is not available\n",
418 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
419 xdr_void, (char *)NULL, to);
420 if (pstatus(client, prognum, vers) < 0)
422 clnt_destroy(client);
428 vers = getvers(argv[2]);
429 addr.sin_port = htons(portnum);
430 if ((client = clnttcp_create(&addr, prognum, vers, &sock,
432 clnt_pcreateerror("rpcinfo");
433 printf("program %lu version %lu is not available\n",
439 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
440 xdr_void, (char *)NULL, to);
441 if (pstatus(client, prognum, vers) < 0)
449 * This routine should take a pointer to an "rpc_err" structure, rather than
450 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
451 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
452 * As such, we have to keep the CLIENT structure around in order to print
453 * a good error message.
456 pstatus(client, prognum, vers)
457 register CLIENT *client;
461 struct rpc_err rpcerr;
463 clnt_geterr(client, &rpcerr);
464 if (rpcerr.re_status != RPC_SUCCESS) {
465 clnt_perror(client, "rpcinfo");
466 printf("program %lu version %lu is not available\n",
470 printf("program %lu version %lu ready and waiting\n",
481 struct sockaddr_in server_addr;
482 register struct hostent *hp;
483 struct pmaplist *head = NULL;
484 int socket = RPC_ANYSOCK;
485 struct timeval minutetimeout;
486 register CLIENT *client;
494 get_inet_address(&server_addr, argv[0]);
496 bzero((char *)&server_addr, sizeof server_addr);
497 server_addr.sin_family = AF_INET;
498 if ((hp = gethostbyname("localhost")) != NULL)
499 bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
500 MIN(hp->h_length,sizeof(server_addr.sin_addr)));
502 server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
504 minutetimeout.tv_sec = 60;
505 minutetimeout.tv_usec = 0;
506 server_addr.sin_port = htons(PMAPPORT);
507 if ((client = clnttcp_create(&server_addr, PMAPPROG,
508 PMAPVERS, &socket, 50, 500)) == NULL) {
509 clnt_pcreateerror("rpcinfo: can't contact portmapper");
512 if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
513 xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
514 fprintf(stderr, "rpcinfo: can't contact portmapper: ");
515 clnt_perror(client, "rpcinfo");
519 printf("No remote programs registered.\n");
521 printf(" program vers proto port\n");
522 for (; head != NULL; head = head->pml_next) {
524 head->pml_map.pm_prog,
525 head->pml_map.pm_vers);
526 if (head->pml_map.pm_prot == IPPROTO_UDP)
527 printf("%6s", "udp");
528 else if (head->pml_map.pm_prot == IPPROTO_TCP)
529 printf("%6s", "tcp");
531 printf("%6ld", head->pml_map.pm_prot);
532 printf("%7ld", head->pml_map.pm_port);
533 rpc = getrpcbynumber(head->pml_map.pm_prog);
535 printf(" %s\n", rpc->r_name);
543 * reply_proc collects replies from the broadcast.
544 * to get a unique list of responses the output of rpcinfo should
545 * be piped through sort(1) and then uniq(1).
551 void *res; /* Nothing comes back */
552 struct sockaddr_in *who; /* Who sent us the reply */
554 register struct hostent *hp;
556 hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
558 printf("%s %s\n", inet_ntoa(who->sin_addr),
559 (hp == NULL) ? "(unknown)" : hp->h_name);
568 enum clnt_stat rpc_stat;
569 u_long prognum, vers;
575 prognum = getprognum(argv[0]);
576 vers = getvers(argv[1]);
577 rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
578 (char *)NULL, xdr_void, (char *)NULL, reply_proc);
579 if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
580 fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
581 clnt_sperrno(rpc_stat));
588 deletereg(argc, argv)
591 { u_long prog_num, version_num ;
597 if (getuid()) /* This command allowed only to root */
598 errx(1, "sorry, you are not root") ;
599 prog_num = getprognum(argv[0]);
600 version_num = getvers(argv[1]);
601 if ((pmap_unset(prog_num, version_num)) == 0)
602 errx(1, "could not delete registration for prog %s version %s",
609 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
610 "usage: rpcinfo [-n portnum] -u host prognum [versnum]",
611 " rpcinfo [-n portnum] -t host prognum [versnum]",
612 " rpcinfo -p [host]",
613 " rpcinfo -b prognum versnum",
614 " rpcinfo -d prognum versnum");
621 register struct rpcent *rpc;
622 register u_long prognum;
625 rpc = getrpcbyname(arg);
627 errx(1, "%s is unknown service", arg);
628 prognum = rpc->r_number;
630 prognum = (u_long) atoi(arg);
640 register u_long vers;
642 vers = (int) atoi(arg);
647 get_inet_address(addr, host)
648 struct sockaddr_in *addr;
651 register struct hostent *hp;
653 bzero((char *)addr, sizeof *addr);
654 addr->sin_addr.s_addr = (u_long) inet_addr(host);
655 if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
656 if ((hp = gethostbyname(host)) == NULL)
657 errx(1, "%s is unknown host\n", host);
658 bcopy(hp->h_addr, (char *)&addr->sin_addr,
659 MIN(hp->h_length,sizeof(addr->sin_addr)));
661 addr->sin_family = AF_INET;