rpcinfo.c (83e6e8406c69690f4340d93976ef64c39406ed01) | rpcinfo.c (e99a5be3952a324ef039e8fe70761aa29850d62e) |
---|---|
1/* $NetBSD: rpcinfo.c,v 1.15 2000/10/04 20:09:05 mjl Exp $ */ | 1#ifndef lint 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";*/ 4static char rcsid[] = "$Id: rpcinfo.c,v 1.1 1993/09/13 23:22:42 jtc Exp $"; 5#endif |
2 3/* | 6 7/* |
8 * Copyright (C) 1986, Sun Microsystems, Inc. 9 */ 10 11/* 12 * rpcinfo: ping a particular rpc program 13 * or dump the portmapper 14 */ 15 16/* |
|
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. | 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. |
10 * | 23 * |
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. | 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. |
14 * | 27 * |
15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. | 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. |
18 * | 31 * |
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. | 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. |
22 * | 35 * |
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. | 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. |
26 * | 39 * |
27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 | 40 * Sun Microsystems, Inc. 41 * 2550 Garcia Avenue 42 * Mountain View, California 94043 43 */ 44 |
32/* 33 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. 34 */ 35 36/* #ident "@(#)rpcinfo.c 1.18 93/07/05 SMI" */ 37 38#if 0 39#ifndef lint 40static char sccsid[] = "@(#)rpcinfo.c 1.16 89/04/05 Copyr 1986 Sun Micro"; 41#endif 42#endif 43 44#include <sys/cdefs.h> 45__FBSDID("$FreeBSD$"); 46 47/* 48 * rpcinfo: ping a particular rpc program 49 * or dump the the registered programs on the remote machine. 50 */ 51 52/* 53 * We are for now defining PORTMAP here. It doesnt even compile 54 * unless it is defined. 55 */ 56#ifndef PORTMAP 57#define PORTMAP 58#endif 59 60/* 61 * If PORTMAP is defined, rpcinfo will talk to both portmapper and 62 * rpcbind programs; else it talks only to rpcbind. In the latter case 63 * all the portmapper specific options such as -u, -t, -p become void. 64 */ 65#include <sys/types.h> 66#include <sys/param.h> 67#include <sys/socket.h> 68#include <sys/un.h> | |
69#include <rpc/rpc.h> 70#include <stdio.h> | 45#include <rpc/rpc.h> 46#include <stdio.h> |
71#include <rpc/rpcb_prot.h> 72#include <rpc/rpcent.h> 73#include <rpc/nettype.h> 74#include <rpc/rpc_com.h> 75#include <stdlib.h> 76#include <string.h> 77#include <unistd.h> 78#include <err.h> 79#include <ctype.h> 80 81#ifdef PORTMAP /* Support for version 2 portmapper */ 82#include <netinet/in.h> | 47#include <sys/socket.h> |
83#include <netdb.h> | 48#include <netdb.h> |
84#include <arpa/inet.h> | |
85#include <rpc/pmap_prot.h> 86#include <rpc/pmap_clnt.h> | 49#include <rpc/pmap_prot.h> 50#include <rpc/pmap_clnt.h> |
87#endif | 51#include <signal.h> 52#include <ctype.h> |
88 89#define MAXHOSTLEN 256 | 53 54#define MAXHOSTLEN 256 |
55 |
|
90#define MIN_VERS ((u_long) 0) 91#define MAX_VERS ((u_long) 4294967295UL) | 56#define MIN_VERS ((u_long) 0) 57#define MAX_VERS ((u_long) 4294967295UL) |
92#define UNKNOWN "unknown" | |
93 | 58 |
59static void udpping(/*u_short portflag, int argc, char **argv*/); 60static void tcpping(/*u_short portflag, int argc, char **argv*/); 61static int pstatus(/*CLIENT *client, u_long prognum, u_long vers*/); 62static void pmapdump(/*int argc, char **argv*/); 63static bool_t reply_proc(/*void *res, struct sockaddr_in *who*/); 64static void brdcst(/*int argc, char **argv*/); 65static void deletereg(/* int argc, char **argv */) ; 66static void usage(/*void*/); 67static u_long getprognum(/*char *arg*/); 68static u_long getvers(/*char *arg*/); 69static void get_inet_address(/*struct sockaddr_in *addr, char *host*/); 70extern u_long inet_addr(); /* in 4.2BSD, arpa/inet.h called that a in_addr */ 71extern char *inet_ntoa(); 72 |
|
94/* 95 * Functions to be performed. 96 */ 97#define NONE 0 /* no function */ 98#define PMAPDUMP 1 /* dump portmapper registrations */ 99#define TCPPING 2 /* ping TCP service */ 100#define UDPPING 3 /* ping UDP service */ | 73/* 74 * Functions to be performed. 75 */ 76#define NONE 0 /* no function */ 77#define PMAPDUMP 1 /* dump portmapper registrations */ 78#define TCPPING 2 /* ping TCP service */ 79#define UDPPING 3 /* ping UDP service */ |
101#define BROADCAST 4 /* ping broadcast service */ 102#define DELETES 5 /* delete registration for the service */ 103#define ADDRPING 6 /* pings at the given address */ 104#define PROGPING 7 /* pings a program on a given host */ 105#define RPCBDUMP 8 /* dump rpcbind registrations */ 106#define RPCBDUMP_SHORT 9 /* dump rpcbind registrations - short version */ 107#define RPCBADDRLIST 10 /* dump addr list about one prog */ 108#define RPCBGETSTAT 11 /* Get statistics */ | 80#define BRDCST 4 /* ping broadcast UDP service */ 81#define DELETES 5 /* delete registration for the service */ |
109 | 82 |
110struct netidlist { 111 char *netid; 112 struct netidlist *next; 113}; 114 115struct verslist { 116 int vers; 117 struct verslist *next; 118}; 119 120struct rpcbdump_short { 121 u_long prog; 122 struct verslist *vlist; 123 struct netidlist *nlist; 124 struct rpcbdump_short *next; 125 char *owner; 126}; 127 128 129 130#ifdef PORTMAP 131static void ip_ping(u_short, char *, int, char **); 132static CLIENT *clnt_com_create(struct sockaddr_in *, u_long, u_long, int *, 133 char *); 134static void pmapdump(int, char **); 135static void get_inet_address(struct sockaddr_in *, char *); 136#endif 137 138static bool_t reply_proc(void *, struct netbuf *, struct netconfig *); 139static void brdcst(int, char **); 140static void addrping(char *, char *, int, char **); 141static void progping(char *, int, char **); 142static CLIENT *clnt_addr_create(char *, struct netconfig *, u_long, u_long); 143static CLIENT *clnt_rpcbind_create(char *, int, struct netbuf **); 144static CLIENT *getclnthandle(char *, struct netconfig *, u_long, 145 struct netbuf **); 146static CLIENT *local_rpcb(u_long, u_long); 147static int pstatus(CLIENT *, u_long, u_long); 148static void rpcbdump(int, char *, int, char **); 149static void rpcbgetstat(int, char **); 150static void rpcbaddrlist(char *, int, char **); 151static void deletereg(char *, int, char **); 152static void print_rmtcallstat(int, rpcb_stat *); 153static void print_getaddrstat(int, rpcb_stat *); 154static void usage(void); 155static u_long getprognum(char *); 156static u_long getvers(char *); 157static char *spaces(int); 158static bool_t add_version(struct rpcbdump_short *, u_long); 159static bool_t add_netid(struct rpcbdump_short *, char *); 160 | |
161int | 83int |
162main(int argc, char **argv) | 84main(argc, argv) 85 int argc; 86 char **argv; |
163{ 164 register int c; | 87{ 88 register int c; |
89 extern char *optarg; 90 extern int optind; |
|
165 int errflg; 166 int function; | 91 int errflg; 92 int function; |
167 char *netid = NULL; 168 char *address = NULL; 169#ifdef PORTMAP 170 char *strptr; 171 u_short portnum = 0; 172#endif | 93 u_short portnum; |
173 174 function = NONE; | 94 95 function = NONE; |
96 portnum = 0; |
|
175 errflg = 0; | 97 errflg = 0; |
176#ifdef PORTMAP 177 while ((c = getopt(argc, argv, "a:bdlmn:pstT:u")) != -1) { 178#else 179 while ((c = getopt(argc, argv, "a:bdlmn:sT:")) != -1) { 180#endif | 98 while ((c = getopt(argc, argv, "ptubdn:")) != EOF) { |
181 switch (c) { | 99 switch (c) { |
182#ifdef PORTMAP | 100 |
183 case 'p': 184 if (function != NONE) 185 errflg = 1; 186 else 187 function = PMAPDUMP; 188 break; 189 190 case 't': --- 5 unchanged lines hidden (view full) --- 196 197 case 'u': 198 if (function != NONE) 199 errflg = 1; 200 else 201 function = UDPPING; 202 break; 203 | 101 case 'p': 102 if (function != NONE) 103 errflg = 1; 104 else 105 function = PMAPDUMP; 106 break; 107 108 case 't': --- 5 unchanged lines hidden (view full) --- 114 115 case 'u': 116 if (function != NONE) 117 errflg = 1; 118 else 119 function = UDPPING; 120 break; 121 |
204 case 'n': 205 portnum = (u_short) strtol(optarg, &strptr, 10); 206 if (strptr == optarg || *strptr != '\0') 207 errx(1, "%s is illegal port number", optarg); 208 break; 209#endif 210 case 'a': 211 address = optarg; 212 if (function != NONE) 213 errflg = 1; 214 else 215 function = ADDRPING; 216 break; | |
217 case 'b': 218 if (function != NONE) 219 errflg = 1; 220 else | 122 case 'b': 123 if (function != NONE) 124 errflg = 1; 125 else |
221 function = BROADCAST; | 126 function = BRDCST; |
222 break; 223 | 127 break; 128 |
129 case 'n': 130 portnum = (u_short) atoi(optarg); /* hope we don't get bogus # */ 131 break; 132 |
|
224 case 'd': 225 if (function != NONE) 226 errflg = 1; 227 else 228 function = DELETES; 229 break; 230 | 133 case 'd': 134 if (function != NONE) 135 errflg = 1; 136 else 137 function = DELETES; 138 break; 139 |
231 case 'l': 232 if (function != NONE) 233 errflg = 1; 234 else 235 function = RPCBADDRLIST; 236 break; 237 238 case 'm': 239 if (function != NONE) 240 errflg = 1; 241 else 242 function = RPCBGETSTAT; 243 break; 244 245 case 's': 246 if (function != NONE) 247 errflg = 1; 248 else 249 function = RPCBDUMP_SHORT; 250 break; 251 252 case 'T': 253 netid = optarg; 254 break; | |
255 case '?': 256 errflg = 1; | 140 case '?': 141 errflg = 1; |
257 break; | |
258 } 259 } 260 | 142 } 143 } 144 |
261 if (errflg || ((function == ADDRPING) && !netid)) | 145 if (errflg || function == NONE) { |
262 usage(); | 146 usage(); |
263 264 if (function == NONE) { 265 if (argc - optind > 1) 266 function = PROGPING; 267 else 268 function = RPCBDUMP; | 147 return (1); |
269 } 270 271 switch (function) { | 148 } 149 150 switch (function) { |
272#ifdef PORTMAP | 151 |
273 case PMAPDUMP: | 152 case PMAPDUMP: |
274 if (portnum != 0) | 153 if (portnum != 0) { |
275 usage(); | 154 usage(); |
155 return (1); 156 } |
|
276 pmapdump(argc - optind, argv + optind); 277 break; 278 279 case UDPPING: | 157 pmapdump(argc - optind, argv + optind); 158 break; 159 160 case UDPPING: |
280 ip_ping(portnum, "udp", argc - optind, argv + optind); | 161 udpping(portnum, argc - optind, argv + optind); |
281 break; 282 283 case TCPPING: | 162 break; 163 164 case TCPPING: |
284 ip_ping(portnum, "tcp", argc - optind, argv + optind); | 165 tcpping(portnum, argc - optind, argv + optind); |
285 break; | 166 break; |
286#endif 287 case BROADCAST: | 167 168 case BRDCST: 169 if (portnum != 0) { 170 usage(); 171 return (1); 172 } |
288 brdcst(argc - optind, argv + optind); 289 break; | 173 brdcst(argc - optind, argv + optind); 174 break; |
175 |
|
290 case DELETES: | 176 case DELETES: |
291 deletereg(netid, argc - optind, argv + optind); | 177 deletereg(argc - optind, argv + optind); |
292 break; | 178 break; |
293 case ADDRPING: 294 addrping(address, netid, argc - optind, argv + optind); 295 break; 296 case PROGPING: 297 progping(netid, argc - optind, argv + optind); 298 break; 299 case RPCBDUMP: 300 case RPCBDUMP_SHORT: 301 rpcbdump(function, netid, argc - optind, argv + optind); 302 break; 303 case RPCBGETSTAT: 304 rpcbgetstat(argc - optind, argv + optind); 305 break; 306 case RPCBADDRLIST: 307 rpcbaddrlist(netid, argc - optind, argv + optind); 308 break; | |
309 } | 179 } |
180 |
|
310 return (0); 311} | 181 return (0); 182} |
312 313static CLIENT * 314local_rpcb(u_long prog, u_long vers) | 183 184static void 185udpping(portnum, argc, argv) 186 u_short portnum; 187 int argc; 188 char **argv; |
315{ | 189{ |
316 void *localhandle; 317 struct netconfig *nconf; 318 CLIENT *clnt; 319 320 localhandle = setnetconfig(); 321 while ((nconf = getnetconfig(localhandle)) != NULL) { 322 if (nconf->nc_protofmly != NULL && 323 strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) 324 break; | 190 struct timeval to; 191 struct sockaddr_in addr; 192 enum clnt_stat rpc_stat; 193 CLIENT *client; 194 u_long prognum, vers, minvers, maxvers; 195 int sock = RPC_ANYSOCK; 196 struct rpc_err rpcerr; 197 int failure; 198 199 if (argc < 2 || argc > 3) { 200 usage(); 201 exit(1); |
325 } | 202 } |
326 if (nconf == NULL) { 327 warnx("getnetconfig: %s", nc_sperror()); 328 return (NULL); | 203 prognum = getprognum(argv[1]); 204 get_inet_address(&addr, argv[0]); 205 /* Open the socket here so it will survive calls to clnt_destroy */ 206 sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP); 207 if (sock < 0) { 208 perror("rpcinfo: socket"); 209 exit(1); |
329 } | 210 } |
330 331 clnt = clnt_tp_create(NULL, prog, vers, nconf); 332 endnetconfig(localhandle); 333 return clnt; 334} 335 336#ifdef PORTMAP 337static CLIENT * 338clnt_com_create(struct sockaddr_in *addr, u_long prog, u_long vers, 339 int *fdp, char *trans) 340{ 341 CLIENT *clnt; 342 343 if (strcmp(trans, "tcp") == 0) { 344 clnt = clnttcp_create(addr, prog, vers, fdp, 0, 0); 345 } else { 346 struct timeval to; 347 | 211 failure = 0; 212 if (argc == 2) { 213 /* 214 * A call to version 0 should fail with a program/version 215 * mismatch, and give us the range of versions supported. 216 */ 217 addr.sin_port = htons(portnum); |
348 to.tv_sec = 5; 349 to.tv_usec = 0; | 218 to.tv_sec = 5; 219 to.tv_usec = 0; |
350 clnt = clntudp_create(addr, prog, vers, to, fdp); | 220 if ((client = clntudp_create(&addr, prognum, (u_long)0, 221 to, &sock)) == NULL) { 222 clnt_pcreateerror("rpcinfo"); 223 printf("program %lu is not available\n", 224 prognum); 225 exit(1); 226 } 227 to.tv_sec = 10; 228 to.tv_usec = 0; 229 rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL, 230 xdr_void, (char *)NULL, to); 231 if (rpc_stat == RPC_PROGVERSMISMATCH) { 232 clnt_geterr(client, &rpcerr); 233 minvers = rpcerr.re_vers.low; 234 maxvers = rpcerr.re_vers.high; 235 } else if (rpc_stat == RPC_SUCCESS) { 236 /* 237 * Oh dear, it DOES support version 0. 238 * Let's try version MAX_VERS. 239 */ 240 addr.sin_port = htons(portnum); 241 to.tv_sec = 5; 242 to.tv_usec = 0; 243 if ((client = clntudp_create(&addr, prognum, MAX_VERS, 244 to, &sock)) == NULL) { 245 clnt_pcreateerror("rpcinfo"); 246 printf("program %lu version %lu is not available\n", 247 prognum, MAX_VERS); 248 exit(1); 249 } 250 to.tv_sec = 10; 251 to.tv_usec = 0; 252 rpc_stat = clnt_call(client, NULLPROC, xdr_void, 253 (char *)NULL, xdr_void, (char *)NULL, to); 254 if (rpc_stat == RPC_PROGVERSMISMATCH) { 255 clnt_geterr(client, &rpcerr); 256 minvers = rpcerr.re_vers.low; 257 maxvers = rpcerr.re_vers.high; 258 } else if (rpc_stat == RPC_SUCCESS) { 259 /* 260 * It also supports version MAX_VERS. 261 * Looks like we have a wise guy. 262 * OK, we give them information on all 263 * 4 billion versions they support... 264 */ 265 minvers = 0; 266 maxvers = MAX_VERS; 267 } else { 268 (void) pstatus(client, prognum, MAX_VERS); 269 exit(1); 270 } 271 } else { 272 (void) pstatus(client, prognum, (u_long)0); 273 exit(1); 274 } 275 clnt_destroy(client); 276 for (vers = minvers; vers <= maxvers; vers++) { 277 addr.sin_port = htons(portnum); 278 to.tv_sec = 5; 279 to.tv_usec = 0; 280 if ((client = clntudp_create(&addr, prognum, vers, 281 to, &sock)) == NULL) { 282 clnt_pcreateerror("rpcinfo"); 283 printf("program %lu version %lu is not available\n", 284 prognum, vers); 285 exit(1); 286 } 287 to.tv_sec = 10; 288 to.tv_usec = 0; 289 rpc_stat = clnt_call(client, NULLPROC, xdr_void, 290 (char *)NULL, xdr_void, (char *)NULL, to); 291 if (pstatus(client, prognum, vers) < 0) 292 failure = 1; 293 clnt_destroy(client); 294 } |
351 } | 295 } |
352 if (clnt == (CLIENT *)NULL) { 353 clnt_pcreateerror("rpcinfo"); 354 if (vers == MIN_VERS) 355 printf("program %lu is not available\n", prog); 356 else | 296 else { 297 vers = getvers(argv[2]); 298 addr.sin_port = htons(portnum); 299 to.tv_sec = 5; 300 to.tv_usec = 0; 301 if ((client = clntudp_create(&addr, prognum, vers, 302 to, &sock)) == NULL) { 303 clnt_pcreateerror("rpcinfo"); |
357 printf("program %lu version %lu is not available\n", | 304 printf("program %lu version %lu is not available\n", |
358 prog, vers); 359 exit(1); | 305 prognum, vers); 306 exit(1); 307 } 308 to.tv_sec = 10; 309 to.tv_usec = 0; 310 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL, 311 xdr_void, (char *)NULL, to); 312 if (pstatus(client, prognum, vers) < 0) 313 failure = 1; |
360 } | 314 } |
361 return (clnt); | 315 (void) close(sock); /* Close it up again */ 316 if (failure) 317 exit(1); |
362} 363 | 318} 319 |
364/* 365 * If portnum is 0, then go and get the address from portmapper, which happens 366 * transparently through clnt*_create(); If version number is not given, it 367 * tries to find out the version number by making a call to version 0 and if 368 * that fails, it obtains the high order and the low order version number. If 369 * version 0 calls succeeds, it tries for MAXVERS call and repeats the same. 370 */ | |
371static void | 320static void |
372ip_ping(u_short portnum, char *trans, int argc, char **argv) | 321tcpping(portnum, argc, argv) 322 u_short portnum; 323 int argc; 324 char **argv; |
373{ | 325{ |
374 CLIENT *client; 375 int fd = RPC_ANYFD; | |
376 struct timeval to; 377 struct sockaddr_in addr; 378 enum clnt_stat rpc_stat; | 326 struct timeval to; 327 struct sockaddr_in addr; 328 enum clnt_stat rpc_stat; |
329 CLIENT *client; |
|
379 u_long prognum, vers, minvers, maxvers; | 330 u_long prognum, vers, minvers, maxvers; |
331 int sock = RPC_ANYSOCK; |
|
380 struct rpc_err rpcerr; | 332 struct rpc_err rpcerr; |
381 int failure = 0; | 333 int failure; |
382 | 334 |
383 if (argc < 2 || argc > 3) | 335 if (argc < 2 || argc > 3) { |
384 usage(); | 336 usage(); |
385 to.tv_sec = 10; 386 to.tv_usec = 0; | 337 exit(1); 338 } |
387 prognum = getprognum(argv[1]); 388 get_inet_address(&addr, argv[0]); | 339 prognum = getprognum(argv[1]); 340 get_inet_address(&addr, argv[0]); |
389 if (argc == 2) { /* Version number not known */ | 341 failure = 0; 342 if (argc == 2) { |
390 /* 391 * A call to version 0 should fail with a program/version 392 * mismatch, and give us the range of versions supported. 393 */ | 343 /* 344 * A call to version 0 should fail with a program/version 345 * mismatch, and give us the range of versions supported. 346 */ |
394 vers = MIN_VERS; 395 } else { 396 vers = getvers(argv[2]); 397 } 398 addr.sin_port = htons(portnum); 399 client = clnt_com_create(&addr, prognum, vers, &fd, trans); 400 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 401 (char *)NULL, (xdrproc_t) xdr_void, (char *)NULL, 402 to); 403 if (argc != 2) { 404 /* Version number was known */ 405 if (pstatus(client, prognum, vers) < 0) 406 exit(1); 407 (void) CLNT_DESTROY(client); 408 return; 409 } 410 /* Version number not known */ 411 (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL); 412 if (rpc_stat == RPC_PROGVERSMISMATCH) { 413 clnt_geterr(client, &rpcerr); 414 minvers = rpcerr.re_vers.low; 415 maxvers = rpcerr.re_vers.high; 416 } else if (rpc_stat == RPC_SUCCESS) { 417 /* 418 * Oh dear, it DOES support version 0. 419 * Let's try version MAX_VERS. 420 */ 421 (void) CLNT_DESTROY(client); | |
422 addr.sin_port = htons(portnum); | 347 addr.sin_port = htons(portnum); |
423 client = clnt_com_create(&addr, prognum, MAX_VERS, &fd, trans); 424 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 425 (char *)NULL, (xdrproc_t) xdr_void, 426 (char *)NULL, to); | 348 if ((client = clnttcp_create(&addr, prognum, MIN_VERS, 349 &sock, 0, 0)) == NULL) { 350 clnt_pcreateerror("rpcinfo"); 351 printf("program %lu is not available\n", 352 prognum); 353 exit(1); 354 } 355 to.tv_sec = 10; 356 to.tv_usec = 0; 357 rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL, 358 xdr_void, (char *)NULL, to); |
427 if (rpc_stat == RPC_PROGVERSMISMATCH) { 428 clnt_geterr(client, &rpcerr); 429 minvers = rpcerr.re_vers.low; 430 maxvers = rpcerr.re_vers.high; 431 } else if (rpc_stat == RPC_SUCCESS) { 432 /* | 359 if (rpc_stat == RPC_PROGVERSMISMATCH) { 360 clnt_geterr(client, &rpcerr); 361 minvers = rpcerr.re_vers.low; 362 maxvers = rpcerr.re_vers.high; 363 } else if (rpc_stat == RPC_SUCCESS) { 364 /* |
433 * It also supports version MAX_VERS. 434 * Looks like we have a wise guy. 435 * OK, we give them information on all 436 * 4 billion versions they support... | 365 * Oh dear, it DOES support version 0. 366 * Let's try version MAX_VERS. |
437 */ | 367 */ |
438 minvers = 0; 439 maxvers = MAX_VERS; | 368 addr.sin_port = htons(portnum); 369 if ((client = clnttcp_create(&addr, prognum, MAX_VERS, 370 &sock, 0, 0)) == NULL) { 371 clnt_pcreateerror("rpcinfo"); 372 printf("program %lu version %lu is not available\n", 373 prognum, MAX_VERS); 374 exit(1); 375 } 376 to.tv_sec = 10; 377 to.tv_usec = 0; 378 rpc_stat = clnt_call(client, NULLPROC, xdr_void, 379 (char *)NULL, xdr_void, (char *)NULL, to); 380 if (rpc_stat == RPC_PROGVERSMISMATCH) { 381 clnt_geterr(client, &rpcerr); 382 minvers = rpcerr.re_vers.low; 383 maxvers = rpcerr.re_vers.high; 384 } else if (rpc_stat == RPC_SUCCESS) { 385 /* 386 * It also supports version MAX_VERS. 387 * Looks like we have a wise guy. 388 * OK, we give them information on all 389 * 4 billion versions they support... 390 */ 391 minvers = 0; 392 maxvers = MAX_VERS; 393 } else { 394 (void) pstatus(client, prognum, MAX_VERS); 395 exit(1); 396 } |
440 } else { | 397 } else { |
441 (void) pstatus(client, prognum, MAX_VERS); | 398 (void) pstatus(client, prognum, MIN_VERS); |
442 exit(1); 443 } | 399 exit(1); 400 } |
444 } else { 445 (void) pstatus(client, prognum, (u_long)0); 446 exit(1); | 401 clnt_destroy(client); 402 (void) close(sock); 403 sock = RPC_ANYSOCK; /* Re-initialize it for later */ 404 for (vers = minvers; vers <= maxvers; vers++) { 405 addr.sin_port = htons(portnum); 406 if ((client = clnttcp_create(&addr, prognum, vers, 407 &sock, 0, 0)) == NULL) { 408 clnt_pcreateerror("rpcinfo"); 409 printf("program %lu version %lu is not available\n", 410 prognum, vers); 411 exit(1); 412 } 413 to.tv_usec = 0; 414 to.tv_sec = 10; 415 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL, 416 xdr_void, (char *)NULL, to); 417 if (pstatus(client, prognum, vers) < 0) 418 failure = 1; 419 clnt_destroy(client); 420 (void) close(sock); 421 sock = RPC_ANYSOCK; 422 } |
447 } | 423 } |
448 (void) CLNT_DESTROY(client); 449 for (vers = minvers; vers <= maxvers; vers++) { | 424 else { 425 vers = getvers(argv[2]); |
450 addr.sin_port = htons(portnum); | 426 addr.sin_port = htons(portnum); |
451 client = clnt_com_create(&addr, prognum, vers, &fd, trans); 452 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 453 (char *)NULL, (xdrproc_t) xdr_void, 454 (char *)NULL, to); | 427 if ((client = clnttcp_create(&addr, prognum, vers, &sock, 428 0, 0)) == NULL) { 429 clnt_pcreateerror("rpcinfo"); 430 printf("program %lu version %lu is not available\n", 431 prognum, vers); 432 exit(1); 433 } 434 to.tv_usec = 0; 435 to.tv_sec = 10; 436 rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL, 437 xdr_void, (char *)NULL, to); |
455 if (pstatus(client, prognum, vers) < 0) | 438 if (pstatus(client, prognum, vers) < 0) |
456 failure = 1; 457 (void) CLNT_DESTROY(client); | 439 failure = 1; |
458 } 459 if (failure) 460 exit(1); | 440 } 441 if (failure) 442 exit(1); |
461 (void) close(fd); 462 return; | |
463} 464 465/* | 443} 444 445/* |
466 * Dump all the portmapper registerations | 446 * This routine should take a pointer to an "rpc_err" structure, rather than 447 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to 448 * a CLIENT structure rather than a pointer to an "rpc_err" structure. 449 * As such, we have to keep the CLIENT structure around in order to print 450 * a good error message. |
467 */ | 451 */ |
452static int 453pstatus(client, prognum, vers) 454 register CLIENT *client; 455 u_long prognum; 456 u_long vers; 457{ 458 struct rpc_err rpcerr; 459 460 clnt_geterr(client, &rpcerr); 461 if (rpcerr.re_status != RPC_SUCCESS) { 462 clnt_perror(client, "rpcinfo"); 463 printf("program %lu version %lu is not available\n", 464 prognum, vers); 465 return (-1); 466 } else { 467 printf("program %lu version %lu ready and waiting\n", 468 prognum, vers); 469 return (0); 470 } 471} 472 |
|
468static void | 473static void |
469pmapdump(int argc, char **argv) | 474pmapdump(argc, argv) 475 int argc; 476 char **argv; |
470{ 471 struct sockaddr_in server_addr; | 477{ 478 struct sockaddr_in server_addr; |
479 register struct hostent *hp; |
|
472 struct pmaplist *head = NULL; 473 int socket = RPC_ANYSOCK; 474 struct timeval minutetimeout; 475 register CLIENT *client; 476 struct rpcent *rpc; | 480 struct pmaplist *head = NULL; 481 int socket = RPC_ANYSOCK; 482 struct timeval minutetimeout; 483 register CLIENT *client; 484 struct rpcent *rpc; |
477 enum clnt_stat clnt_st; 478 struct rpc_err err; 479 char *host; 480 481 if (argc > 1) | 485 486 if (argc > 1) { |
482 usage(); | 487 usage(); |
483 if (argc == 1) { 484 host = argv[0]; 485 get_inet_address(&server_addr, host); 486 server_addr.sin_port = htons(PMAPPORT); 487 client = clnttcp_create(&server_addr, PMAPPROG, PMAPVERS, 488 &socket, 50, 500); 489 } else 490 client = local_rpcb(PMAPPROG, PMAPVERS); 491 492 if (client == NULL) { 493 if (rpc_createerr.cf_stat == RPC_TLIERROR) { 494 /* 495 * "Misc. TLI error" is not too helpful. Most likely 496 * the connection to the remote server timed out, so 497 * this error is at least less perplexing. 498 */ 499 rpc_createerr.cf_stat = RPC_PMAPFAILURE; 500 rpc_createerr.cf_error.re_status = RPC_FAILED; 501 } 502 clnt_pcreateerror("rpcinfo: can't contact portmapper"); | |
503 exit(1); 504 } | 488 exit(1); 489 } |
505 | 490 if (argc == 1) 491 get_inet_address(&server_addr, argv[0]); 492 else { 493 bzero((char *)&server_addr, sizeof server_addr); 494 server_addr.sin_family = AF_INET; 495 if ((hp = gethostbyname("localhost")) != NULL) 496 bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, 497 hp->h_length); 498 else 499 server_addr.sin_addr.s_addr = inet_addr("0.0.0.0"); 500 } |
506 minutetimeout.tv_sec = 60; 507 minutetimeout.tv_usec = 0; | 501 minutetimeout.tv_sec = 60; 502 minutetimeout.tv_usec = 0; |
508 509 clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, 510 NULL, (xdrproc_t) xdr_pmaplist_ptr, (char *)&head, 511 minutetimeout); 512 if (clnt_st != RPC_SUCCESS) { 513 if ((clnt_st == RPC_PROGVERSMISMATCH) || 514 (clnt_st == RPC_PROGUNAVAIL)) { 515 CLNT_GETERR(client, &err); 516 if (err.re_vers.low > PMAPVERS) 517 warnx( 518 "%s does not support portmapper. Try rpcinfo %s instead", 519 host, host); 520 exit(1); 521 } 522 clnt_perror(client, "rpcinfo: can't contact portmapper"); | 503 server_addr.sin_port = htons(PMAPPORT); 504 if ((client = clnttcp_create(&server_addr, PMAPPROG, 505 PMAPVERS, &socket, 50, 500)) == NULL) { 506 clnt_pcreateerror("rpcinfo: can't contact portmapper"); |
523 exit(1); 524 } | 507 exit(1); 508 } |
509 if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL, 510 xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) { 511 fprintf(stderr, "rpcinfo: can't contact portmapper: "); 512 clnt_perror(client, "rpcinfo"); 513 exit(1); 514 } |
|
525 if (head == NULL) { 526 printf("No remote programs registered.\n"); 527 } else { | 515 if (head == NULL) { 516 printf("No remote programs registered.\n"); 517 } else { |
528 printf(" program vers proto port service\n"); | 518 printf(" program vers proto port\n"); |
529 for (; head != NULL; head = head->pml_next) { 530 printf("%10ld%5ld", | 519 for (; head != NULL; head = head->pml_next) { 520 printf("%10ld%5ld", |
531 head->pml_map.pm_prog, 532 head->pml_map.pm_vers); | 521 head->pml_map.pm_prog, 522 head->pml_map.pm_vers); |
533 if (head->pml_map.pm_prot == IPPROTO_UDP) | 523 if (head->pml_map.pm_prot == IPPROTO_UDP) |
534 printf("%6s", "udp"); | 524 printf("%6s", "udp"); |
535 else if (head->pml_map.pm_prot == IPPROTO_TCP) 536 printf("%6s", "tcp"); | 525 else if (head->pml_map.pm_prot == IPPROTO_TCP) 526 printf("%6s", "tcp"); |
537 else if (head->pml_map.pm_prot == IPPROTO_ST) 538 printf("%6s", "local"); | |
539 else | 527 else |
540 printf("%6ld", head->pml_map.pm_prot); 541 printf("%7ld", head->pml_map.pm_port); | 528 printf("%6ld", head->pml_map.pm_prot); 529 printf("%7ld", head->pml_map.pm_port); |
542 rpc = getrpcbynumber(head->pml_map.pm_prog); 543 if (rpc) 544 printf(" %s\n", rpc->r_name); 545 else 546 printf("\n"); 547 } 548 } 549} 550 | 530 rpc = getrpcbynumber(head->pml_map.pm_prog); 531 if (rpc) 532 printf(" %s\n", rpc->r_name); 533 else 534 printf("\n"); 535 } 536 } 537} 538 |
551static void 552get_inet_address(struct sockaddr_in *addr, char *host) 553{ 554 struct netconfig *nconf; 555 struct addrinfo hints, *res; 556 int error; 557 558 (void) memset((char *)addr, 0, sizeof (*addr)); 559 addr->sin_addr.s_addr = inet_addr(host); 560 if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) { 561 if ((nconf = __rpc_getconfip("udp")) == NULL && 562 (nconf = __rpc_getconfip("tcp")) == NULL) 563 errx(1, "couldn't find a suitable transport"); 564 else { 565 memset(&hints, 0, sizeof hints); 566 hints.ai_family = AF_INET; 567 if ((error = getaddrinfo(host, "rpcbind", &hints, &res)) 568 != 0) 569 errx(1, "%s: %s", host, gai_strerror(error)); 570 else { 571 memcpy(addr, res->ai_addr, res->ai_addrlen); 572 freeaddrinfo(res); 573 } 574 (void) freenetconfigent(nconf); 575 } 576 } else { 577 addr->sin_family = AF_INET; 578 } 579} 580#endif /* PORTMAP */ 581 582/* 583 * reply_proc collects replies from the broadcast. | 539/* 540 * reply_proc collects replies from the broadcast. |
584 * to get a unique list of responses the output of rpcinfo should 585 * be piped through sort(1) and then uniq(1). 586 */ 587 588/*ARGSUSED*/ 589static bool_t | 541 * to get a unique list of responses the output of rpcinfo should 542 * be piped through sort(1) and then uniq(1). 543 */ 544 545/*ARGSUSED*/ 546static bool_t |
590reply_proc(void *res, struct netbuf *who, struct netconfig *nconf) 591 /* void *res; Nothing comes back */ 592 /* struct netbuf *who; Who sent us the reply */ 593 /* struct netconfig *nconf; On which transport the reply came */ | 547reply_proc(res, who) 548 void *res; /* Nothing comes back */ 549 struct sockaddr_in *who; /* Who sent us the reply */ |
594{ | 550{ |
595 char *uaddr; 596 char hostbuf[NI_MAXHOST]; 597 char *hostname; 598 struct sockaddr *sa = (struct sockaddr *)who->buf; | 551 register struct hostent *hp; |
599 | 552 |
600 if (getnameinfo(sa, sa->sa_len, hostbuf, NI_MAXHOST, NULL, 0, 0)) { 601 hostname = UNKNOWN; 602 } else { 603 hostname = hostbuf; 604 } 605 if (!(uaddr = taddr2uaddr(nconf, who))) { 606 uaddr = UNKNOWN; 607 } 608 printf("%s\t%s\n", uaddr, hostname); 609 if (strcmp(uaddr, UNKNOWN)) 610 free((char *)uaddr); 611 return (FALSE); | 553 hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr, 554 AF_INET); 555 printf("%s %s\n", inet_ntoa(who->sin_addr), 556 (hp == NULL) ? "(unknown)" : hp->h_name); 557 return(FALSE); |
612} 613 614static void | 558} 559 560static void |
615brdcst(int argc, char **argv) | 561brdcst(argc, argv) 562 int argc; 563 char **argv; |
616{ 617 enum clnt_stat rpc_stat; 618 u_long prognum, vers; 619 | 564{ 565 enum clnt_stat rpc_stat; 566 u_long prognum, vers; 567 |
620 if (argc != 2) | 568 if (argc != 2) { |
621 usage(); | 569 usage(); |
622 prognum = getprognum(argv[0]); 623 vers = getvers(argv[1]); 624 rpc_stat = rpc_broadcast(prognum, vers, NULLPROC, 625 (xdrproc_t) xdr_void, (char *)NULL, (xdrproc_t) xdr_void, 626 (char *)NULL, (resultproc_t) reply_proc, NULL); 627 if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) 628 errx(1, "broadcast failed: %s", clnt_sperrno(rpc_stat)); 629 exit(0); 630} 631 632static bool_t 633add_version(struct rpcbdump_short *rs, u_long vers) 634{ 635 struct verslist *vl; 636 637 for (vl = rs->vlist; vl; vl = vl->next) 638 if (vl->vers == vers) 639 break; 640 if (vl) 641 return (TRUE); 642 vl = (struct verslist *)malloc(sizeof (struct verslist)); 643 if (vl == NULL) 644 return (FALSE); 645 vl->vers = vers; 646 vl->next = rs->vlist; 647 rs->vlist = vl; 648 return (TRUE); 649} 650 651static bool_t 652add_netid(struct rpcbdump_short *rs, char *netid) 653{ 654 struct netidlist *nl; 655 656 for (nl = rs->nlist; nl; nl = nl->next) 657 if (strcmp(nl->netid, netid) == 0) 658 break; 659 if (nl) 660 return (TRUE); 661 nl = (struct netidlist *)malloc(sizeof (struct netidlist)); 662 if (nl == NULL) 663 return (FALSE); 664 nl->netid = netid; 665 nl->next = rs->nlist; 666 rs->nlist = nl; 667 return (TRUE); 668} 669 670static void 671rpcbdump(int dumptype, char *netid, int argc, char **argv) 672{ 673 rpcblist_ptr head = NULL; 674 struct timeval minutetimeout; 675 register CLIENT *client; 676 struct rpcent *rpc; 677 char *host; 678 struct netidlist *nl; 679 struct verslist *vl; 680 struct rpcbdump_short *rs, *rs_tail; 681 char buf[256]; 682 enum clnt_stat clnt_st; 683 struct rpc_err err; 684 struct rpcbdump_short *rs_head = NULL; 685 686 if (argc > 1) 687 usage(); 688 if (argc == 1) { 689 host = argv[0]; 690 if (netid == NULL) { 691 client = clnt_rpcbind_create(host, RPCBVERS, NULL); 692 } else { 693 struct netconfig *nconf; 694 695 nconf = getnetconfigent(netid); 696 if (nconf == NULL) { 697 nc_perror("rpcinfo: invalid transport"); 698 exit(1); 699 } 700 client = getclnthandle(host, nconf, RPCBVERS, NULL); 701 if (nconf) 702 (void) freenetconfigent(nconf); 703 } 704 } else 705 client = local_rpcb(PMAPPROG, RPCBVERS); 706 707 if (client == (CLIENT *)NULL) { 708 clnt_pcreateerror("rpcinfo: can't contact rpcbind"); | |
709 exit(1); 710 } | 570 exit(1); 571 } |
711 712 minutetimeout.tv_sec = 60; 713 minutetimeout.tv_usec = 0; 714 clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, (xdrproc_t) xdr_void, 715 NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *) &head, 716 minutetimeout); 717 if (clnt_st != RPC_SUCCESS) { 718 if ((clnt_st == RPC_PROGVERSMISMATCH) || 719 (clnt_st == RPC_PROGUNAVAIL)) { 720 int vers; 721 722 CLNT_GETERR(client, &err); 723 if (err.re_vers.low == RPCBVERS4) { 724 vers = RPCBVERS4; 725 clnt_control(client, CLSET_VERS, (char *)&vers); 726 clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, 727 (xdrproc_t) xdr_void, NULL, 728 (xdrproc_t) xdr_rpcblist_ptr, (char *) &head, 729 minutetimeout); 730 if (clnt_st != RPC_SUCCESS) 731 goto failed; 732 } else { 733 if (err.re_vers.high == PMAPVERS) { 734 int high, low; 735 struct pmaplist *pmaphead = NULL; 736 rpcblist_ptr list, prev; 737 738 vers = PMAPVERS; 739 clnt_control(client, CLSET_VERS, (char *)&vers); 740 clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, 741 (xdrproc_t) xdr_void, NULL, 742 (xdrproc_t) xdr_pmaplist_ptr, 743 (char *)&pmaphead, minutetimeout); 744 if (clnt_st != RPC_SUCCESS) 745 goto failed; 746 /* 747 * convert to rpcblist_ptr format 748 */ 749 for (head = NULL; pmaphead != NULL; 750 pmaphead = pmaphead->pml_next) { 751 list = (rpcblist *)malloc(sizeof (rpcblist)); 752 if (list == NULL) 753 goto error; 754 if (head == NULL) 755 head = list; 756 else 757 prev->rpcb_next = (rpcblist_ptr) list; 758 759 list->rpcb_next = NULL; 760 list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog; 761 list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers; 762 if (pmaphead->pml_map.pm_prot == IPPROTO_UDP) 763 list->rpcb_map.r_netid = "udp"; 764 else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP) 765 list->rpcb_map.r_netid = "tcp"; 766 else { 767#define MAXLONG_AS_STRING "2147483648" 768 list->rpcb_map.r_netid = 769 malloc(strlen(MAXLONG_AS_STRING) + 1); 770 if (list->rpcb_map.r_netid == NULL) 771 goto error; 772 sprintf(list->rpcb_map.r_netid, "%6ld", 773 pmaphead->pml_map.pm_prot); 774 } 775 list->rpcb_map.r_owner = UNKNOWN; 776 low = pmaphead->pml_map.pm_port & 0xff; 777 high = (pmaphead->pml_map.pm_port >> 8) & 0xff; 778 list->rpcb_map.r_addr = strdup("0.0.0.0.XXX.XXX"); 779 sprintf(&list->rpcb_map.r_addr[8], "%d.%d", 780 high, low); 781 prev = list; 782 } 783 } 784 } 785 } else { /* any other error */ 786failed: 787 clnt_perror(client, "rpcinfo: can't contact rpcbind: "); 788 exit(1); 789 } 790 } 791 if (head == NULL) { 792 printf("No remote programs registered.\n"); 793 } else if (dumptype == RPCBDUMP) { 794 printf( 795" program version netid address service owner\n"); 796 for (; head != NULL; head = head->rpcb_next) { 797 printf("%10u%5u ", 798 head->rpcb_map.r_prog, head->rpcb_map.r_vers); 799 printf("%-9s ", head->rpcb_map.r_netid); 800 printf("%-22s", head->rpcb_map.r_addr); 801 rpc = getrpcbynumber(head->rpcb_map.r_prog); 802 if (rpc) 803 printf(" %-10s", rpc->r_name); 804 else 805 printf(" %-10s", "-"); 806 printf(" %s\n", head->rpcb_map.r_owner); 807 } 808 } else if (dumptype == RPCBDUMP_SHORT) { 809 for (; head != NULL; head = head->rpcb_next) { 810 for (rs = rs_head; rs; rs = rs->next) 811 if (head->rpcb_map.r_prog == rs->prog) 812 break; 813 if (rs == NULL) { 814 rs = (struct rpcbdump_short *) 815 malloc(sizeof (struct rpcbdump_short)); 816 if (rs == NULL) 817 goto error; 818 rs->next = NULL; 819 if (rs_head == NULL) { 820 rs_head = rs; 821 rs_tail = rs; 822 } else { 823 rs_tail->next = rs; 824 rs_tail = rs; 825 } 826 rs->prog = head->rpcb_map.r_prog; 827 rs->owner = head->rpcb_map.r_owner; 828 rs->nlist = NULL; 829 rs->vlist = NULL; 830 } 831 if (add_version(rs, head->rpcb_map.r_vers) == FALSE) 832 goto error; 833 if (add_netid(rs, head->rpcb_map.r_netid) == FALSE) 834 goto error; 835 } 836 printf( 837" program version(s) netid(s) service owner\n"); 838 for (rs = rs_head; rs; rs = rs->next) { 839 char *p = buf; 840 841 printf("%10ld ", rs->prog); 842 for (vl = rs->vlist; vl; vl = vl->next) { 843 sprintf(p, "%d", vl->vers); 844 p = p + strlen(p); 845 if (vl->next) 846 sprintf(p++, ","); 847 } 848 printf("%-10s", buf); 849 buf[0] = '\0'; 850 for (nl = rs->nlist; nl; nl = nl->next) { 851 strcat(buf, nl->netid); 852 if (nl->next) 853 strcat(buf, ","); 854 } 855 printf("%-32s", buf); 856 rpc = getrpcbynumber(rs->prog); 857 if (rpc) 858 printf(" %-11s", rpc->r_name); 859 else 860 printf(" %-11s", "-"); 861 printf(" %s\n", rs->owner); 862 } 863 } 864 clnt_destroy(client); 865 return; 866error: warnx("no memory"); 867 return; 868} 869 870static char nullstring[] = "\000"; 871 872static void 873rpcbaddrlist(char *netid, int argc, char **argv) 874{ 875 rpcb_entry_list_ptr head = NULL; 876 struct timeval minutetimeout; 877 register CLIENT *client; 878 struct rpcent *rpc; 879 char *host; 880 RPCB parms; 881 struct netbuf *targaddr; 882 883 if (argc != 3) 884 usage(); 885 host = argv[0]; 886 if (netid == NULL) { 887 client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr); 888 } else { 889 struct netconfig *nconf; 890 891 nconf = getnetconfigent(netid); 892 if (nconf == NULL) { 893 nc_perror("rpcinfo: invalid transport"); 894 exit(1); 895 } 896 client = getclnthandle(host, nconf, RPCBVERS4, &targaddr); 897 if (nconf) 898 (void) freenetconfigent(nconf); 899 } 900 if (client == (CLIENT *)NULL) { 901 clnt_pcreateerror("rpcinfo: can't contact rpcbind"); 902 exit(1); 903 } 904 minutetimeout.tv_sec = 60; 905 minutetimeout.tv_usec = 0; 906 907 parms.r_prog = getprognum(argv[1]); 908 parms.r_vers = getvers(argv[2]); 909 parms.r_netid = client->cl_netid; 910 if (targaddr == NULL) { 911 parms.r_addr = nullstring; /* for XDRing */ 912 } else { 913 /* 914 * We also send the remote system the address we 915 * used to contact it in case it can help it 916 * connect back with us 917 */ 918 struct netconfig *nconf; 919 920 nconf = getnetconfigent(client->cl_netid); 921 if (nconf != NULL) { 922 parms.r_addr = taddr2uaddr(nconf, targaddr); 923 if (parms.r_addr == NULL) 924 parms.r_addr = nullstring; 925 freenetconfigent(nconf); 926 } else { 927 parms.r_addr = nullstring; /* for XDRing */ 928 } 929 free(targaddr->buf); 930 free(targaddr); 931 } 932 parms.r_owner = nullstring; 933 934 if (CLNT_CALL(client, RPCBPROC_GETADDRLIST, (xdrproc_t) xdr_rpcb, 935 (char *) &parms, (xdrproc_t) xdr_rpcb_entry_list_ptr, 936 (char *) &head, minutetimeout) != RPC_SUCCESS) { 937 clnt_perror(client, "rpcinfo: can't contact rpcbind: "); 938 exit(1); 939 } 940 if (head == NULL) { 941 printf("No remote programs registered.\n"); 942 } else { 943 printf( 944 " program vers tp_family/name/class address\t\t service\n"); 945 for (; head != NULL; head = head->rpcb_entry_next) { 946 rpcb_entry *re; 947 char buf[128]; 948 949 re = &head->rpcb_entry_map; 950 printf("%10u%3u ", 951 parms.r_prog, parms.r_vers); 952 sprintf(buf, "%s/%s/%s ", 953 re->r_nc_protofmly, re->r_nc_proto, 954 re->r_nc_semantics == NC_TPI_CLTS ? "clts" : 955 re->r_nc_semantics == NC_TPI_COTS ? "cots" : 956 "cots_ord"); 957 printf("%-24s", buf); 958 printf("%-24s", re->r_maddr); 959 rpc = getrpcbynumber(parms.r_prog); 960 if (rpc) 961 printf(" %-13s", rpc->r_name); 962 else 963 printf(" %-13s", "-"); 964 printf("\n"); 965 } 966 } 967 clnt_destroy(client); 968 return; 969} 970 971/* 972 * monitor rpcbind 973 */ 974static void 975rpcbgetstat(int argc, char **argv) 976{ 977 rpcb_stat_byvers inf; 978 struct timeval minutetimeout; 979 register CLIENT *client; 980 char *host; 981 int i, j; 982 rpcbs_addrlist *pa; 983 rpcbs_rmtcalllist *pr; 984 int cnt, flen; 985#define MAXFIELD 64 986 char fieldbuf[MAXFIELD]; 987#define MAXLINE 256 988 char linebuf[MAXLINE]; 989 char *cp, *lp; 990 char *pmaphdr[] = { 991 "NULL", "SET", "UNSET", "GETPORT", 992 "DUMP", "CALLIT" 993 }; 994 char *rpcb3hdr[] = { 995 "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME", 996 "U2T", "T2U" 997 }; 998 char *rpcb4hdr[] = { 999 "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME", 1000 "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT" 1001 }; 1002 1003#define TABSTOP 8 1004 1005 if (argc >= 1) { 1006 host = argv[0]; 1007 client = clnt_rpcbind_create(host, RPCBVERS4, NULL); 1008 } else 1009 client = local_rpcb(PMAPPROG, RPCBVERS4); 1010 if (client == (CLIENT *)NULL) { 1011 clnt_pcreateerror("rpcinfo: can't contact rpcbind"); 1012 exit(1); 1013 } 1014 minutetimeout.tv_sec = 60; 1015 minutetimeout.tv_usec = 0; 1016 memset((char *)&inf, 0, sizeof (rpcb_stat_byvers)); 1017 if (CLNT_CALL(client, RPCBPROC_GETSTAT, (xdrproc_t) xdr_void, NULL, 1018 (xdrproc_t) xdr_rpcb_stat_byvers, (char *)&inf, minutetimeout) 1019 != RPC_SUCCESS) { 1020 clnt_perror(client, "rpcinfo: can't contact rpcbind: "); 1021 exit(1); 1022 } 1023 printf("PORTMAP (version 2) statistics\n"); 1024 lp = linebuf; 1025 for (i = 0; i <= rpcb_highproc_2; i++) { 1026 fieldbuf[0] = '\0'; 1027 switch (i) { 1028 case PMAPPROC_SET: 1029 sprintf(fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo); 1030 break; 1031 case PMAPPROC_UNSET: 1032 sprintf(fieldbuf, "%d/", 1033 inf[RPCBVERS_2_STAT].unsetinfo); 1034 break; 1035 case PMAPPROC_GETPORT: 1036 cnt = 0; 1037 for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa; 1038 pa = pa->next) 1039 cnt += pa->success; 1040 sprintf(fieldbuf, "%d/", cnt); 1041 break; 1042 case PMAPPROC_CALLIT: 1043 cnt = 0; 1044 for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr; 1045 pr = pr->next) 1046 cnt += pr->success; 1047 sprintf(fieldbuf, "%d/", cnt); 1048 break; 1049 default: break; /* For the remaining ones */ 1050 } 1051 cp = &fieldbuf[0] + strlen(fieldbuf); 1052 sprintf(cp, "%d", inf[RPCBVERS_2_STAT].info[i]); 1053 flen = strlen(fieldbuf); 1054 printf("%s%s", pmaphdr[i], 1055 spaces((TABSTOP * (1 + flen / TABSTOP)) 1056 - strlen(pmaphdr[i]))); 1057 sprintf(lp, "%s%s", fieldbuf, 1058 spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) 1059 - flen))); 1060 lp += (flen + cnt); 1061 } 1062 printf("\n%s\n\n", linebuf); 1063 1064 if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT]) { 1065 printf("PMAP_RMTCALL call statistics\n"); 1066 print_rmtcallstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]); 1067 printf("\n"); 1068 } 1069 1070 if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT]) { 1071 printf("PMAP_GETPORT call statistics\n"); 1072 print_getaddrstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]); 1073 printf("\n"); 1074 } 1075 1076 printf("RPCBIND (version 3) statistics\n"); 1077 lp = linebuf; 1078 for (i = 0; i <= rpcb_highproc_3; i++) { 1079 fieldbuf[0] = '\0'; 1080 switch (i) { 1081 case RPCBPROC_SET: 1082 sprintf(fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo); 1083 break; 1084 case RPCBPROC_UNSET: 1085 sprintf(fieldbuf, "%d/", 1086 inf[RPCBVERS_3_STAT].unsetinfo); 1087 break; 1088 case RPCBPROC_GETADDR: 1089 cnt = 0; 1090 for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa; 1091 pa = pa->next) 1092 cnt += pa->success; 1093 sprintf(fieldbuf, "%d/", cnt); 1094 break; 1095 case RPCBPROC_CALLIT: 1096 cnt = 0; 1097 for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr; 1098 pr = pr->next) 1099 cnt += pr->success; 1100 sprintf(fieldbuf, "%d/", cnt); 1101 break; 1102 default: break; /* For the remaining ones */ 1103 } 1104 cp = &fieldbuf[0] + strlen(fieldbuf); 1105 sprintf(cp, "%d", inf[RPCBVERS_3_STAT].info[i]); 1106 flen = strlen(fieldbuf); 1107 printf("%s%s", rpcb3hdr[i], 1108 spaces((TABSTOP * (1 + flen / TABSTOP)) 1109 - strlen(rpcb3hdr[i]))); 1110 sprintf(lp, "%s%s", fieldbuf, 1111 spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) 1112 - flen))); 1113 lp += (flen + cnt); 1114 } 1115 printf("\n%s\n\n", linebuf); 1116 1117 if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT]) { 1118 printf("RPCB_RMTCALL (version 3) call statistics\n"); 1119 print_rmtcallstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]); 1120 printf("\n"); 1121 } 1122 1123 if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR]) { 1124 printf("RPCB_GETADDR (version 3) call statistics\n"); 1125 print_getaddrstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]); 1126 printf("\n"); 1127 } 1128 1129 printf("RPCBIND (version 4) statistics\n"); 1130 1131 for (j = 0; j <= 9; j += 9) { /* Just two iterations for printing */ 1132 lp = linebuf; 1133 for (i = j; i <= MAX(8, rpcb_highproc_4 - 9 + j); i++) { 1134 fieldbuf[0] = '\0'; 1135 switch (i) { 1136 case RPCBPROC_SET: 1137 sprintf(fieldbuf, "%d/", 1138 inf[RPCBVERS_4_STAT].setinfo); 1139 break; 1140 case RPCBPROC_UNSET: 1141 sprintf(fieldbuf, "%d/", 1142 inf[RPCBVERS_4_STAT].unsetinfo); 1143 break; 1144 case RPCBPROC_GETADDR: 1145 cnt = 0; 1146 for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa; 1147 pa = pa->next) 1148 cnt += pa->success; 1149 sprintf(fieldbuf, "%d/", cnt); 1150 break; 1151 case RPCBPROC_CALLIT: 1152 cnt = 0; 1153 for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr; 1154 pr = pr->next) 1155 cnt += pr->success; 1156 sprintf(fieldbuf, "%d/", cnt); 1157 break; 1158 default: break; /* For the remaining ones */ 1159 } 1160 cp = &fieldbuf[0] + strlen(fieldbuf); 1161 /* 1162 * XXX: We also add RPCBPROC_GETADDRLIST queries to 1163 * RPCB_GETADDR because rpcbind includes the 1164 * RPCB_GETADDRLIST successes in RPCB_GETADDR. 1165 */ 1166 if (i != RPCBPROC_GETADDR) 1167 sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i]); 1168 else 1169 sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i] + 1170 inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]); 1171 flen = strlen(fieldbuf); 1172 printf("%s%s", rpcb4hdr[i], 1173 spaces((TABSTOP * (1 + flen / TABSTOP)) 1174 - strlen(rpcb4hdr[i]))); 1175 sprintf(lp, "%s%s", fieldbuf, 1176 spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) 1177 - flen))); 1178 lp += (flen + cnt); 1179 } 1180 printf("\n%s\n", linebuf); 1181 } 1182 1183 if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] || 1184 inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT]) { 1185 printf("\n"); 1186 printf("RPCB_RMTCALL (version 4) call statistics\n"); 1187 print_rmtcallstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]); 1188 } 1189 1190 if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR]) { 1191 printf("\n"); 1192 printf("RPCB_GETADDR (version 4) call statistics\n"); 1193 print_getaddrstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]); 1194 } 1195 clnt_destroy(client); 1196} 1197 1198/* 1199 * Delete registeration for this (prog, vers, netid) 1200 */ 1201static void 1202deletereg(char *netid, int argc, char **argv) 1203{ 1204 struct netconfig *nconf = NULL; 1205 1206 if (argc != 2) 1207 usage(); 1208 if (netid) { 1209 nconf = getnetconfigent(netid); 1210 if (nconf == NULL) 1211 errx(1, "netid %s not supported", netid); 1212 } 1213 if ((rpcb_unset(getprognum(argv[0]), getvers(argv[1]), nconf)) == 0) 1214 errx(1, 1215 "could not delete registration for prog %s version %s", 1216 argv[0], argv[1]); 1217} 1218 1219/* 1220 * Create and return a handle for the given nconf. 1221 * Exit if cannot create handle. 1222 */ 1223static CLIENT * 1224clnt_addr_create(char *address, struct netconfig *nconf, 1225 u_long prog, u_long vers) 1226{ 1227 CLIENT *client; 1228 static struct netbuf *nbuf; 1229 static int fd = RPC_ANYFD; 1230 1231 if (fd == RPC_ANYFD) { 1232 if ((fd = __rpc_nconf2fd(nconf)) == -1) { 1233 rpc_createerr.cf_stat = RPC_TLIERROR; 1234 clnt_pcreateerror("rpcinfo"); 1235 exit(1); 1236 } 1237 /* Convert the uaddr to taddr */ 1238 nbuf = uaddr2taddr(nconf, address); 1239 if (nbuf == NULL) 1240 errx(1, "no address for client handle"); 1241 } 1242 client = clnt_tli_create(fd, nconf, nbuf, prog, vers, 0, 0); 1243 if (client == (CLIENT *)NULL) { 1244 clnt_pcreateerror("rpcinfo"); 1245 exit(1); 1246 } 1247 return (client); 1248} 1249 1250/* 1251 * If the version number is given, ping that (prog, vers); else try to find 1252 * the version numbers supported for that prog and ping all the versions. 1253 * Remote rpcbind is not contacted for this service. The requests are 1254 * sent directly to the services themselves. 1255 */ 1256static void 1257addrping(char *address, char *netid, int argc, char **argv) 1258{ 1259 CLIENT *client; 1260 struct timeval to; 1261 enum clnt_stat rpc_stat; 1262 u_long prognum, versnum, minvers, maxvers; 1263 struct rpc_err rpcerr; 1264 int failure = 0; 1265 struct netconfig *nconf; 1266 int fd; 1267 1268 if (argc < 1 || argc > 2 || (netid == NULL)) 1269 usage(); 1270 nconf = getnetconfigent(netid); 1271 if (nconf == (struct netconfig *)NULL) 1272 errx(1, "could not find %s", netid); 1273 to.tv_sec = 10; 1274 to.tv_usec = 0; | |
1275 prognum = getprognum(argv[0]); | 572 prognum = getprognum(argv[0]); |
1276 if (argc == 1) { /* Version number not known */ 1277 /* 1278 * A call to version 0 should fail with a program/version 1279 * mismatch, and give us the range of versions supported. 1280 */ 1281 versnum = MIN_VERS; 1282 } else { 1283 versnum = getvers(argv[1]); 1284 } 1285 client = clnt_addr_create(address, nconf, prognum, versnum); 1286 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 1287 (char *)NULL, (xdrproc_t) xdr_void, 1288 (char *)NULL, to); 1289 if (argc == 2) { 1290 /* Version number was known */ 1291 if (pstatus(client, prognum, versnum) < 0) 1292 failure = 1; 1293 (void) CLNT_DESTROY(client); 1294 if (failure) 1295 exit(1); 1296 return; 1297 } 1298 /* Version number not known */ 1299 (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL); 1300 (void) CLNT_CONTROL(client, CLGET_FD, (char *)&fd); 1301 if (rpc_stat == RPC_PROGVERSMISMATCH) { 1302 clnt_geterr(client, &rpcerr); 1303 minvers = rpcerr.re_vers.low; 1304 maxvers = rpcerr.re_vers.high; 1305 } else if (rpc_stat == RPC_SUCCESS) { 1306 /* 1307 * Oh dear, it DOES support version 0. 1308 * Let's try version MAX_VERS. 1309 */ 1310 (void) CLNT_DESTROY(client); 1311 client = clnt_addr_create(address, nconf, prognum, MAX_VERS); 1312 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 1313 (char *)NULL, (xdrproc_t) xdr_void, 1314 (char *)NULL, to); 1315 if (rpc_stat == RPC_PROGVERSMISMATCH) { 1316 clnt_geterr(client, &rpcerr); 1317 minvers = rpcerr.re_vers.low; 1318 maxvers = rpcerr.re_vers.high; 1319 } else if (rpc_stat == RPC_SUCCESS) { 1320 /* 1321 * It also supports version MAX_VERS. 1322 * Looks like we have a wise guy. 1323 * OK, we give them information on all 1324 * 4 billion versions they support... 1325 */ 1326 minvers = 0; 1327 maxvers = MAX_VERS; 1328 } else { 1329 (void) pstatus(client, prognum, MAX_VERS); 1330 exit(1); 1331 } 1332 } else { 1333 (void) pstatus(client, prognum, (u_long)0); | 573 vers = getvers(argv[1]); 574 rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void, 575 (char *)NULL, xdr_void, (char *)NULL, reply_proc); 576 if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) { 577 fprintf(stderr, "rpcinfo: broadcast failed: %s\n", 578 clnt_sperrno(rpc_stat)); |
1334 exit(1); 1335 } | 579 exit(1); 580 } |
1336 (void) CLNT_DESTROY(client); 1337 for (versnum = minvers; versnum <= maxvers; versnum++) { 1338 client = clnt_addr_create(address, nconf, prognum, versnum); 1339 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 1340 (char *)NULL, (xdrproc_t) xdr_void, 1341 (char *)NULL, to); 1342 if (pstatus(client, prognum, versnum) < 0) 1343 failure = 1; 1344 (void) CLNT_DESTROY(client); 1345 } 1346 (void) close(fd); 1347 if (failure) 1348 exit(1); 1349 return; | 581 exit(0); |
1350} 1351 | 582} 583 |
1352/* 1353 * If the version number is given, ping that (prog, vers); else try to find 1354 * the version numbers supported for that prog and ping all the versions. 1355 * Remote rpcbind is *contacted* for this service. The requests are 1356 * then sent directly to the services themselves. 1357 */ | |
1358static void | 584static void |
1359progping(char *netid, int argc, char **argv) 1360{ 1361 CLIENT *client; 1362 struct timeval to; 1363 enum clnt_stat rpc_stat; 1364 u_long prognum, versnum, minvers, maxvers; 1365 struct rpc_err rpcerr; 1366 int failure = 0; 1367 struct netconfig *nconf; | 585deletereg(argc, argv) 586 int argc; 587 char **argv; 588{ u_long prog_num, version_num ; |
1368 | 589 |
1369 if (argc < 2 || argc > 3 || (netid == NULL)) 1370 usage(); 1371 prognum = getprognum(argv[1]); 1372 if (argc == 2) { /* Version number not known */ 1373 /* 1374 * A call to version 0 should fail with a program/version 1375 * mismatch, and give us the range of versions supported. 1376 */ 1377 versnum = MIN_VERS; 1378 } else { 1379 versnum = getvers(argv[2]); | 590 if (argc != 2) { 591 usage() ; 592 exit(1) ; |
1380 } | 593 } |
1381 if (netid) { 1382 nconf = getnetconfigent(netid); 1383 if (nconf == (struct netconfig *)NULL) 1384 errx(1, "could not find %s", netid); 1385 client = clnt_tp_create(argv[0], prognum, versnum, nconf); 1386 } else { 1387 client = clnt_create(argv[0], prognum, versnum, "NETPATH"); | 594 if (getuid()) { /* This command allowed only to root */ 595 fprintf(stderr, "Sorry. You are not root\n") ; 596 exit(1) ; |
1388 } | 597 } |
1389 if (client == (CLIENT *)NULL) { 1390 clnt_pcreateerror("rpcinfo"); 1391 exit(1); | 598 prog_num = getprognum(argv[0]); 599 version_num = getvers(argv[1]); 600 if ((pmap_unset(prog_num, version_num)) == 0) { 601 fprintf(stderr, "rpcinfo: Could not delete registration for prog %s version %s\n", 602 argv[0], argv[1]) ; 603 exit(1) ; |
1392 } | 604 } |
1393 to.tv_sec = 10; 1394 to.tv_usec = 0; 1395 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 1396 (char *)NULL, (xdrproc_t) xdr_void, 1397 (char *)NULL, to); 1398 if (argc == 3) { 1399 /* Version number was known */ 1400 if (pstatus(client, prognum, versnum) < 0) 1401 failure = 1; 1402 (void) CLNT_DESTROY(client); 1403 if (failure) 1404 exit(1); 1405 return; 1406 } 1407 /* Version number not known */ 1408 if (rpc_stat == RPC_PROGVERSMISMATCH) { 1409 clnt_geterr(client, &rpcerr); 1410 minvers = rpcerr.re_vers.low; 1411 maxvers = rpcerr.re_vers.high; 1412 } else if (rpc_stat == RPC_SUCCESS) { 1413 /* 1414 * Oh dear, it DOES support version 0. 1415 * Let's try version MAX_VERS. 1416 */ 1417 versnum = MAX_VERS; 1418 (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum); 1419 rpc_stat = CLNT_CALL(client, NULLPROC, 1420 (xdrproc_t) xdr_void, (char *)NULL, 1421 (xdrproc_t) xdr_void, (char *)NULL, to); 1422 if (rpc_stat == RPC_PROGVERSMISMATCH) { 1423 clnt_geterr(client, &rpcerr); 1424 minvers = rpcerr.re_vers.low; 1425 maxvers = rpcerr.re_vers.high; 1426 } else if (rpc_stat == RPC_SUCCESS) { 1427 /* 1428 * It also supports version MAX_VERS. 1429 * Looks like we have a wise guy. 1430 * OK, we give them information on all 1431 * 4 billion versions they support... 1432 */ 1433 minvers = 0; 1434 maxvers = MAX_VERS; 1435 } else { 1436 (void) pstatus(client, prognum, MAX_VERS); 1437 exit(1); 1438 } 1439 } else { 1440 (void) pstatus(client, prognum, (u_long)0); 1441 exit(1); 1442 } 1443 for (versnum = minvers; versnum <= maxvers; versnum++) { 1444 (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum); 1445 rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, 1446 (char *)NULL, (xdrproc_t) xdr_void, 1447 (char *)NULL, to); 1448 if (pstatus(client, prognum, versnum) < 0) 1449 failure = 1; 1450 } 1451 (void) CLNT_DESTROY(client); 1452 if (failure) 1453 exit(1); 1454 return; | |
1455} 1456 1457static void 1458usage() 1459{ | 605} 606 607static void 608usage() 609{ |
1460 fprintf(stderr, "usage: rpcinfo [-m | -s] [host]\n"); 1461#ifdef PORTMAP 1462 fprintf(stderr, " rpcinfo -p [host]\n"); 1463#endif 1464 fprintf(stderr, " rpcinfo -T netid host prognum [versnum]\n"); 1465 fprintf(stderr, " rpcinfo -l host prognum versnum\n"); 1466#ifdef PORTMAP 1467 fprintf(stderr, 1468" rpcinfo [-n portnum] -u | -t host prognum [versnum]\n"); 1469#endif 1470 fprintf(stderr, 1471" rpcinfo -a serv_address -T netid prognum [version]\n"); | 610 fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"); 611 fprintf(stderr, " rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"); 612 fprintf(stderr, " rpcinfo -p [ host ]\n"); |
1472 fprintf(stderr, " rpcinfo -b prognum versnum\n"); | 613 fprintf(stderr, " rpcinfo -b prognum versnum\n"); |
1473 fprintf(stderr, " rpcinfo -d [-T netid] prognum versnum\n"); 1474 exit(1); | 614 fprintf(stderr, " rpcinfo -d prognum versnum\n") ; |
1475} 1476 1477static u_long | 615} 616 617static u_long |
1478getprognum (char *arg) | 618getprognum(arg) 619 char *arg; |
1479{ | 620{ |
1480 char *strptr; | |
1481 register struct rpcent *rpc; 1482 register u_long prognum; | 621 register struct rpcent *rpc; 622 register u_long prognum; |
1483 char *tptr = arg; | |
1484 | 623 |
1485 while (*tptr && isdigit(*tptr++)); 1486 if (*tptr || isalpha(*(tptr - 1))) { | 624 if (isalpha(*arg)) { |
1487 rpc = getrpcbyname(arg); | 625 rpc = getrpcbyname(arg); |
1488 if (rpc == NULL) 1489 errx(1, "%s is unknown service", arg); | 626 if (rpc == NULL) { 627 fprintf(stderr, "rpcinfo: %s is unknown service\n", 628 arg); 629 exit(1); 630 } |
1490 prognum = rpc->r_number; 1491 } else { | 631 prognum = rpc->r_number; 632 } else { |
1492 prognum = strtol(arg, &strptr, 10); 1493 if (strptr == arg || *strptr != '\0') 1494 errx(1, "%s is illegal program number", arg); | 633 prognum = (u_long) atoi(arg); |
1495 } | 634 } |
635 |
|
1496 return (prognum); 1497} 1498 1499static u_long | 636 return (prognum); 637} 638 639static u_long |
1500getvers(char *arg) | 640getvers(arg) 641 char *arg; |
1501{ | 642{ |
1502 char *strptr; | |
1503 register u_long vers; 1504 | 643 register u_long vers; 644 |
1505 vers = (int) strtol(arg, &strptr, 10); 1506 if (strptr == arg || *strptr != '\0') 1507 errx(1, "%s is illegal version number", arg); | 645 vers = (int) atoi(arg); |
1508 return (vers); 1509} 1510 | 646 return (vers); 647} 648 |
1511/* 1512 * This routine should take a pointer to an "rpc_err" structure, rather than 1513 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to 1514 * a CLIENT structure rather than a pointer to an "rpc_err" structure. 1515 * As such, we have to keep the CLIENT structure around in order to print 1516 * a good error message. 1517 */ 1518static int 1519pstatus(register CLIENT *client, u_long prog, u_long vers) | 649static void 650get_inet_address(addr, host) 651 struct sockaddr_in *addr; 652 char *host; |
1520{ | 653{ |
1521 struct rpc_err rpcerr; | 654 register struct hostent *hp; |
1522 | 655 |
1523 clnt_geterr(client, &rpcerr); 1524 if (rpcerr.re_status != RPC_SUCCESS) { 1525 clnt_perror(client, "rpcinfo"); 1526 printf("program %lu version %lu is not available\n", 1527 prog, vers); 1528 return (-1); 1529 } else { 1530 printf("program %lu version %lu ready and waiting\n", 1531 prog, vers); 1532 return (0); 1533 } 1534} 1535 1536static CLIENT * 1537clnt_rpcbind_create(char *host, int rpcbversnum, struct netbuf **targaddr) 1538{ 1539 static char *tlist[3] = { 1540 "circuit_n", "circuit_v", "datagram_v" 1541 }; 1542 int i; 1543 struct netconfig *nconf; 1544 CLIENT *clnt = NULL; 1545 void *handle; 1546 1547 rpc_createerr.cf_stat = RPC_SUCCESS; 1548 for (i = 0; i < 3; i++) { 1549 if ((handle = __rpc_setconf(tlist[i])) == NULL) 1550 continue; 1551 while (clnt == (CLIENT *)NULL) { 1552 if ((nconf = __rpc_getconf(handle)) == NULL) { 1553 if (rpc_createerr.cf_stat == RPC_SUCCESS) 1554 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 1555 break; 1556 } 1557 clnt = getclnthandle(host, nconf, rpcbversnum, 1558 targaddr); | 656 bzero((char *)addr, sizeof *addr); 657 addr->sin_addr.s_addr = (u_long) inet_addr(host); 658 if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) { 659 if ((hp = gethostbyname(host)) == NULL) { 660 fprintf(stderr, "rpcinfo: %s is unknown host\n", host); 661 exit(1); |
1559 } | 662 } |
1560 if (clnt) 1561 break; 1562 __rpc_endconf(handle); | 663 bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length); |
1563 } | 664 } |
1564 return (clnt); | 665 addr->sin_family = AF_INET; |
1565} | 666} |
1566 1567static CLIENT* 1568getclnthandle(char *host, struct netconfig *nconf, 1569 u_long rpcbversnum, struct netbuf **targaddr) 1570{ 1571 struct netbuf addr; 1572 struct addrinfo hints, *res; 1573 CLIENT *client = NULL; 1574 1575 /* Get the address of the rpcbind */ 1576 memset(&hints, 0, sizeof hints); 1577 if (getaddrinfo(host, "rpcbind", &hints, &res) != 0) { 1578 rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 1579 return (NULL); 1580 } 1581 addr.len = addr.maxlen = res->ai_addrlen; 1582 addr.buf = res->ai_addr; 1583 client = clnt_tli_create(RPC_ANYFD, nconf, &addr, RPCBPROG, 1584 rpcbversnum, 0, 0); 1585 if (client) { 1586 if (targaddr != NULL) { 1587 *targaddr = 1588 (struct netbuf *)malloc(sizeof (struct netbuf)); 1589 if (*targaddr != NULL) { 1590 (*targaddr)->maxlen = addr.maxlen; 1591 (*targaddr)->len = addr.len; 1592 (*targaddr)->buf = (char *)malloc(addr.len); 1593 if ((*targaddr)->buf != NULL) { 1594 memcpy((*targaddr)->buf, addr.buf, 1595 addr.len); 1596 } 1597 } 1598 } 1599 } else { 1600 if (rpc_createerr.cf_stat == RPC_TLIERROR) { 1601 /* 1602 * Assume that the other system is dead; this is a 1603 * better error to display to the user. 1604 */ 1605 rpc_createerr.cf_stat = RPC_RPCBFAILURE; 1606 rpc_createerr.cf_error.re_status = RPC_FAILED; 1607 } 1608 } 1609 freeaddrinfo(res); 1610 return (client); 1611} 1612 1613static void 1614print_rmtcallstat(int rtype, rpcb_stat *infp) 1615{ 1616 register rpcbs_rmtcalllist_ptr pr; 1617 struct rpcent *rpc; 1618 1619 if (rtype == RPCBVERS_4_STAT) 1620 printf( 1621 "prog\t\tvers\tproc\tnetid\tindirect success failure\n"); 1622 else 1623 printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n"); 1624 for (pr = infp->rmtinfo; pr; pr = pr->next) { 1625 rpc = getrpcbynumber(pr->prog); 1626 if (rpc) 1627 printf("%-16s", rpc->r_name); 1628 else 1629 printf("%-16d", pr->prog); 1630 printf("%d\t%d\t%s\t", 1631 pr->vers, pr->proc, pr->netid); 1632 if (rtype == RPCBVERS_4_STAT) 1633 printf("%d\t ", pr->indirect); 1634 printf("%d\t%d\n", pr->success, pr->failure); 1635 } 1636} 1637 1638static void 1639print_getaddrstat(int rtype, rpcb_stat *infp) 1640{ 1641 rpcbs_addrlist_ptr al; 1642 register struct rpcent *rpc; 1643 1644 printf("prog\t\tvers\tnetid\t success\tfailure\n"); 1645 for (al = infp->addrinfo; al; al = al->next) { 1646 rpc = getrpcbynumber(al->prog); 1647 if (rpc) 1648 printf("%-16s", rpc->r_name); 1649 else 1650 printf("%-16d", al->prog); 1651 printf("%d\t%s\t %-12d\t%d\n", 1652 al->vers, al->netid, 1653 al->success, al->failure); 1654 } 1655} 1656 1657static char * 1658spaces(int howmany) 1659{ 1660 static char space_array[] = /* 64 spaces */ 1661 " "; 1662 1663 if (howmany <= 0 || howmany > sizeof (space_array)) { 1664 return (""); 1665 } 1666 return (&space_array[sizeof (space_array) - howmany - 1]); 1667} | |