diff options
author | Olaf Kirch <okir@suse.de> | 2015-02-03 11:14:28 -0500 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2015-02-04 08:03:38 -0500 |
commit | f83927337df8086b9649714514779d04054c0c64 (patch) | |
tree | 9d9a6427cc993c0b856ed81c60337e6886b0f7d5 | |
parent | 06d07713e661894bf0adc56e5f6f64166c79b679 (diff) | |
download | rpcbind-f83927337df8086b9649714514779d04054c0c64.tar.gz |
rpcinfo: make -t/-u options support IPv6 addresses, too
Currently, rpcinfo supports two ways to test whether a given
service is alive.
For IPv4 hosts, you can use -u and -t. But for IPv6, you need
to use "rpcinfo -a" and specify the host through a universal
address, which is fairly inconvenient.
This patch modifies ip_ping to allow using -u and -t for IPv6
addresses and hosts as well.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r-- | src/rpcinfo.c | 86 |
1 files changed, 79 insertions, 7 deletions
diff --git a/src/rpcinfo.c b/src/rpcinfo.c index 5983b07..3fea753 100644 --- a/src/rpcinfo.c +++ b/src/rpcinfo.c @@ -119,6 +119,7 @@ static CLIENT *clnt_com_create (struct sockaddr_in *, u_long, u_long, int *, char *); static void pmapdump (int, char **); static void get_inet_address (struct sockaddr_in *, char *); +static CLIENT *ip_getclient(const char *hostname, rpcprog_t prognum, rpcvers_t versnum, const char *proto); #endif static bool_t reply_proc (void *, struct netbuf *, struct netconfig *); @@ -411,16 +412,15 @@ ip_ping_one(client, vers) * version 0 calls succeeds, it tries for MAXVERS call and repeats the same. */ static void -ip_ping (portnum, trans, argc, argv) +ip_ping (portnum, proto, argc, argv) u_short portnum; - char *trans; + char *proto; int argc; char **argv; { CLIENT *client; - int fd = RPC_ANYFD; - struct sockaddr_in addr; enum clnt_stat rpc_stat; + const char *hostname; u_long prognum, vers, minvers, maxvers; struct rpc_err rpcerr; int failure = 0; @@ -430,8 +430,9 @@ ip_ping (portnum, trans, argc, argv) usage (); exit (1); } + + hostname = argv[0]; prognum = getprognum (argv[1]); - get_inet_address (&addr, argv[0]); if (argc == 2) { /* Version number not known */ /* @@ -444,8 +445,9 @@ ip_ping (portnum, trans, argc, argv) { vers = getvers (argv[2]); } - addr.sin_port = htons (portnum); - client = clnt_com_create (&addr, prognum, vers, &fd, trans); + + client = ip_getclient(hostname, prognum, vers, proto); + rpc_stat = ip_ping_one(client, vers); if (argc != 2) { @@ -649,6 +651,76 @@ get_inet_address (addr, host) addr->sin_family = AF_INET; } } + +/* + * Try to obtain the address of a given host/program/version, using the + * specified protocol (one of udp or tcp). + * This loops over all netconfig entries (according to the order given by + * netpath and the config file), and tries to resolve the hostname, and obtain + * the address using rpcb_getaddr. + */ +CLIENT * +ip_getclient(hostname, prognum, versnum, proto) + const char *hostname; + rpcprog_t prognum; + rpcvers_t versnum; + const char *proto; +{ + void *handle; + enum clnt_stat saved_stat = RPC_SUCCESS; + struct netconfig *nconf, *result = NULL; + struct netbuf bind_address; + struct sockaddr_storage __sa; + CLIENT *client; + + memset(&bind_address, 0, sizeof(bind_address)); + bind_address.maxlen = sizeof(__sa); + bind_address.buf = &__sa; + + handle = setnetconfig(); + while ((nconf = getnetconfig(handle)) != NULL) + { + if (!strcmp(nconf->nc_proto, proto)) { + if (rpcb_getaddr(prognum, versnum, nconf, &bind_address, hostname)) + { + result = getnetconfigent(nconf->nc_netid); + endnetconfig(handle); + break; + } + + if (rpc_createerr.cf_stat != RPC_UNKNOWNHOST) + { + clnt_pcreateerror (hostname); + exit (1); + } + + saved_stat = rpc_createerr.cf_stat; + } + } + + if (result == NULL) + { + if (saved_stat != RPC_SUCCESS) + { + rpc_createerr.cf_stat = saved_stat; + clnt_pcreateerror (hostname); + } + else + fprintf (stderr, "Cannot find suitable transport for protocol %s\n", proto); + + exit (1); + } + + client = clnt_tli_create(RPC_ANYFD, result, &bind_address, prognum, versnum, 0, 0); + if (client == NULL) + { + clnt_pcreateerror(hostname); + exit (1); + } + + freenetconfigent(result); + return client; +} #endif /* PORTMAP */ static int |