2 /*static char sccsid[] = "from: @(#)rpcinfo.c 1.22 87/08/12 SMI";*/
3 /*static char sccsid[] = "from: @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC";*/
5 "$FreeBSD: src/usr.bin/rpcinfo/rpcinfo.c,v 1.9.2.1 2001/03/04 09:00:23 kris Exp $";
9 * Copyright (C) 1986, Sun Microsystems, Inc.
13 * rpcinfo: ping a particular rpc program
14 * or dump the portmapper
18 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
19 * unrestricted use provided that this legend is included on all tape
20 * media and as a part of the software program in whole or part. Users
21 * may copy or modify Sun RPC without charge, but are not authorized
22 * to license or distribute it to anyone else except as part of a product or
23 * program developed by the user.
25 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
26 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
29 * Sun RPC is provided with no support and without any obligation on the
30 * part of Sun Microsystems, Inc. to assist in its use, correction,
31 * modification or enhancement.
33 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
34 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
35 * OR ANY PART THEREOF.
37 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
38 * or profits or other special, indirect and consequential damages, even if
39 * Sun has been advised of the possibility of such damages.
41 * Sun Microsystems, Inc.
43 * Mountain View, California 94043
50 #include <sys/socket.h>
52 #include <rpc/pmap_prot.h>
53 #include <rpc/pmap_clnt.h>
57 #include <sys/param.h>
58 #include <arpa/inet.h>
60 #define MAXHOSTLEN 256
62 #define MIN_VERS ((u_long) 0)
63 #define MAX_VERS ((u_long) 4294967295UL)
65 static void udpping(/*u_short portflag, int argc, char **argv*/);
66 static void tcpping(/*u_short portflag, int argc, char **argv*/);
67 static int pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
68 static void pmapdump(/*int argc, char **argv*/);
69 static bool_t reply_proc(/*void *res, struct sockaddr_in *who*/);
70 static void brdcst(/*int argc, char **argv*/);
71 static void deletereg(/* int argc, char **argv */) ;
72 static void usage(/*void*/);
73 static u_long getprognum(/*char *arg*/);
74 static u_long getvers(/*char *arg*/);
75 static void get_inet_address(/*struct sockaddr_in *addr, char *host*/);
78 * Functions to be performed.
80 #define NONE 0 /* no function */
81 #define PMAPDUMP 1 /* dump portmapper registrations */
82 #define TCPPING 2 /* ping TCP service */
83 #define UDPPING 3 /* ping UDP service */
84 #define BRDCST 4 /* ping broadcast UDP service */
85 #define DELETES 5 /* delete registration for the service */
100 while ((c = getopt(argc, argv, "ptubdn:")) != -1) {
104 if (function != NONE)
111 if (function != NONE)
118 if (function != NONE)
125 if (function != NONE)
132 portnum = (u_short) atoi(optarg); /* hope we don't get bogus # */
136 if (function != NONE)
147 if (errflg || function == NONE) {
159 pmapdump(argc - optind, argv + optind);
163 udpping(portnum, argc - optind, argv + optind);
167 tcpping(portnum, argc - optind, argv + optind);
175 brdcst(argc - optind, argv + optind);
179 deletereg(argc - optind, argv + optind);
187 udpping(portnum, argc, argv)
193 struct sockaddr_in addr;
194 enum clnt_stat rpc_stat;
196 u_long prognum, vers, minvers, maxvers;
197 int sock = RPC_ANYSOCK;
198 struct rpc_err rpcerr;
201 if (argc < 2 || argc > 3) {
205 prognum = getprognum(argv[1]);
206 get_inet_address(&addr, argv[0]);
207 /* Open the socket here so it will survive calls to clnt_destroy */
208 sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
210 perror("rpcinfo: socket");
216 * A call to version 0 should fail with a program/version
217 * mismatch, and give us the range of versions supported.
219 addr.sin_port = htons(portnum);
222 if ((client = clntudp_create(&addr, prognum, (u_long)0,
223 to, &sock)) == NULL) {
224 clnt_pcreateerror("rpcinfo");
225 printf("program %lu is not available\n",
231 rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
232 xdr_void, (char *)NULL, to);
233 if (rpc_stat == RPC_PROGVERSMISMATCH) {
234 clnt_geterr(client, &rpcerr);
235 minvers = rpcerr.re_vers.low;
236 maxvers = rpcerr.re_vers.high;
237 } else if (rpc_stat == RPC_SUCCESS) {
239 * Oh dear, it DOES support version 0.
240 * Let's try version MAX_VERS.
242 addr.sin_port = htons(portnum);
245 if ((client = clntudp_create(&addr, prognum, MAX_VERS,
246 to, &sock)) == NULL) {
247 clnt_pcreateerror("rpcinfo");
248 printf("program %lu version %lu is not available\n",
254 rpc_stat = clnt_call(client, NULLPROC, xdr_void,
255 (char *)NULL, xdr_void, (char *)NULL, to);
256 if (rpc_stat == RPC_PROGVERSMISMATCH) {
257 clnt_geterr(client, &rpcerr);
258 minvers = rpcerr.re_vers.low;
259 maxvers = rpcerr.re_vers.high;
260 } else if (rpc_stat == RPC_SUCCESS) {
262 * It also supports version MAX_VERS.
263 * Looks like we have a wise guy.
264 * OK, we give them information on all
265 * 4 billion versions they support...
270 (void) pstatus(client, prognum, MAX_VERS);
274 (void) pstatus(client, prognum, (u_long)0);
277 clnt_destroy(client);
278 for (vers = minvers; vers <= maxvers; vers++) {
279 addr.sin_port = htons(portnum);
282 if ((client = clntudp_create(&addr, prognum, vers,
283 to, &sock)) == NULL) {
284 clnt_pcreateerror("rpcinfo");
285 printf("program %lu version %lu is not available\n",
291 rpc_stat = clnt_call(client, NULLPROC, xdr_void,
292 (char *)NULL, xdr_void, (char *)NULL, to);
293 if (pstatus(client, prognum, vers) < 0)
295 clnt_destroy(client);
299 vers = getvers(argv[2]);
300 addr.sin_port = htons(portnum);
303 if ((client = clntudp_create(&addr, prognum, vers,
304 to, &sock)) == NULL) {
305 clnt_pcreateerror("rpcinfo");
306 printf("program %lu version %lu is not available\n",
312 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
313 xdr_void, (char *)NULL, to);
314 if (pstatus(client, prognum, vers) < 0)
317 (void) close(sock); /* Close it up again */
323 tcpping(portnum, argc, argv)
329 struct sockaddr_in addr;
330 enum clnt_stat rpc_stat;
332 u_long prognum, vers, minvers, maxvers;
333 int sock = RPC_ANYSOCK;
334 struct rpc_err rpcerr;
337 if (argc < 2 || argc > 3) {
341 prognum = getprognum(argv[1]);
342 get_inet_address(&addr, argv[0]);
346 * A call to version 0 should fail with a program/version
347 * mismatch, and give us the range of versions supported.
349 addr.sin_port = htons(portnum);
350 if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
351 &sock, 0, 0)) == NULL) {
352 clnt_pcreateerror("rpcinfo");
353 printf("program %lu is not available\n",
359 rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
360 xdr_void, (char *)NULL, to);
361 if (rpc_stat == RPC_PROGVERSMISMATCH) {
362 clnt_geterr(client, &rpcerr);
363 minvers = rpcerr.re_vers.low;
364 maxvers = rpcerr.re_vers.high;
365 } else if (rpc_stat == RPC_SUCCESS) {
367 * Oh dear, it DOES support version 0.
368 * Let's try version MAX_VERS.
370 addr.sin_port = htons(portnum);
371 if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
372 &sock, 0, 0)) == NULL) {
373 clnt_pcreateerror("rpcinfo");
374 printf("program %lu version %lu is not available\n",
380 rpc_stat = clnt_call(client, NULLPROC, xdr_void,
381 (char *)NULL, xdr_void, (char *)NULL, to);
382 if (rpc_stat == RPC_PROGVERSMISMATCH) {
383 clnt_geterr(client, &rpcerr);
384 minvers = rpcerr.re_vers.low;
385 maxvers = rpcerr.re_vers.high;
386 } else if (rpc_stat == RPC_SUCCESS) {
388 * It also supports version MAX_VERS.
389 * Looks like we have a wise guy.
390 * OK, we give them information on all
391 * 4 billion versions they support...
396 (void) pstatus(client, prognum, MAX_VERS);
400 (void) pstatus(client, prognum, MIN_VERS);
403 clnt_destroy(client);
405 sock = RPC_ANYSOCK; /* Re-initialize it for later */
406 for (vers = minvers; vers <= maxvers; vers++) {
407 addr.sin_port = htons(portnum);
408 if ((client = clnttcp_create(&addr, prognum, vers,
409 &sock, 0, 0)) == NULL) {
410 clnt_pcreateerror("rpcinfo");
411 printf("program %lu version %lu is not available\n",
417 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
418 xdr_void, (char *)NULL, to);
419 if (pstatus(client, prognum, vers) < 0)
421 clnt_destroy(client);
427 vers = getvers(argv[2]);
428 addr.sin_port = htons(portnum);
429 if ((client = clnttcp_create(&addr, prognum, vers, &sock,
431 clnt_pcreateerror("rpcinfo");
432 printf("program %lu version %lu is not available\n",
438 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
439 xdr_void, (char *)NULL, to);
440 if (pstatus(client, prognum, vers) < 0)
448 * This routine should take a pointer to an "rpc_err" structure, rather than
449 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
450 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
451 * As such, we have to keep the CLIENT structure around in order to print
452 * a good error message.
455 pstatus(client, prognum, vers)
456 register CLIENT *client;
460 struct rpc_err rpcerr;
462 clnt_geterr(client, &rpcerr);
463 if (rpcerr.re_status != RPC_SUCCESS) {
464 clnt_perror(client, "rpcinfo");
465 printf("program %lu version %lu is not available\n",
469 printf("program %lu version %lu ready and waiting\n",
480 struct sockaddr_in server_addr;
481 register struct hostent *hp;
482 struct pmaplist *head = NULL;
483 int socket = RPC_ANYSOCK;
484 struct timeval minutetimeout;
485 register CLIENT *client;
493 get_inet_address(&server_addr, argv[0]);
495 bzero((char *)&server_addr, sizeof server_addr);
496 server_addr.sin_family = AF_INET;
497 if ((hp = gethostbyname("localhost")) != NULL)
498 bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
499 MIN(hp->h_length,sizeof(server_addr.sin_addr)));
501 server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
503 minutetimeout.tv_sec = 60;
504 minutetimeout.tv_usec = 0;
505 server_addr.sin_port = htons(PMAPPORT);
506 if ((client = clnttcp_create(&server_addr, PMAPPROG,
507 PMAPVERS, &socket, 50, 500)) == NULL) {
508 clnt_pcreateerror("rpcinfo: can't contact portmapper");
511 if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
512 xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
513 fprintf(stderr, "rpcinfo: can't contact portmapper: ");
514 clnt_perror(client, "rpcinfo");
518 printf("No remote programs registered.\n");
520 printf(" program vers proto port\n");
521 for (; head != NULL; head = head->pml_next) {
523 head->pml_map.pm_prog,
524 head->pml_map.pm_vers);
525 if (head->pml_map.pm_prot == IPPROTO_UDP)
526 printf("%6s", "udp");
527 else if (head->pml_map.pm_prot == IPPROTO_TCP)
528 printf("%6s", "tcp");
530 printf("%6ld", head->pml_map.pm_prot);
531 printf("%7ld", head->pml_map.pm_port);
532 rpc = getrpcbynumber(head->pml_map.pm_prog);
534 printf(" %s\n", rpc->r_name);
542 * reply_proc collects replies from the broadcast.
543 * to get a unique list of responses the output of rpcinfo should
544 * be piped through sort(1) and then uniq(1).
550 void *res; /* Nothing comes back */
551 struct sockaddr_in *who; /* Who sent us the reply */
553 register struct hostent *hp;
555 hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
557 printf("%s %s\n", inet_ntoa(who->sin_addr),
558 (hp == NULL) ? "(unknown)" : hp->h_name);
567 enum clnt_stat rpc_stat;
568 u_long prognum, vers;
574 prognum = getprognum(argv[0]);
575 vers = getvers(argv[1]);
576 rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
577 (char *)NULL, xdr_void, (char *)NULL, reply_proc);
578 if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
579 fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
580 clnt_sperrno(rpc_stat));
587 deletereg(argc, argv)
590 { u_long prog_num, version_num ;
596 if (getuid()) /* This command allowed only to root */
597 errx(1, "sorry, you are not root") ;
598 prog_num = getprognum(argv[0]);
599 version_num = getvers(argv[1]);
600 if ((pmap_unset(prog_num, version_num)) == 0)
601 errx(1, "could not delete registration for prog %s version %s",
608 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
609 "usage: rpcinfo [-n portnum] -u host prognum [versnum]",
610 " rpcinfo [-n portnum] -t host prognum [versnum]",
611 " rpcinfo -p [host]",
612 " rpcinfo -b prognum versnum",
613 " rpcinfo -d prognum versnum");
620 register struct rpcent *rpc;
621 register u_long prognum;
624 rpc = getrpcbyname(arg);
626 errx(1, "%s is unknown service", arg);
627 prognum = rpc->r_number;
629 prognum = (u_long) atoi(arg);
639 register u_long vers;
641 vers = (int) atoi(arg);
646 get_inet_address(addr, host)
647 struct sockaddr_in *addr;
650 register struct hostent *hp;
652 bzero((char *)addr, sizeof *addr);
653 addr->sin_addr.s_addr = (u_long) inet_addr(host);
654 if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
655 if ((hp = gethostbyname(host)) == NULL)
656 errx(1, "%s is unknown host\n", host);
657 bcopy(hp->h_addr, (char *)&addr->sin_addr,
658 MIN(hp->h_length,sizeof(addr->sin_addr)));
660 addr->sin_family = AF_INET;