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
;