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
;