Update.
[glibc.git] / sunrpc / rpcinfo.c
blob7f9966469440c22fc1456dea27086b250104587d
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";
5 #endif
7 /*
8 * Copyright (C) 1986, Sun Microsystems, Inc.
9 */
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.
41 * 2550 Garcia Avenue
42 * Mountain View, California 94043
45 #include <getopt.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <rpc/rpc.h>
49 #include <stdio.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
53 #include <netdb.h>
54 #include <rpc/pmap_prot.h>
55 #include <rpc/pmap_clnt.h>
56 #include <signal.h>
57 #include <ctype.h>
58 #include <locale.h>
59 #include <libintl.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 */
88 int
89 main (int argc, char **argv)
91 register int c;
92 int errflg;
93 int function;
94 u_short portnum;
96 setlocale (LC_ALL, "");
97 textdomain (_libc_intl_domainname);
99 function = NONE;
100 portnum = 0;
101 errflg = 0;
102 while ((c = getopt (argc, argv, "ptubdn:")) != -1)
104 switch (c)
107 case 'p':
108 if (function != NONE)
109 errflg = 1;
110 else
111 function = PMAPDUMP;
112 break;
114 case 't':
115 if (function != NONE)
116 errflg = 1;
117 else
118 function = TCPPING;
119 break;
121 case 'u':
122 if (function != NONE)
123 errflg = 1;
124 else
125 function = UDPPING;
126 break;
128 case 'b':
129 if (function != NONE)
130 errflg = 1;
131 else
132 function = BRDCST;
133 break;
135 case 'n':
136 portnum = (u_short) atoi (optarg); /* hope we don't get bogus # */
137 break;
139 case 'd':
140 if (function != NONE)
141 errflg = 1;
142 else
143 function = DELETES;
144 break;
146 case '?':
147 errflg = 1;
151 if (errflg || function == NONE)
153 usage ();
154 return 1;
157 switch (function)
160 case PMAPDUMP:
161 if (portnum != 0)
163 usage ();
164 return 1;
166 pmapdump (argc - optind, argv + optind);
167 break;
169 case UDPPING:
170 udpping (portnum, argc - optind, argv + optind);
171 break;
173 case TCPPING:
174 tcpping (portnum, argc - optind, argv + optind);
175 break;
177 case BRDCST:
178 if (portnum != 0)
180 usage ();
181 return 1;
183 brdcst (argc - optind, argv + optind);
184 break;
186 case DELETES:
187 deletereg (argc - optind, argv + optind);
188 break;
191 return 0;
194 static void
195 udpping (portnum, argc, argv)
196 u_short portnum;
197 int argc;
198 char **argv;
200 struct timeval to;
201 struct sockaddr_in addr;
202 enum clnt_stat rpc_stat;
203 CLIENT *client;
204 u_long prognum, vers, minvers, maxvers;
205 int sock = RPC_ANYSOCK;
206 struct rpc_err rpcerr;
207 int failure;
209 if (argc < 2 || argc > 3)
211 usage ();
212 exit (1);
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);
218 if (sock < 0)
220 perror ("rpcinfo: socket");
221 exit (1);
223 failure = 0;
224 if (argc == 2)
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);
231 to.tv_sec = 5;
232 to.tv_usec = 0;
233 if ((client = clntudp_create (&addr, prognum, (u_long) 0,
234 to, &sock)) == NULL)
236 clnt_pcreateerror ("rpcinfo");
237 printf (_("program %lu is not available\n"), prognum);
238 exit (1);
240 to.tv_sec = 10;
241 to.tv_usec = 0;
242 rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
243 (char *) NULL, (xdrproc_t) xdr_void,
244 (char *) NULL, to);
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);
258 to.tv_sec = 5;
259 to.tv_usec = 0;
260 if ((client = clntudp_create (&addr, prognum, MAX_VERS,
261 to, &sock)) == NULL)
263 clnt_pcreateerror ("rpcinfo");
264 printf (_("program %lu version %lu is not available\n"),
265 prognum, MAX_VERS);
266 exit (1);
268 to.tv_sec = 10;
269 to.tv_usec = 0;
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...
286 minvers = 0;
287 maxvers = MAX_VERS;
289 else
291 (void) pstatus (client, prognum, MAX_VERS);
292 exit (1);
295 else
297 (void) pstatus (client, prognum, (u_long) 0);
298 exit (1);
300 clnt_destroy (client);
301 for (vers = minvers; vers <= maxvers; vers++)
303 addr.sin_port = htons (portnum);
304 to.tv_sec = 5;
305 to.tv_usec = 0;
306 if ((client = clntudp_create (&addr, prognum, vers,
307 to, &sock)) == NULL)
309 clnt_pcreateerror ("rpcinfo");
310 printf (_("program %lu version %lu is not available\n"),
311 prognum, vers);
312 exit (1);
314 to.tv_sec = 10;
315 to.tv_usec = 0;
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)
319 failure = 1;
320 clnt_destroy (client);
323 else
325 vers = getvers (argv[2]);
326 addr.sin_port = htons (portnum);
327 to.tv_sec = 5;
328 to.tv_usec = 0;
329 if ((client = clntudp_create (&addr, prognum, vers,
330 to, &sock)) == NULL)
332 clnt_pcreateerror ("rpcinfo");
333 printf (_("program %lu version %lu is not available\n"),
334 prognum, vers);
335 exit (1);
337 to.tv_sec = 10;
338 to.tv_usec = 0;
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)
342 failure = 1;
344 (void) close (sock); /* Close it up again */
345 if (failure)
346 exit (1);
349 static void
350 tcpping (portnum, argc, argv)
351 u_short portnum;
352 int argc;
353 char **argv;
355 struct timeval to;
356 struct sockaddr_in addr;
357 enum clnt_stat rpc_stat;
358 CLIENT *client;
359 u_long prognum, vers, minvers, maxvers;
360 int sock = RPC_ANYSOCK;
361 struct rpc_err rpcerr;
362 int failure;
364 if (argc < 2 || argc > 3)
366 usage ();
367 exit (1);
369 prognum = getprognum (argv[1]);
370 get_inet_address (&addr, argv[0]);
371 failure = 0;
372 if (argc == 2)
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);
384 exit (1);
386 to.tv_sec = 10;
387 to.tv_usec = 0;
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"),
408 prognum, MAX_VERS);
409 exit (1);
411 to.tv_sec = 10;
412 to.tv_usec = 0;
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...
429 minvers = 0;
430 maxvers = MAX_VERS;
432 else
434 (void) pstatus (client, prognum, MAX_VERS);
435 exit (1);
438 else
440 (void) pstatus (client, prognum, MIN_VERS);
441 exit (1);
443 clnt_destroy (client);
444 (void) close (sock);
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"),
454 prognum, vers);
455 exit (1);
457 to.tv_usec = 0;
458 to.tv_sec = 10;
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)
462 failure = 1;
463 clnt_destroy (client);
464 (void) close (sock);
465 sock = RPC_ANYSOCK;
468 else
470 vers = getvers (argv[2]);
471 addr.sin_port = htons (portnum);
472 if ((client = clnttcp_create (&addr, prognum, vers, &sock,
473 0, 0)) == NULL)
475 clnt_pcreateerror ("rpcinfo");
476 printf (_("program %lu version %lu is not available\n"),
477 prognum, vers);
478 exit (1);
480 to.tv_usec = 0;
481 to.tv_sec = 10;
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)
485 failure = 1;
487 if (failure)
488 exit (1);
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.
498 static int
499 pstatus (client, prognum, vers)
500 register CLIENT *client;
501 u_long prognum;
502 u_long vers;
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);
511 return -1;
513 else
515 printf (_("program %lu version %lu ready and waiting\n"), prognum, vers);
516 return 0;
520 static void
521 pmapdump (argc, argv)
522 int argc;
523 char **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;
531 struct rpcent *rpc;
533 if (argc > 1)
535 usage ();
536 exit (1);
538 if (argc == 1)
539 get_inet_address (&server_addr, argv[0]);
540 else
542 bzero ((char *) &server_addr, sizeof server_addr);
543 server_addr.sin_family = AF_INET;
544 if ((hp = gethostbyname ("localhost")) != NULL)
545 bcopy (hp->h_addr, (caddr_t) & server_addr.sin_addr,
546 hp->h_length);
547 else
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"));
557 exit (1);
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");
566 exit (1);
568 if (head == NULL)
570 fputs (_("No remote programs registered.\n"), stdout);
572 else
574 fputs (_(" program vers proto port\n"), stdout);
575 for (; head != NULL; head = head->pml_next)
577 printf ("%10ld%5ld",
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");
584 else
585 printf ("%6ld", head->pml_map.pm_prot);
586 printf ("%7ld", head->pml_map.pm_port);
587 rpc = getrpcbynumber (head->pml_map.pm_prog);
588 if (rpc)
589 printf (" %s\n", rpc->r_name);
590 else
591 printf ("\n");
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).
602 /*ARGSUSED */
603 static bool_t
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,
611 AF_INET);
612 printf ("%s %s\n", inet_ntoa (who->sin_addr),
613 (hp == NULL) ? _("(unknown)") : hp->h_name);
614 return FALSE;
617 static void
618 brdcst (argc, argv)
619 int argc;
620 char **argv;
622 enum clnt_stat rpc_stat;
623 u_long prognum, vers;
625 if (argc != 2)
627 usage ();
628 exit (1);
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));
639 exit (1);
641 exit (0);
644 static void
645 deletereg (argc, argv)
646 int argc;
647 char **argv;
649 u_long prog_num, version_num;
651 if (argc != 2)
653 usage ();
654 exit (1);
656 if (getuid ())
657 { /* This command allowed only to root */
658 fputs (_("Sorry. You are not root\n"), stderr);
659 exit (1);
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"),
666 argv[0], argv[1]);
667 exit (1);
671 static void
672 usage ()
674 fputs (_("Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"),
675 stderr);
676 fputs (_(" rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"),
677 stderr);
678 fputs (_(" rpcinfo -p [ host ]\n"), stderr);
679 fputs (_(" rpcinfo -b prognum versnum\n"), stderr);
680 fputs (_(" rpcinfo -d prognum versnum\n"), stderr);
683 static u_long
684 getprognum (arg)
685 char *arg;
687 register struct rpcent *rpc;
688 register u_long prognum;
690 if (isalpha (*arg))
692 rpc = getrpcbyname (arg);
693 if (rpc == NULL)
695 fprintf (stderr, _("rpcinfo: %s is unknown service\n"), arg);
696 exit (1);
698 prognum = rpc->r_number;
700 else
702 prognum = (u_long) atoi (arg);
705 return prognum;
708 static u_long
709 getvers (arg)
710 char *arg;
712 register u_long vers;
714 vers = (int) atoi (arg);
715 return vers;
718 static void
719 get_inet_address (addr, host)
720 struct sockaddr_in *addr;
721 char *host;
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"),
733 host);
734 exit (1);
736 bcopy (hp->h_addr, (char *) &addr->sin_addr, hp->h_length);
738 addr->sin_family = AF_INET;