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 #include "../version.h"
62 #define PACKAGE _libc_intl_domainname
64 #define MAXHOSTLEN 256
66 #define MIN_VERS ((u_long) 0)
67 #define MAX_VERS ((u_long) 4294967295UL)
69 static void udpping (u_short portflag, int argc, char **argv);
70 static void tcpping (u_short portflag, int argc, char **argv);
71 static int pstatus (CLIENT *client, u_long prognum, u_long vers);
72 static void pmapdump (int argc, char **argv);
73 static bool_t reply_proc (void *res, struct sockaddr_in *who);
74 static void brdcst (int argc, char **argv) __attribute__ ((noreturn));
75 static void deletereg (int argc, char **argv);
76 static void usage (FILE *stream);
77 static void print_version (void);
78 static u_long getprognum (char *arg);
79 static u_long getvers (char *arg);
80 static void get_inet_address (struct sockaddr_in *addr, char *host);
83 * Functions to be performed.
85 #define NONE 0 /* no function */
86 #define PMAPDUMP 1 /* dump portmapper registrations */
87 #define TCPPING 2 /* ping TCP service */
88 #define UDPPING 3 /* ping UDP service */
89 #define BRDCST 4 /* ping broadcast UDP service */
90 #define DELETES 5 /* delete registration for the service */
93 main (int argc, char **argv)
99 static const struct option long_options[] = {
100 { "help", no_argument, NULL, 'H' },
101 { "version", no_argument, NULL, 'V' },
105 setlocale (LC_ALL, "");
106 textdomain (_libc_intl_domainname);
111 while ((c = getopt_long (argc, argv, "ptubdn:", long_options, NULL)) != -1)
117 if (function != NONE)
124 if (function != NONE)
131 if (function != NONE)
138 if (function != NONE)
145 portnum = (u_short) atoi (optarg); /* hope we don't get bogus # */
149 if (function != NONE)
168 if (errflg || function == NONE)
183 pmapdump (argc - optind, argv + optind);
187 udpping (portnum, argc - optind, argv + optind);
191 tcpping (portnum, argc - optind, argv + optind);
200 brdcst (argc - optind, argv + optind);
204 deletereg (argc - optind, argv + optind);
212 udpping (portnum, argc, argv)
218 struct sockaddr_in addr;
219 enum clnt_stat rpc_stat;
221 u_long prognum, vers, minvers, maxvers;
222 int sock = RPC_ANYSOCK;
223 struct rpc_err rpcerr;
226 if (argc < 2 || argc > 3)
231 prognum = getprognum (argv[1]);
232 get_inet_address (&addr, argv[0]);
233 /* Open the socket here so it will survive calls to clnt_destroy */
234 sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
237 perror ("rpcinfo: socket");
244 * A call to version 0 should fail with a program/version
245 * mismatch, and give us the range of versions supported.
247 addr.sin_port = htons (portnum);
250 if ((client = clntudp_create (&addr, prognum, (u_long) 0,
253 clnt_pcreateerror ("rpcinfo");
254 printf (_("program %lu is not available\n"), prognum);
259 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
260 (char *) NULL, (xdrproc_t) xdr_void,
262 if (rpc_stat == RPC_PROGVERSMISMATCH)
264 clnt_geterr (client, &rpcerr);
265 minvers = rpcerr.re_vers.low;
266 maxvers = rpcerr.re_vers.high;
268 else if (rpc_stat == RPC_SUCCESS)
271 * Oh dear, it DOES support version 0.
272 * Let's try version MAX_VERS.
274 addr.sin_port = htons (portnum);
277 if ((client = clntudp_create (&addr, prognum, MAX_VERS,
280 clnt_pcreateerror ("rpcinfo");
281 printf (_("program %lu version %lu is not available\n"),
287 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
288 NULL, (xdrproc_t) xdr_void, NULL, to);
289 if (rpc_stat == RPC_PROGVERSMISMATCH)
291 clnt_geterr (client, &rpcerr);
292 minvers = rpcerr.re_vers.low;
293 maxvers = rpcerr.re_vers.high;
295 else if (rpc_stat == RPC_SUCCESS)
298 * It also supports version MAX_VERS.
299 * Looks like we have a wise guy.
300 * OK, we give them information on all
301 * 4 billion versions they support...
308 (void) pstatus (client, prognum, MAX_VERS);
314 (void) pstatus (client, prognum, (u_long) 0);
317 clnt_destroy (client);
318 for (vers = minvers; vers <= maxvers; vers++)
320 addr.sin_port = htons (portnum);
323 if ((client = clntudp_create (&addr, prognum, vers,
326 clnt_pcreateerror ("rpcinfo");
327 printf (_("program %lu version %lu is not available\n"),
333 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
334 NULL, (xdrproc_t) xdr_void, NULL, to);
335 if (pstatus (client, prognum, vers) < 0)
337 clnt_destroy (client);
342 vers = getvers (argv[2]);
343 addr.sin_port = htons (portnum);
346 if ((client = clntudp_create (&addr, prognum, vers,
349 clnt_pcreateerror ("rpcinfo");
350 printf (_("program %lu version %lu is not available\n"),
356 rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
357 (xdrproc_t) xdr_void, NULL, to);
358 if (pstatus (client, prognum, vers) < 0)
361 (void) close (sock); /* Close it up again */
367 tcpping (portnum, argc, argv)
373 struct sockaddr_in addr;
374 enum clnt_stat rpc_stat;
376 u_long prognum, vers, minvers, maxvers;
377 int sock = RPC_ANYSOCK;
378 struct rpc_err rpcerr;
381 if (argc < 2 || argc > 3)
386 prognum = getprognum (argv[1]);
387 get_inet_address (&addr, argv[0]);
392 * A call to version 0 should fail with a program/version
393 * mismatch, and give us the range of versions supported.
395 addr.sin_port = htons (portnum);
396 if ((client = clnttcp_create (&addr, prognum, MIN_VERS,
397 &sock, 0, 0)) == NULL)
399 clnt_pcreateerror ("rpcinfo");
400 printf (_("program %lu is not available\n"), prognum);
405 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, NULL,
406 (xdrproc_t) xdr_void, NULL, to);
407 if (rpc_stat == RPC_PROGVERSMISMATCH)
409 clnt_geterr (client, &rpcerr);
410 minvers = rpcerr.re_vers.low;
411 maxvers = rpcerr.re_vers.high;
413 else if (rpc_stat == RPC_SUCCESS)
416 * Oh dear, it DOES support version 0.
417 * Let's try version MAX_VERS.
419 addr.sin_port = htons (portnum);
420 if ((client = clnttcp_create (&addr, prognum, MAX_VERS,
421 &sock, 0, 0)) == NULL)
423 clnt_pcreateerror ("rpcinfo");
424 printf (_("program %lu version %lu is not available\n"),
430 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
431 NULL, (xdrproc_t) xdr_void, NULL, to);
432 if (rpc_stat == RPC_PROGVERSMISMATCH)
434 clnt_geterr (client, &rpcerr);
435 minvers = rpcerr.re_vers.low;
436 maxvers = rpcerr.re_vers.high;
438 else if (rpc_stat == RPC_SUCCESS)
441 * It also supports version MAX_VERS.
442 * Looks like we have a wise guy.
443 * OK, we give them information on all
444 * 4 billion versions they support...
451 (void) pstatus (client, prognum, MAX_VERS);
457 (void) pstatus (client, prognum, MIN_VERS);
460 clnt_destroy (client);
462 sock = RPC_ANYSOCK; /* Re-initialize it for later */
463 for (vers = minvers; vers <= maxvers; vers++)
465 addr.sin_port = htons (portnum);
466 if ((client = clnttcp_create (&addr, prognum, vers,
467 &sock, 0, 0)) == NULL)
469 clnt_pcreateerror ("rpcinfo");
470 printf (_("program %lu version %lu is not available\n"),
476 rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
477 (xdrproc_t) xdr_void, NULL, to);
478 if (pstatus (client, prognum, vers) < 0)
480 clnt_destroy (client);
487 vers = getvers (argv[2]);
488 addr.sin_port = htons (portnum);
489 if ((client = clnttcp_create (&addr, prognum, vers, &sock,
492 clnt_pcreateerror ("rpcinfo");
493 printf (_("program %lu version %lu is not available\n"),
499 rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
500 (xdrproc_t) xdr_void, NULL, to);
501 if (pstatus (client, prognum, vers) < 0)
509 * This routine should take a pointer to an "rpc_err" structure, rather than
510 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
511 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
512 * As such, we have to keep the CLIENT structure around in order to print
513 * a good error message.
516 pstatus (client, prognum, vers)
517 register CLIENT *client;
521 struct rpc_err rpcerr;
523 clnt_geterr (client, &rpcerr);
524 if (rpcerr.re_status != RPC_SUCCESS)
526 clnt_perror (client, "rpcinfo");
527 printf (_("program %lu version %lu is not available\n"), prognum, vers);
532 printf (_("program %lu version %lu ready and waiting\n"), prognum, vers);
538 pmapdump (argc, argv)
542 struct sockaddr_in server_addr;
543 register struct hostent *hp;
544 struct pmaplist *head = NULL;
545 int socket = RPC_ANYSOCK;
546 struct timeval minutetimeout;
547 register CLIENT *client;
556 get_inet_address (&server_addr, argv[0]);
559 bzero ((char *) &server_addr, sizeof server_addr);
560 server_addr.sin_family = AF_INET;
561 if ((hp = gethostbyname ("localhost")) != NULL)
562 memcpy ((caddr_t) & server_addr.sin_addr, hp->h_addr,
565 server_addr.sin_addr.s_addr = inet_addr ("0.0.0.0");
567 minutetimeout.tv_sec = 60;
568 minutetimeout.tv_usec = 0;
569 server_addr.sin_port = htons (PMAPPORT);
570 if ((client = clnttcp_create (&server_addr, PMAPPROG,
571 PMAPVERS, &socket, 50, 500)) == NULL)
573 clnt_pcreateerror (_("rpcinfo: can't contact portmapper"));
576 if (clnt_call (client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL,
577 (xdrproc_t) xdr_pmaplist, (caddr_t) &head,
578 minutetimeout) != RPC_SUCCESS)
580 fputs (_("rpcinfo: can't contact portmapper"), stderr);
581 fputs (": ", stderr);
582 clnt_perror (client, "rpcinfo");
587 fputs (_("No remote programs registered.\n"), stdout);
591 fputs (_(" program vers proto port\n"), stdout);
592 for (; head != NULL; head = head->pml_next)
595 head->pml_map.pm_prog,
596 head->pml_map.pm_vers);
597 if (head->pml_map.pm_prot == IPPROTO_UDP)
598 printf ("%6s", "udp");
599 else if (head->pml_map.pm_prot == IPPROTO_TCP)
600 printf ("%6s", "tcp");
602 printf ("%6ld", head->pml_map.pm_prot);
603 printf ("%7ld", head->pml_map.pm_port);
604 rpc = getrpcbynumber (head->pml_map.pm_prog);
606 printf (" %s\n", rpc->r_name);
614 * reply_proc collects replies from the broadcast.
615 * to get a unique list of responses the output of rpcinfo should
616 * be piped through sort(1) and then uniq(1).
621 reply_proc (res, who)
622 void *res; /* Nothing comes back */
623 struct sockaddr_in *who; /* Who sent us the reply */
625 register struct hostent *hp;
627 hp = gethostbyaddr ((char *) &who->sin_addr, sizeof who->sin_addr,
629 printf ("%s %s\n", inet_ntoa (who->sin_addr),
630 (hp == NULL) ? _("(unknown)") : hp->h_name);
639 enum clnt_stat rpc_stat;
640 u_long prognum, vers;
647 prognum = getprognum (argv[0]);
648 vers = getvers (argv[1]);
649 rpc_stat = clnt_broadcast (prognum, vers, NULLPROC, (xdrproc_t) xdr_void,
650 NULL, (xdrproc_t) xdr_void, NULL,
651 (resultproc_t) reply_proc);
652 if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT))
654 fprintf (stderr, _("rpcinfo: broadcast failed: %s\n"),
655 clnt_sperrno (rpc_stat));
662 deletereg (argc, argv)
666 u_long prog_num, version_num;
674 { /* This command allowed only to root */
675 fputs (_("Sorry. You are not root\n"), stderr);
678 prog_num = getprognum (argv[0]);
679 version_num = getvers (argv[1]);
680 if ((pmap_unset (prog_num, version_num)) == 0)
682 fprintf (stderr, _("rpcinfo: Could not delete registration for prog %s version %s\n"),
691 fputs (_("Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"),
693 fputs (_(" rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"),
695 fputs (_(" rpcinfo -p [ host ]\n"), stream);
696 fputs (_(" rpcinfo -b prognum versnum\n"), stream);
697 fputs (_(" rpcinfo -d prognum versnum\n"), stream);
698 fputc ('\n', stream);
699 fprintf (stream, _("\
700 For bug reporting instructions, please see:\n\
701 <http://www.gnu.org/software/libc/bugs.html>.\n"));
707 printf ("rpcinfo (GNU %s) %s\n", PACKAGE, VERSION);
714 register struct rpcent *rpc;
715 register u_long prognum;
719 rpc = getrpcbyname (arg);
722 fprintf (stderr, _("rpcinfo: %s is unknown service\n"), arg);
725 prognum = rpc->r_number;
729 prognum = (u_long) atoi (arg);
739 register u_long vers;
741 vers = (int) atoi (arg);
746 get_inet_address (addr, host)
747 struct sockaddr_in *addr;
750 register struct hostent *hp;
752 bzero ((char *) addr, sizeof *addr);
753 addr->sin_addr.s_addr = (u_long) inet_addr (host);
754 if (addr->sin_addr.s_addr == INADDR_NONE
755 || addr->sin_addr.s_addr == INADDR_ANY)
757 if ((hp = gethostbyname (host)) == NULL)
759 fprintf (stderr, _("rpcinfo: %s is unknown host\n"),
763 memmove ((char *) &addr->sin_addr, hp->h_addr, hp->h_length);
765 addr->sin_family = AF_INET;