2 /* @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC */
3 #if !defined(lint) && defined (SCCSID)
4 static char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
8 * Copyright (C) 1986, Sun Microsystems, Inc.
12 * rpcinfo: ping a particular rpc program
13 * or dump the portmapper
17 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
18 * unrestricted use provided that this legend is included on all tape
19 * media and as a part of the software program in whole or part. Users
20 * may copy or modify Sun RPC without charge, but are not authorized
21 * to license or distribute it to anyone else except as part of a product or
22 * program developed by the user.
24 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
25 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
28 * Sun RPC is provided with no support and without any obligation on the
29 * part of Sun Microsystems, Inc. to assist in its use, correction,
30 * modification or enhancement.
32 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
33 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
34 * OR ANY PART THEREOF.
36 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
37 * or profits or other special, indirect and consequential damages, even if
38 * Sun has been advised of the possibility of such damages.
40 * Sun Microsystems, Inc.
42 * Mountain View, California 94043
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
54 #include <rpc/pmap_prot.h>
55 #include <rpc/pmap_clnt.h>
61 #define MAXHOSTLEN 256
63 #define MIN_VERS ((u_long) 0)
64 #define MAX_VERS ((u_long) 4294967295UL)
66 static void udpping (u_short portflag, int argc, char **argv);
67 static void tcpping (u_short portflag, int argc, char **argv);
68 static int pstatus (CLIENT *client, u_long prognum, u_long vers);
69 static void pmapdump (int argc, char **argv);
70 static bool_t reply_proc (void *res, struct sockaddr_in *who);
71 static void brdcst (int argc, char **argv) __attribute__ ((noreturn));
72 static void deletereg (int argc, char **argv);
73 static void usage (void);
74 static u_long getprognum (char *arg);
75 static u_long getvers (char *arg);
76 static void get_inet_address (struct sockaddr_in *addr, char *host);
79 * Functions to be performed.
81 #define NONE 0 /* no function */
82 #define PMAPDUMP 1 /* dump portmapper registrations */
83 #define TCPPING 2 /* ping TCP service */
84 #define UDPPING 3 /* ping UDP service */
85 #define BRDCST 4 /* ping broadcast UDP service */
86 #define DELETES 5 /* delete registration for the service */
89 main (int argc, char **argv)
96 setlocale (LC_ALL, "");
97 textdomain (_libc_intl_domainname);
102 while ((c = getopt (argc, argv, "ptubdn:")) != -1)
108 if (function != NONE)
115 if (function != NONE)
122 if (function != NONE)
129 if (function != NONE)
136 portnum = (u_short) atoi (optarg); /* hope we don't get bogus # */
140 if (function != NONE)
151 if (errflg || function == NONE)
166 pmapdump (argc - optind, argv + optind);
170 udpping (portnum, argc - optind, argv + optind);
174 tcpping (portnum, argc - optind, argv + optind);
183 brdcst (argc - optind, argv + optind);
187 deletereg (argc - optind, argv + optind);
195 udpping (portnum, argc, argv)
201 struct sockaddr_in addr;
202 enum clnt_stat rpc_stat;
204 u_long prognum, vers, minvers, maxvers;
205 int sock = RPC_ANYSOCK;
206 struct rpc_err rpcerr;
209 if (argc < 2 || argc > 3)
214 prognum = getprognum (argv[1]);
215 get_inet_address (&addr, argv[0]);
216 /* Open the socket here so it will survive calls to clnt_destroy */
217 sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
220 perror ("rpcinfo: socket");
227 * A call to version 0 should fail with a program/version
228 * mismatch, and give us the range of versions supported.
230 addr.sin_port = htons (portnum);
233 if ((client = clntudp_create (&addr, prognum, (u_long) 0,
236 clnt_pcreateerror ("rpcinfo");
237 printf (_("program %lu is not available\n"), prognum);
242 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
243 (char *) NULL, (xdrproc_t) xdr_void,
245 if (rpc_stat == RPC_PROGVERSMISMATCH)
247 clnt_geterr (client, &rpcerr);
248 minvers = rpcerr.re_vers.low;
249 maxvers = rpcerr.re_vers.high;
251 else if (rpc_stat == RPC_SUCCESS)
254 * Oh dear, it DOES support version 0.
255 * Let's try version MAX_VERS.
257 addr.sin_port = htons (portnum);
260 if ((client = clntudp_create (&addr, prognum, MAX_VERS,
263 clnt_pcreateerror ("rpcinfo");
264 printf (_("program %lu version %lu is not available\n"),
270 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
271 NULL, (xdrproc_t) xdr_void, NULL, to);
272 if (rpc_stat == RPC_PROGVERSMISMATCH)
274 clnt_geterr (client, &rpcerr);
275 minvers = rpcerr.re_vers.low;
276 maxvers = rpcerr.re_vers.high;
278 else if (rpc_stat == RPC_SUCCESS)
281 * It also supports version MAX_VERS.
282 * Looks like we have a wise guy.
283 * OK, we give them information on all
284 * 4 billion versions they support...
291 (void) pstatus (client, prognum, MAX_VERS);
297 (void) pstatus (client, prognum, (u_long) 0);
300 clnt_destroy (client);
301 for (vers = minvers; vers <= maxvers; vers++)
303 addr.sin_port = htons (portnum);
306 if ((client = clntudp_create (&addr, prognum, vers,
309 clnt_pcreateerror ("rpcinfo");
310 printf (_("program %lu version %lu is not available\n"),
316 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
317 NULL, (xdrproc_t) xdr_void, NULL, to);
318 if (pstatus (client, prognum, vers) < 0)
320 clnt_destroy (client);
325 vers = getvers (argv[2]);
326 addr.sin_port = htons (portnum);
329 if ((client = clntudp_create (&addr, prognum, vers,
332 clnt_pcreateerror ("rpcinfo");
333 printf (_("program %lu version %lu is not available\n"),
339 rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
340 (xdrproc_t) xdr_void, NULL, to);
341 if (pstatus (client, prognum, vers) < 0)
344 (void) close (sock); /* Close it up again */
350 tcpping (portnum, argc, argv)
356 struct sockaddr_in addr;
357 enum clnt_stat rpc_stat;
359 u_long prognum, vers, minvers, maxvers;
360 int sock = RPC_ANYSOCK;
361 struct rpc_err rpcerr;
364 if (argc < 2 || argc > 3)
369 prognum = getprognum (argv[1]);
370 get_inet_address (&addr, argv[0]);
375 * A call to version 0 should fail with a program/version
376 * mismatch, and give us the range of versions supported.
378 addr.sin_port = htons (portnum);
379 if ((client = clnttcp_create (&addr, prognum, MIN_VERS,
380 &sock, 0, 0)) == NULL)
382 clnt_pcreateerror ("rpcinfo");
383 printf (_("program %lu is not available\n"), prognum);
388 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, NULL,
389 (xdrproc_t) xdr_void, NULL, to);
390 if (rpc_stat == RPC_PROGVERSMISMATCH)
392 clnt_geterr (client, &rpcerr);
393 minvers = rpcerr.re_vers.low;
394 maxvers = rpcerr.re_vers.high;
396 else if (rpc_stat == RPC_SUCCESS)
399 * Oh dear, it DOES support version 0.
400 * Let's try version MAX_VERS.
402 addr.sin_port = htons (portnum);
403 if ((client = clnttcp_create (&addr, prognum, MAX_VERS,
404 &sock, 0, 0)) == NULL)
406 clnt_pcreateerror ("rpcinfo");
407 printf (_("program %lu version %lu is not available\n"),
413 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
414 NULL, (xdrproc_t) xdr_void, NULL, to);
415 if (rpc_stat == RPC_PROGVERSMISMATCH)
417 clnt_geterr (client, &rpcerr);
418 minvers = rpcerr.re_vers.low;
419 maxvers = rpcerr.re_vers.high;
421 else if (rpc_stat == RPC_SUCCESS)
424 * It also supports version MAX_VERS.
425 * Looks like we have a wise guy.
426 * OK, we give them information on all
427 * 4 billion versions they support...
434 (void) pstatus (client, prognum, MAX_VERS);
440 (void) pstatus (client, prognum, MIN_VERS);
443 clnt_destroy (client);
445 sock = RPC_ANYSOCK; /* Re-initialize it for later */
446 for (vers = minvers; vers <= maxvers; vers++)
448 addr.sin_port = htons (portnum);
449 if ((client = clnttcp_create (&addr, prognum, vers,
450 &sock, 0, 0)) == NULL)
452 clnt_pcreateerror ("rpcinfo");
453 printf (_("program %lu version %lu is not available\n"),
459 rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
460 (xdrproc_t) xdr_void, NULL, to);
461 if (pstatus (client, prognum, vers) < 0)
463 clnt_destroy (client);
470 vers = getvers (argv[2]);
471 addr.sin_port = htons (portnum);
472 if ((client = clnttcp_create (&addr, prognum, vers, &sock,
475 clnt_pcreateerror ("rpcinfo");
476 printf (_("program %lu version %lu is not available\n"),
482 rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
483 (xdrproc_t) xdr_void, NULL, to);
484 if (pstatus (client, prognum, vers) < 0)
492 * This routine should take a pointer to an "rpc_err" structure, rather than
493 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
494 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
495 * As such, we have to keep the CLIENT structure around in order to print
496 * a good error message.
499 pstatus (client, prognum, vers)
500 register CLIENT *client;
504 struct rpc_err rpcerr;
506 clnt_geterr (client, &rpcerr);
507 if (rpcerr.re_status != RPC_SUCCESS)
509 clnt_perror (client, "rpcinfo");
510 printf (_("program %lu version %lu is not available\n"), prognum, vers);
515 printf (_("program %lu version %lu ready and waiting\n"), prognum, vers);
521 pmapdump (argc, argv)
525 struct sockaddr_in server_addr;
526 register struct hostent *hp;
527 struct pmaplist *head = NULL;
528 int socket = RPC_ANYSOCK;
529 struct timeval minutetimeout;
530 register CLIENT *client;
539 get_inet_address (&server_addr, argv[0]);
542 bzero ((char *) &server_addr, sizeof server_addr);
543 server_addr.sin_family = AF_INET;
544 if ((hp = gethostbyname ("localhost")) != NULL)
545 memcpy ((caddr_t) & server_addr.sin_addr, hp->h_addr,
548 server_addr.sin_addr.s_addr = inet_addr ("0.0.0.0");
550 minutetimeout.tv_sec = 60;
551 minutetimeout.tv_usec = 0;
552 server_addr.sin_port = htons (PMAPPORT);
553 if ((client = clnttcp_create (&server_addr, PMAPPROG,
554 PMAPVERS, &socket, 50, 500)) == NULL)
556 clnt_pcreateerror (_("rpcinfo: can't contact portmapper"));
559 if (clnt_call (client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL,
560 (xdrproc_t) xdr_pmaplist, (caddr_t) &head,
561 minutetimeout) != RPC_SUCCESS)
563 fputs (_("rpcinfo: can't contact portmapper"), stderr);
564 fputs (": ", stderr);
565 clnt_perror (client, "rpcinfo");
570 fputs (_("No remote programs registered.\n"), stdout);
574 fputs (_(" program vers proto port\n"), stdout);
575 for (; head != NULL; head = head->pml_next)
578 head->pml_map.pm_prog,
579 head->pml_map.pm_vers);
580 if (head->pml_map.pm_prot == IPPROTO_UDP)
581 printf ("%6s", "udp");
582 else if (head->pml_map.pm_prot == IPPROTO_TCP)
583 printf ("%6s", "tcp");
585 printf ("%6ld", head->pml_map.pm_prot);
586 printf ("%7ld", head->pml_map.pm_port);
587 rpc = getrpcbynumber (head->pml_map.pm_prog);
589 printf (" %s\n", rpc->r_name);
597 * reply_proc collects replies from the broadcast.
598 * to get a unique list of responses the output of rpcinfo should
599 * be piped through sort(1) and then uniq(1).
604 reply_proc (res, who)
605 void *res; /* Nothing comes back */
606 struct sockaddr_in *who; /* Who sent us the reply */
608 register struct hostent *hp;
610 hp = gethostbyaddr ((char *) &who->sin_addr, sizeof who->sin_addr,
612 printf ("%s %s\n", inet_ntoa (who->sin_addr),
613 (hp == NULL) ? _("(unknown)") : hp->h_name);
622 enum clnt_stat rpc_stat;
623 u_long prognum, vers;
630 prognum = getprognum (argv[0]);
631 vers = getvers (argv[1]);
632 rpc_stat = clnt_broadcast (prognum, vers, NULLPROC, (xdrproc_t) xdr_void,
633 NULL, (xdrproc_t) xdr_void, NULL,
634 (resultproc_t) reply_proc);
635 if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT))
637 fprintf (stderr, _("rpcinfo: broadcast failed: %s\n"),
638 clnt_sperrno (rpc_stat));
645 deletereg (argc, argv)
649 u_long prog_num, version_num;
657 { /* This command allowed only to root */
658 fputs (_("Sorry. You are not root\n"), stderr);
661 prog_num = getprognum (argv[0]);
662 version_num = getvers (argv[1]);
663 if ((pmap_unset (prog_num, version_num)) == 0)
665 fprintf (stderr, _("rpcinfo: Could not delete registration for prog %s version %s\n"),
674 fputs (_("Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"),
676 fputs (_(" rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"),
678 fputs (_(" rpcinfo -p [ host ]\n"), stderr);
679 fputs (_(" rpcinfo -b prognum versnum\n"), stderr);
680 fputs (_(" rpcinfo -d prognum versnum\n"), stderr);
687 register struct rpcent *rpc;
688 register u_long prognum;
692 rpc = getrpcbyname (arg);
695 fprintf (stderr, _("rpcinfo: %s is unknown service\n"), arg);
698 prognum = rpc->r_number;
702 prognum = (u_long) atoi (arg);
712 register u_long vers;
714 vers = (int) atoi (arg);
719 get_inet_address (addr, host)
720 struct sockaddr_in *addr;
723 register struct hostent *hp;
725 bzero ((char *) addr, sizeof *addr);
726 addr->sin_addr.s_addr = (u_long) inet_addr (host);
727 if (addr->sin_addr.s_addr == INADDR_NONE
728 || addr->sin_addr.s_addr == INADDR_ANY)
730 if ((hp = gethostbyname (host)) == NULL)
732 fprintf (stderr, _("rpcinfo: %s is unknown host\n"),
736 memmove ((char *) &addr->sin_addr, hp->h_addr, hp->h_length);
738 addr->sin_family = AF_INET;