diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/.cvsignore | 1 | ||||
-rw-r--r-- | tools/Makefile | 4 | ||||
-rw-r--r-- | tools/rpcinfo-flushed.c | 740 |
3 files changed, 743 insertions, 2 deletions
diff --git a/tools/.cvsignore b/tools/.cvsignore index 21a6d396b..88754bc8b 100644 --- a/tools/.cvsignore +++ b/tools/.cvsignore @@ -1,3 +1,4 @@ rpm2header gendepslist xhost+ +rpcinfo-flushed diff --git a/tools/Makefile b/tools/Makefile index 681f5748f..551c4fefc 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -7,7 +7,7 @@ CFLAGS = -Wall .PHONY: clean install $(DIRS) -all: $(BASE)/depslist.ordered $(BASE)/compss $(DIRS) xhost+ install +all: $(BASE)/depslist.ordered $(BASE)/compss $(DIRS) xhost+ rpcinfo-flushed install $(DIRS): make -C $@ @@ -35,4 +35,4 @@ $(BASE)/hdlist.cz: $(BASE)/hdlists $(RPMS) clean: for i in $(DIRS); do $(MAKE) -C $$i clean; done - rm -rf *~ xhost+ ddcprobe/ddcxinfos */*.o + rm -rf *~ xhost+ rpcinfo-flushed ddcprobe/ddcxinfos */*.o diff --git a/tools/rpcinfo-flushed.c b/tools/rpcinfo-flushed.c new file mode 100644 index 000000000..16303406d --- /dev/null +++ b/tools/rpcinfo-flushed.c @@ -0,0 +1,740 @@ +#define _(x) x + +/* @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC */ +#if !defined(lint) && defined (SCCSID) +static char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI"; +#endif + +/* + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +/* + * rpcinfo: ping a particular rpc program + * or dump the portmapper + */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include <getopt.h> +#include <string.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <stdio.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <rpc/pmap_prot.h> +#include <rpc/pmap_clnt.h> +#include <signal.h> +#include <ctype.h> +#include <locale.h> +#include <libintl.h> + +#define MAXHOSTLEN 256 + +#define MIN_VERS ((u_long) 0) +#define MAX_VERS ((u_long) 4294967295UL) + +static void udpping (u_short portflag, int argc, char **argv); +static void tcpping (u_short portflag, int argc, char **argv); +static int pstatus (CLIENT *client, u_long prognum, u_long vers); +static void pmapdump (int argc, char **argv); +static bool_t reply_proc (void *res, struct sockaddr_in *who); +static void brdcst (int argc, char **argv) __attribute__ ((noreturn)); +static void deletereg (int argc, char **argv); +static void usage (void); +static u_long getprognum (char *arg); +static u_long getvers (char *arg); +static void get_inet_address (struct sockaddr_in *addr, char *host); + +/* + * Functions to be performed. + */ +#define NONE 0 /* no function */ +#define PMAPDUMP 1 /* dump portmapper registrations */ +#define TCPPING 2 /* ping TCP service */ +#define UDPPING 3 /* ping UDP service */ +#define BRDCST 4 /* ping broadcast UDP service */ +#define DELETES 5 /* delete registration for the service */ + +int +main (int argc, char **argv) +{ + register int c; + int errflg; + int function; + u_short portnum; + + setlocale (LC_ALL, ""); + + function = NONE; + portnum = 0; + errflg = 0; + while ((c = getopt (argc, argv, "ptubdn:")) != -1) + { + switch (c) + { + + case 'p': + if (function != NONE) + errflg = 1; + else + function = PMAPDUMP; + break; + + case 't': + if (function != NONE) + errflg = 1; + else + function = TCPPING; + break; + + case 'u': + if (function != NONE) + errflg = 1; + else + function = UDPPING; + break; + + case 'b': + if (function != NONE) + errflg = 1; + else + function = BRDCST; + break; + + case 'n': + portnum = (u_short) atoi (optarg); /* hope we don't get bogus # */ + break; + + case 'd': + if (function != NONE) + errflg = 1; + else + function = DELETES; + break; + + case '?': + errflg = 1; + } + } + + if (errflg || function == NONE) + { + usage (); + return 1; + } + + switch (function) + { + + case PMAPDUMP: + if (portnum != 0) + { + usage (); + return 1; + } + pmapdump (argc - optind, argv + optind); + break; + + case UDPPING: + udpping (portnum, argc - optind, argv + optind); + break; + + case TCPPING: + tcpping (portnum, argc - optind, argv + optind); + break; + + case BRDCST: + if (portnum != 0) + { + usage (); + return 1; + } + brdcst (argc - optind, argv + optind); + break; + + case DELETES: + deletereg (argc - optind, argv + optind); + break; + } + + return 0; +} + +static void +udpping (portnum, argc, argv) + u_short portnum; + int argc; + char **argv; +{ + struct timeval to; + struct sockaddr_in addr; + enum clnt_stat rpc_stat; + CLIENT *client; + u_long prognum, vers, minvers, maxvers; + int sock = RPC_ANYSOCK; + struct rpc_err rpcerr; + int failure; + + if (argc < 2 || argc > 3) + { + usage (); + exit (1); + } + prognum = getprognum (argv[1]); + get_inet_address (&addr, argv[0]); + /* Open the socket here so it will survive calls to clnt_destroy */ + sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) + { + perror ("rpcinfo: socket"); + exit (1); + } + failure = 0; + if (argc == 2) + { + /* + * A call to version 0 should fail with a program/version + * mismatch, and give us the range of versions supported. + */ + addr.sin_port = htons (portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create (&addr, prognum, (u_long) 0, + to, &sock)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu is not available\n"), prognum); + exit (1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, + (char *) NULL, (xdrproc_t) xdr_void, + (char *) NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) + { + clnt_geterr (client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } + else if (rpc_stat == RPC_SUCCESS) + { + /* + * Oh dear, it DOES support version 0. + * Let's try version MAX_VERS. + */ + addr.sin_port = htons (portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create (&addr, prognum, MAX_VERS, + to, &sock)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu version %lu is not available\n"), + prognum, MAX_VERS); + exit (1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, + NULL, (xdrproc_t) xdr_void, NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) + { + clnt_geterr (client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } + else if (rpc_stat == RPC_SUCCESS) + { + /* + * It also supports version MAX_VERS. + * Looks like we have a wise guy. + * OK, we give them information on all + * 4 billion versions they support... + */ + minvers = 0; + maxvers = MAX_VERS; + } + else + { + (void) pstatus (client, prognum, MAX_VERS); + exit (1); + } + } + else + { + (void) pstatus (client, prognum, (u_long) 0); + exit (1); + } + clnt_destroy (client); + for (vers = minvers; vers <= maxvers; vers++) + { + addr.sin_port = htons (portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create (&addr, prognum, vers, + to, &sock)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu version %lu is not available\n"), + prognum, vers); + exit (1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, + NULL, (xdrproc_t) xdr_void, NULL, to); + if (pstatus (client, prognum, vers) < 0) + failure = 1; + clnt_destroy (client); + } + } + else + { + vers = getvers (argv[2]); + addr.sin_port = htons (portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create (&addr, prognum, vers, + to, &sock)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu version %lu is not available\n"), + prognum, vers); + exit (1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, to); + if (pstatus (client, prognum, vers) < 0) + failure = 1; + } + (void) close (sock); /* Close it up again */ + if (failure) + exit (1); +} + +static void +tcpping (portnum, argc, argv) + u_short portnum; + int argc; + char **argv; +{ + struct timeval to; + struct sockaddr_in addr; + enum clnt_stat rpc_stat; + CLIENT *client; + u_long prognum, vers, minvers, maxvers; + int sock = RPC_ANYSOCK; + struct rpc_err rpcerr; + int failure; + + if (argc < 2 || argc > 3) + { + usage (); + exit (1); + } + prognum = getprognum (argv[1]); + get_inet_address (&addr, argv[0]); + failure = 0; + if (argc == 2) + { + /* + * A call to version 0 should fail with a program/version + * mismatch, and give us the range of versions supported. + */ + addr.sin_port = htons (portnum); + if ((client = clnttcp_create (&addr, prognum, MIN_VERS, + &sock, 0, 0)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu is not available\n"), prognum); + exit (1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) + { + clnt_geterr (client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } + else if (rpc_stat == RPC_SUCCESS) + { + /* + * Oh dear, it DOES support version 0. + * Let's try version MAX_VERS. + */ + addr.sin_port = htons (portnum); + if ((client = clnttcp_create (&addr, prognum, MAX_VERS, + &sock, 0, 0)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu version %lu is not available\n"), + prognum, MAX_VERS); + exit (1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, + NULL, (xdrproc_t) xdr_void, NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) + { + clnt_geterr (client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } + else if (rpc_stat == RPC_SUCCESS) + { + /* + * It also supports version MAX_VERS. + * Looks like we have a wise guy. + * OK, we give them information on all + * 4 billion versions they support... + */ + minvers = 0; + maxvers = MAX_VERS; + } + else + { + (void) pstatus (client, prognum, MAX_VERS); + exit (1); + } + } + else + { + (void) pstatus (client, prognum, MIN_VERS); + exit (1); + } + clnt_destroy (client); + (void) close (sock); + sock = RPC_ANYSOCK; /* Re-initialize it for later */ + for (vers = minvers; vers <= maxvers; vers++) + { + addr.sin_port = htons (portnum); + if ((client = clnttcp_create (&addr, prognum, vers, + &sock, 0, 0)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu version %lu is not available\n"), + prognum, vers); + exit (1); + } + to.tv_usec = 0; + to.tv_sec = 10; + rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, to); + if (pstatus (client, prognum, vers) < 0) + failure = 1; + clnt_destroy (client); + (void) close (sock); + sock = RPC_ANYSOCK; + } + } + else + { + vers = getvers (argv[2]); + addr.sin_port = htons (portnum); + if ((client = clnttcp_create (&addr, prognum, vers, &sock, + 0, 0)) == NULL) + { + clnt_pcreateerror ("rpcinfo"); + printf (_("program %lu version %lu is not available\n"), + prognum, vers); + exit (1); + } + to.tv_usec = 0; + to.tv_sec = 10; + rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, to); + if (pstatus (client, prognum, vers) < 0) + failure = 1; + } + if (failure) + exit (1); +} + +/* + * This routine should take a pointer to an "rpc_err" structure, rather than + * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to + * a CLIENT structure rather than a pointer to an "rpc_err" structure. + * As such, we have to keep the CLIENT structure around in order to print + * a good error message. + */ +static int +pstatus (client, prognum, vers) + register CLIENT *client; + u_long prognum; + u_long vers; +{ + struct rpc_err rpcerr; + + clnt_geterr (client, &rpcerr); + if (rpcerr.re_status != RPC_SUCCESS) + { + clnt_perror (client, "rpcinfo"); + printf (_("program %lu version %lu is not available\n"), prognum, vers); + return -1; + } + else + { + printf (_("program %lu version %lu ready and waiting\n"), prognum, vers); + return 0; + } +} + +static void +pmapdump (argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in server_addr; + register struct hostent *hp; + struct pmaplist *head = NULL; + int socket = RPC_ANYSOCK; + struct timeval minutetimeout; + register CLIENT *client; + struct rpcent *rpc; + + if (argc > 1) + { + usage (); + exit (1); + } + if (argc == 1) + get_inet_address (&server_addr, argv[0]); + else + { + bzero ((char *) &server_addr, sizeof server_addr); + server_addr.sin_family = AF_INET; + if ((hp = gethostbyname ("localhost")) != NULL) + bcopy (hp->h_addr, (caddr_t) & server_addr.sin_addr, + hp->h_length); + else + server_addr.sin_addr.s_addr = inet_addr ("0.0.0.0"); + } + minutetimeout.tv_sec = 60; + minutetimeout.tv_usec = 0; + server_addr.sin_port = htons (PMAPPORT); + if ((client = clnttcp_create (&server_addr, PMAPPROG, + PMAPVERS, &socket, 50, 500)) == NULL) + { + clnt_pcreateerror (_("rpcinfo: can't contact portmapper")); + exit (1); + } + if (clnt_call (client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_pmaplist, (caddr_t) &head, + minutetimeout) != RPC_SUCCESS) + { + fputs (_("rpcinfo: can't contact portmapper"), stderr); + fputs (": ", stderr); + clnt_perror (client, "rpcinfo"); + exit (1); + } + if (head == NULL) + { + fputs (_("No remote programs registered.\n"), stdout); + } + else + { + fputs (_(" program vers proto port\n"), stdout); + for (; head != NULL; head = head->pml_next) + { + printf ("%10ld%5ld", + head->pml_map.pm_prog, + head->pml_map.pm_vers); + if (head->pml_map.pm_prot == IPPROTO_UDP) + printf ("%6s", "udp"); + else if (head->pml_map.pm_prot == IPPROTO_TCP) + printf ("%6s", "tcp"); + else + printf ("%6ld", head->pml_map.pm_prot); + printf ("%7ld", head->pml_map.pm_port); + rpc = getrpcbynumber (head->pml_map.pm_prog); + if (rpc) + printf (" %s\n", rpc->r_name); + else + printf ("\n"); + } + } +} + +/* + * reply_proc collects replies from the broadcast. + * to get a unique list of responses the output of rpcinfo should + * be piped through sort(1) and then uniq(1). + */ + +/*ARGSUSED */ +static bool_t +reply_proc (res, who) + void *res; /* Nothing comes back */ + struct sockaddr_in *who; /* Who sent us the reply */ +{ + register struct hostent *hp; + + hp = gethostbyaddr ((char *) &who->sin_addr, sizeof who->sin_addr, + AF_INET); + printf ("%s %s\n", inet_ntoa (who->sin_addr), + (hp == NULL) ? _("(unknown)") : hp->h_name); + fflush(stdout); + return FALSE; +} + +static void +brdcst (argc, argv) + int argc; + char **argv; +{ + enum clnt_stat rpc_stat; + u_long prognum, vers; + + if (argc != 2) + { + usage (); + exit (1); + } + prognum = getprognum (argv[0]); + vers = getvers (argv[1]); + rpc_stat = clnt_broadcast (prognum, vers, NULLPROC, (xdrproc_t) xdr_void, + NULL, (xdrproc_t) xdr_void, NULL, + (resultproc_t) reply_proc); + if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) + { + fprintf (stderr, _("rpcinfo: broadcast failed: %s\n"), + clnt_sperrno (rpc_stat)); + exit (1); + } + exit (0); +} + +static void +deletereg (argc, argv) + int argc; + char **argv; +{ + u_long prog_num, version_num; + + if (argc != 2) + { + usage (); + exit (1); + } + if (getuid ()) + { /* This command allowed only to root */ + fputs (_("Sorry. You are not root\n"), stderr); + exit (1); + } + prog_num = getprognum (argv[0]); + version_num = getvers (argv[1]); + if ((pmap_unset (prog_num, version_num)) == 0) + { + fprintf (stderr, _("rpcinfo: Could not delete registration for prog %s version %s\n"), + argv[0], argv[1]); + exit (1); + } +} + +static void +usage () +{ + fputs (_("Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"), + stderr); + fputs (_(" rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"), + stderr); + fputs (_(" rpcinfo -p [ host ]\n"), stderr); + fputs (_(" rpcinfo -b prognum versnum\n"), stderr); + fputs (_(" rpcinfo -d prognum versnum\n"), stderr); +} + +static u_long +getprognum (arg) + char *arg; +{ + register struct rpcent *rpc; + register u_long prognum; + + if (isalpha (*arg)) + { + rpc = getrpcbyname (arg); + if (rpc == NULL) + { + fprintf (stderr, _("rpcinfo: %s is unknown service\n"), arg); + exit (1); + } + prognum = rpc->r_number; + } + else + { + prognum = (u_long) atoi (arg); + } + + return prognum; +} + +static u_long +getvers (arg) + char *arg; +{ + register u_long vers; + + vers = (int) atoi (arg); + return vers; +} + +static void +get_inet_address (addr, host) + struct sockaddr_in *addr; + char *host; +{ + register struct hostent *hp; + + bzero ((char *) addr, sizeof *addr); + addr->sin_addr.s_addr = (u_long) inet_addr (host); + if (addr->sin_addr.s_addr == INADDR_NONE + || addr->sin_addr.s_addr == INADDR_ANY) + { + if ((hp = gethostbyname (host)) == NULL) + { + fprintf (stderr, _("rpcinfo: %s is unknown host\n"), + host); + exit (1); + } + bcopy (hp->h_addr, (char *) &addr->sin_addr, hp->h_length); + } + addr->sin_family = AF_INET; +} |