diff options
-rw-r--r-- | usr.bin/rpcinfo/rpcinfo.8 | 19 | ||||
-rw-r--r-- | usr.bin/rpcinfo/rpcinfo.c | 261 |
2 files changed, 181 insertions, 99 deletions
diff --git a/usr.bin/rpcinfo/rpcinfo.8 b/usr.bin/rpcinfo/rpcinfo.8 index 81f326c14df..c0a12b2e9b8 100644 --- a/usr.bin/rpcinfo/rpcinfo.8 +++ b/usr.bin/rpcinfo/rpcinfo.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: rpcinfo.8,v 1.6 2000/04/15 11:45:56 aaron Exp $ +.\" $OpenBSD: rpcinfo.8,v 1.7 2000/07/31 16:55:36 deraadt Exp $ .\" from: @(#)rpcinfo.8c 2.2 88/08/03 4.0 RPCSRC; from 1.24 88/02/25 SMI .\" .Dd December 17, 1987 @@ -27,6 +27,9 @@ .Nm rpcinfo .Fl d .Ar program version +.Nm rpcinfo +.Fl s +.Ar program version port .Sh DESCRIPTION .Nm makes an @@ -92,7 +95,19 @@ service of the specified .Ar program and .Ar version . -This option can be exercised only by the superuser. +Registrations which point at ports numbered below 1024 can only be +deleted by the superuser. +.It Fl s +Create a registration for the +.Tn RPC +service of the specified +.Ar program +and +.Ar version , +located at port +.Ar port . +Registrations which point at ports numbered below 1024 can only be +created (or changed) by the superuser. .El .Pp The diff --git a/usr.bin/rpcinfo/rpcinfo.c b/usr.bin/rpcinfo/rpcinfo.c index a7d97f3b8b6..58d3e6cdfe1 100644 --- a/usr.bin/rpcinfo/rpcinfo.c +++ b/usr.bin/rpcinfo/rpcinfo.c @@ -1,9 +1,9 @@ -/* $OpenBSD: rpcinfo.c,v 1.4 1997/01/15 23:43:08 millert Exp $ */ +/* $OpenBSD: rpcinfo.c,v 1.5 2000/07/31 16:55:37 deraadt Exp $ */ #ifndef lint /*static char sccsid[] = "from: @(#)rpcinfo.c 1.22 87/08/12 SMI";*/ /*static char sccsid[] = "from: @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC";*/ -static char rcsid[] = "$OpenBSD: rpcinfo.c,v 1.4 1997/01/15 23:43:08 millert Exp $"; +static char rcsid[] = "$OpenBSD: rpcinfo.c,v 1.5 2000/07/31 16:55:37 deraadt Exp $"; #endif /* @@ -52,6 +52,7 @@ static char rcsid[] = "$OpenBSD: rpcinfo.c,v 1.4 1997/01/15 23:43:08 millert Exp #include <rpc/pmap_clnt.h> #include <signal.h> #include <ctype.h> +#include <errno.h> #include <arpa/inet.h> #define MAXHOSTLEN 256 @@ -59,17 +60,18 @@ static char rcsid[] = "$OpenBSD: rpcinfo.c,v 1.4 1997/01/15 23:43:08 millert Exp #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*/); -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*/); +void udpping(u_short portflag, int argc, char **argv); +void tcpping(u_short portflag, int argc, char **argv); +int pstatus(CLIENT *client, u_long prognum, u_long vers); +void pmapdump(int argc, char **argv); +bool_t reply_proc(void *res, struct sockaddr_in *who); +void brdcst(int argc, char **argv); +void deletereg(int argc, char **argv); +void setreg(int argc, char **argv); +void usage(char *); +int getprognum(char *arg, u_long *ulp); +int getul(char *arg, u_long *ulp); +void get_inet_address(struct sockaddr_in *addr, char *host); /* * Functions to be performed. @@ -80,6 +82,7 @@ static void get_inet_address(/*struct sockaddr_in *addr, char *host*/); #define UDPPING 3 /* ping UDP service */ #define BRDCST 4 /* ping broadcast UDP service */ #define DELETES 5 /* delete registration for the service */ +#define SETS 6 /* set registration for the service */ int main(argc, argv) @@ -92,11 +95,12 @@ main(argc, argv) int errflg; int function; u_short portnum; + u_long tmp; function = NONE; portnum = 0; errflg = 0; - while ((c = getopt(argc, argv, "ptubdn:")) != -1) { + while ((c = getopt(argc, argv, "ptubdsn:")) != -1) { switch (c) { case 'p': @@ -128,7 +132,11 @@ main(argc, argv) break; case 'n': - portnum = (u_short) atoi(optarg); /* hope we don't get bogus # */ + if (getul(optarg, &tmp)) + usage("invalid port number"); + if (tmp >= 65536) + usage("port number out of range"); + portnum = (u_short)tmp; break; case 'd': @@ -138,23 +146,27 @@ main(argc, argv) function = DELETES; break; + case 's': + if (function != NONE) + errflg = 1; + else + function = SETS; + break; + + case '?': errflg = 1; } } - if (errflg || function == NONE) { - usage(); - return (1); - } + if (errflg || function == NONE) + usage(NULL); switch (function) { case PMAPDUMP: - if (portnum != 0) { - usage(); - return (1); - } + if (portnum != 0) + usage(NULL); pmapdump(argc - optind, argv + optind); break; @@ -167,22 +179,25 @@ main(argc, argv) break; case BRDCST: - if (portnum != 0) { - usage(); - return (1); - } + if (portnum != 0) + usage(NULL); + brdcst(argc - optind, argv + optind); break; case DELETES: deletereg(argc - optind, argv + optind); break; + + case SETS: + setreg(argc - optind, argv + optind); + break; } return (0); } -static void +void udpping(portnum, argc, argv) u_short portnum; int argc; @@ -197,11 +212,13 @@ udpping(portnum, argc, argv) struct rpc_err rpcerr; int failure; - if (argc < 2 || argc > 3) { - usage(); - exit(1); - } - prognum = getprognum(argv[1]); + if (argc < 2) + usage("too few arguments"); + if (argc > 3) + usage("too many arguments"); + if (getprognum(argv[1], &prognum)) + usage("program number out of range"); + 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); @@ -295,9 +312,8 @@ udpping(portnum, argc, argv) failure = 1; clnt_destroy(client); } - } - else { - vers = getvers(argv[2]); + } else { + getul(argv[2], &vers); /* XXX */ addr.sin_port = htons(portnum); to.tv_sec = 5; to.tv_usec = 0; @@ -320,7 +336,7 @@ udpping(portnum, argc, argv) exit(1); } -static void +void tcpping(portnum, argc, argv) u_short portnum; int argc; @@ -335,11 +351,13 @@ tcpping(portnum, argc, argv) struct rpc_err rpcerr; int failure; - if (argc < 2 || argc > 3) { - usage(); - exit(1); - } - prognum = getprognum(argv[1]); + if (argc < 2) + usage("too few arguments"); + if (argc > 3) + usage("too many arguments"); + if (getprognum(argv[1], &prognum)) + usage("program number out of range"); + get_inet_address(&addr, argv[0]); failure = 0; if (argc == 2) { @@ -423,9 +441,8 @@ tcpping(portnum, argc, argv) (void) close(sock); sock = RPC_ANYSOCK; } - } - else { - vers = getvers(argv[2]); + } else { + getul(argv[2], &vers); /* XXX */ addr.sin_port = htons(portnum); if ((client = clnttcp_create(&addr, prognum, vers, &sock, 0, 0)) == NULL) { @@ -452,7 +469,7 @@ tcpping(portnum, argc, argv) * As such, we have to keep the CLIENT structure around in order to print * a good error message. */ -static int +int pstatus(client, prognum, vers) register CLIENT *client; u_long prognum; @@ -473,7 +490,7 @@ pstatus(client, prognum, vers) } } -static void +void pmapdump(argc, argv) int argc; char **argv; @@ -486,10 +503,9 @@ pmapdump(argc, argv) register CLIENT *client; struct rpcent *rpc; - if (argc > 1) { - usage(); - exit(1); - } + if (argc > 1) + usage("too many arguments"); + if (argc == 1) get_inet_address(&server_addr, argv[0]); else { @@ -544,12 +560,11 @@ pmapdump(argc, argv) * 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 +bool_t reply_proc(res, who) - void *res; /* Nothing comes back */ - struct sockaddr_in *who; /* Who sent us the reply */ + void *res; /* Nothing comes back */ + struct sockaddr_in *who; /* Who sent us the reply */ { register struct hostent *hp; @@ -560,22 +575,24 @@ reply_proc(res, who) return(FALSE); } -static void +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, xdr_void, - (char *)NULL, xdr_void, (char *)NULL, reply_proc); + u_long prognum, vers_num; + + if (argc != 2) + usage("incorrect number of arguments"); + if (getprognum(argv[1], &prognum)) + usage("program number out of range"); + if (getul(argv[1], &vers_num)) + usage("version number out of range"); + + rpc_stat = clnt_broadcast(prognum, vers_num, NULLPROC, xdr_void, + (char *)NULL, xdr_void, (char *)NULL, + reply_proc); if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) { fprintf(stderr, "rpcinfo: broadcast failed: %s\n", clnt_sperrno(rpc_stat)); @@ -584,38 +601,76 @@ brdcst(argc, argv) exit(0); } -static void +void deletereg(argc, argv) int argc; char **argv; -{ u_long prog_num, version_num ; +{ + u_long prog_num, version_num; + + if (argc != 2) + usage("incorrect number of arguments"); + if (getprognum(argv[0], &prog_num)) + usage("program number out of range"); + if (getul(argv[1], &version_num)) + usage("version number out of range"); - if (argc != 2) { - usage() ; - 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) ; + fprintf(stderr, "rpcinfo: Could not delete " + "registration for prog %s version %s\n", + argv[0], argv[1]); + exit(1); } } -static void -usage() +void +setreg(argc, argv) + int argc; + char **argv; +{ + u_long prog_num, version_num, port_num; + + if (argc != 3) + usage("incorrect number of arguments"); + if (getprognum(argv[0], &prog_num)) + usage("cannot parse program number"); + if (getul(argv[1], &version_num)) + usage("cannot parse version number"); + if (getul(argv[2], &port_num)) + usage("cannot parse port number"); + if (port_num >= 65536) + usage("port number out of range"); + + if ((pmap_set(prog_num, version_num, PF_INET, + (u_short)port_num)) == 0) { + fprintf(stderr, "rpcinfo: Could not set registration " + "for prog %s version %s port %s\n", + argv[0], argv[1], argv[2]); + exit(1); + } +} + +void +usage(char *msg) { - fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"); - fprintf(stderr, " rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"); + if (msg) + fprintf(stderr, + "rpcinfo: %s\n", msg); + fprintf(stderr, + "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"); + fprintf(stderr, + " rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"); fprintf(stderr, " rpcinfo -p [ host ]\n"); fprintf(stderr, " rpcinfo -b prognum versnum\n"); - fprintf(stderr, " rpcinfo -d prognum versnum\n") ; + fprintf(stderr, " rpcinfo -d prognum versnum\n"); + fprintf(stderr, " rpcinfo -s prognum versnum portnum\n"); + exit(1); } -static u_long -getprognum(arg) +int +getprognum(arg, ulp) char *arg; + u_long *ulp; { register struct rpcent *rpc; register u_long prognum; @@ -627,25 +682,36 @@ getprognum(arg) arg); exit(1); } - prognum = rpc->r_number; - } else { - prognum = (u_long) atoi(arg); + *ulp = rpc->r_number; + return 0; } - - return (prognum); + return getul(arg, ulp); } -static u_long -getvers(arg) +int +getul(arg, ulp) char *arg; + u_long *ulp; { - register u_long vers; - - vers = (int) atoi(arg); - return (vers); + u_long ul; + int save_errno = errno; + char *ep; + int ret = 1; + + errno = 0; + ul = strtoul(arg, &ep, 10); + if (arg[0] == '\0' || *ep != '\0') + goto fail; + if (errno == ERANGE && ul == ULONG_MAX) + goto fail; + *ulp = ul; + ret = 0; +fail: + errno = save_errno; + return (ret); } -static void +void get_inet_address(addr, host) struct sockaddr_in *addr; char *host; @@ -655,7 +721,8 @@ get_inet_address(addr, host) bzero((char *)addr, sizeof *addr); if (inet_aton(host, &addr->sin_addr) == 0) { if ((hp = gethostbyname(host)) == NULL) { - fprintf(stderr, "rpcinfo: %s is unknown host\n", host); + fprintf(stderr, "rpcinfo: %s is unknown host\n", + host); exit(1); } bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length); |