rpcinfo.c revision 1.3 1 1.1 glass #ifndef lint
2 1.3 mycroft /*static char sccsid[] = "from: @(#)rpcinfo.c 1.22 87/08/12 SMI";*/
3 1.3 mycroft /*static char sccsid[] = "from: @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC";*/
4 1.3 mycroft static char rcsid[] = "$Id: rpcinfo.c,v 1.3 1993/08/01 18:09:11 mycroft Exp $";
5 1.1 glass #endif
6 1.1 glass
7 1.1 glass /*
8 1.1 glass * Copyright (C) 1986, Sun Microsystems, Inc.
9 1.1 glass */
10 1.1 glass
11 1.1 glass /*
12 1.1 glass * rpcinfo: ping a particular rpc program
13 1.1 glass * or dump the portmapper
14 1.1 glass */
15 1.1 glass
16 1.1 glass /*
17 1.1 glass * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
18 1.1 glass * unrestricted use provided that this legend is included on all tape
19 1.1 glass * media and as a part of the software program in whole or part. Users
20 1.1 glass * may copy or modify Sun RPC without charge, but are not authorized
21 1.1 glass * to license or distribute it to anyone else except as part of a product or
22 1.1 glass * program developed by the user.
23 1.1 glass *
24 1.1 glass * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
25 1.1 glass * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
26 1.1 glass * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
27 1.1 glass *
28 1.1 glass * Sun RPC is provided with no support and without any obligation on the
29 1.1 glass * part of Sun Microsystems, Inc. to assist in its use, correction,
30 1.1 glass * modification or enhancement.
31 1.1 glass *
32 1.1 glass * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
33 1.1 glass * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
34 1.1 glass * OR ANY PART THEREOF.
35 1.1 glass *
36 1.1 glass * In no event will Sun Microsystems, Inc. be liable for any lost revenue
37 1.1 glass * or profits or other special, indirect and consequential damages, even if
38 1.1 glass * Sun has been advised of the possibility of such damages.
39 1.1 glass *
40 1.1 glass * Sun Microsystems, Inc.
41 1.1 glass * 2550 Garcia Avenue
42 1.1 glass * Mountain View, California 94043
43 1.1 glass */
44 1.1 glass
45 1.1 glass #include <rpc/rpc.h>
46 1.1 glass #include <stdio.h>
47 1.1 glass #include <sys/socket.h>
48 1.1 glass #include <netdb.h>
49 1.1 glass #include <rpc/pmap_prot.h>
50 1.1 glass #include <rpc/pmap_clnt.h>
51 1.1 glass #include <signal.h>
52 1.1 glass #include <ctype.h>
53 1.1 glass
54 1.1 glass #define MAXHOSTLEN 256
55 1.1 glass
56 1.1 glass #define MIN_VERS ((u_long) 0)
57 1.2 mycroft #define MAX_VERS ((u_long) 4294967295UL)
58 1.1 glass
59 1.1 glass static void udpping(/*u_short portflag, int argc, char **argv*/);
60 1.1 glass static void tcpping(/*u_short portflag, int argc, char **argv*/);
61 1.1 glass static int pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
62 1.1 glass static void pmapdump(/*int argc, char **argv*/);
63 1.1 glass static bool_t reply_proc(/*void *res, struct sockaddr_in *who*/);
64 1.1 glass static void brdcst(/*int argc, char **argv*/);
65 1.1 glass static void deletereg(/* int argc, char **argv */) ;
66 1.1 glass static void usage(/*void*/);
67 1.1 glass static u_long getprognum(/*char *arg*/);
68 1.1 glass static u_long getvers(/*char *arg*/);
69 1.1 glass static void get_inet_address(/*struct sockaddr_in *addr, char *host*/);
70 1.1 glass extern u_long inet_addr(); /* in 4.2BSD, arpa/inet.h called that a in_addr */
71 1.1 glass extern char *inet_ntoa();
72 1.1 glass
73 1.1 glass /*
74 1.1 glass * Functions to be performed.
75 1.1 glass */
76 1.1 glass #define NONE 0 /* no function */
77 1.1 glass #define PMAPDUMP 1 /* dump portmapper registrations */
78 1.1 glass #define TCPPING 2 /* ping TCP service */
79 1.1 glass #define UDPPING 3 /* ping UDP service */
80 1.1 glass #define BRDCST 4 /* ping broadcast UDP service */
81 1.1 glass #define DELETES 5 /* delete registration for the service */
82 1.1 glass
83 1.1 glass int
84 1.1 glass main(argc, argv)
85 1.1 glass int argc;
86 1.1 glass char **argv;
87 1.1 glass {
88 1.1 glass register int c;
89 1.1 glass extern char *optarg;
90 1.1 glass extern int optind;
91 1.1 glass int errflg;
92 1.1 glass int function;
93 1.1 glass u_short portnum;
94 1.1 glass
95 1.1 glass function = NONE;
96 1.1 glass portnum = 0;
97 1.1 glass errflg = 0;
98 1.1 glass while ((c = getopt(argc, argv, "ptubdn:")) != EOF) {
99 1.1 glass switch (c) {
100 1.1 glass
101 1.1 glass case 'p':
102 1.1 glass if (function != NONE)
103 1.1 glass errflg = 1;
104 1.1 glass else
105 1.1 glass function = PMAPDUMP;
106 1.1 glass break;
107 1.1 glass
108 1.1 glass case 't':
109 1.1 glass if (function != NONE)
110 1.1 glass errflg = 1;
111 1.1 glass else
112 1.1 glass function = TCPPING;
113 1.1 glass break;
114 1.1 glass
115 1.1 glass case 'u':
116 1.1 glass if (function != NONE)
117 1.1 glass errflg = 1;
118 1.1 glass else
119 1.1 glass function = UDPPING;
120 1.1 glass break;
121 1.1 glass
122 1.1 glass case 'b':
123 1.1 glass if (function != NONE)
124 1.1 glass errflg = 1;
125 1.1 glass else
126 1.1 glass function = BRDCST;
127 1.1 glass break;
128 1.1 glass
129 1.1 glass case 'n':
130 1.1 glass portnum = (u_short) atoi(optarg); /* hope we don't get bogus # */
131 1.1 glass break;
132 1.1 glass
133 1.1 glass case 'd':
134 1.1 glass if (function != NONE)
135 1.1 glass errflg = 1;
136 1.1 glass else
137 1.1 glass function = DELETES;
138 1.1 glass break;
139 1.1 glass
140 1.1 glass case '?':
141 1.1 glass errflg = 1;
142 1.1 glass }
143 1.1 glass }
144 1.1 glass
145 1.1 glass if (errflg || function == NONE) {
146 1.1 glass usage();
147 1.1 glass return (1);
148 1.1 glass }
149 1.1 glass
150 1.1 glass switch (function) {
151 1.1 glass
152 1.1 glass case PMAPDUMP:
153 1.1 glass if (portnum != 0) {
154 1.1 glass usage();
155 1.1 glass return (1);
156 1.1 glass }
157 1.1 glass pmapdump(argc - optind, argv + optind);
158 1.1 glass break;
159 1.1 glass
160 1.1 glass case UDPPING:
161 1.1 glass udpping(portnum, argc - optind, argv + optind);
162 1.1 glass break;
163 1.1 glass
164 1.1 glass case TCPPING:
165 1.1 glass tcpping(portnum, argc - optind, argv + optind);
166 1.1 glass break;
167 1.1 glass
168 1.1 glass case BRDCST:
169 1.1 glass if (portnum != 0) {
170 1.1 glass usage();
171 1.1 glass return (1);
172 1.1 glass }
173 1.1 glass brdcst(argc - optind, argv + optind);
174 1.1 glass break;
175 1.1 glass
176 1.1 glass case DELETES:
177 1.1 glass deletereg(argc - optind, argv + optind);
178 1.1 glass break;
179 1.1 glass }
180 1.1 glass
181 1.1 glass return (0);
182 1.1 glass }
183 1.1 glass
184 1.1 glass static void
185 1.1 glass udpping(portnum, argc, argv)
186 1.1 glass u_short portnum;
187 1.1 glass int argc;
188 1.1 glass char **argv;
189 1.1 glass {
190 1.1 glass struct timeval to;
191 1.1 glass struct sockaddr_in addr;
192 1.1 glass enum clnt_stat rpc_stat;
193 1.1 glass CLIENT *client;
194 1.1 glass u_long prognum, vers, minvers, maxvers;
195 1.1 glass int sock = RPC_ANYSOCK;
196 1.1 glass struct rpc_err rpcerr;
197 1.1 glass int failure;
198 1.1 glass
199 1.1 glass if (argc < 2 || argc > 3) {
200 1.1 glass usage();
201 1.1 glass exit(1);
202 1.1 glass }
203 1.1 glass prognum = getprognum(argv[1]);
204 1.1 glass get_inet_address(&addr, argv[0]);
205 1.1 glass /* Open the socket here so it will survive calls to clnt_destroy */
206 1.1 glass sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
207 1.1 glass if (sock < 0) {
208 1.1 glass perror("rpcinfo: socket");
209 1.1 glass exit(1);
210 1.1 glass }
211 1.1 glass failure = 0;
212 1.1 glass if (argc == 2) {
213 1.1 glass /*
214 1.1 glass * A call to version 0 should fail with a program/version
215 1.1 glass * mismatch, and give us the range of versions supported.
216 1.1 glass */
217 1.1 glass addr.sin_port = htons(portnum);
218 1.1 glass to.tv_sec = 5;
219 1.1 glass to.tv_usec = 0;
220 1.1 glass if ((client = clntudp_create(&addr, prognum, (u_long)0,
221 1.1 glass to, &sock)) == NULL) {
222 1.1 glass clnt_pcreateerror("rpcinfo");
223 1.1 glass printf("program %lu is not available\n",
224 1.1 glass prognum);
225 1.1 glass exit(1);
226 1.1 glass }
227 1.1 glass to.tv_sec = 10;
228 1.1 glass to.tv_usec = 0;
229 1.1 glass rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
230 1.1 glass xdr_void, (char *)NULL, to);
231 1.1 glass if (rpc_stat == RPC_PROGVERSMISMATCH) {
232 1.1 glass clnt_geterr(client, &rpcerr);
233 1.1 glass minvers = rpcerr.re_vers.low;
234 1.1 glass maxvers = rpcerr.re_vers.high;
235 1.1 glass } else if (rpc_stat == RPC_SUCCESS) {
236 1.1 glass /*
237 1.1 glass * Oh dear, it DOES support version 0.
238 1.1 glass * Let's try version MAX_VERS.
239 1.1 glass */
240 1.1 glass addr.sin_port = htons(portnum);
241 1.1 glass to.tv_sec = 5;
242 1.1 glass to.tv_usec = 0;
243 1.1 glass if ((client = clntudp_create(&addr, prognum, MAX_VERS,
244 1.1 glass to, &sock)) == NULL) {
245 1.1 glass clnt_pcreateerror("rpcinfo");
246 1.1 glass printf("program %lu version %lu is not available\n",
247 1.1 glass prognum, MAX_VERS);
248 1.1 glass exit(1);
249 1.1 glass }
250 1.1 glass to.tv_sec = 10;
251 1.1 glass to.tv_usec = 0;
252 1.1 glass rpc_stat = clnt_call(client, NULLPROC, xdr_void,
253 1.1 glass (char *)NULL, xdr_void, (char *)NULL, to);
254 1.1 glass if (rpc_stat == RPC_PROGVERSMISMATCH) {
255 1.1 glass clnt_geterr(client, &rpcerr);
256 1.1 glass minvers = rpcerr.re_vers.low;
257 1.1 glass maxvers = rpcerr.re_vers.high;
258 1.1 glass } else if (rpc_stat == RPC_SUCCESS) {
259 1.1 glass /*
260 1.1 glass * It also supports version MAX_VERS.
261 1.1 glass * Looks like we have a wise guy.
262 1.1 glass * OK, we give them information on all
263 1.1 glass * 4 billion versions they support...
264 1.1 glass */
265 1.1 glass minvers = 0;
266 1.1 glass maxvers = MAX_VERS;
267 1.1 glass } else {
268 1.1 glass (void) pstatus(client, prognum, MAX_VERS);
269 1.1 glass exit(1);
270 1.1 glass }
271 1.1 glass } else {
272 1.1 glass (void) pstatus(client, prognum, (u_long)0);
273 1.1 glass exit(1);
274 1.1 glass }
275 1.1 glass clnt_destroy(client);
276 1.1 glass for (vers = minvers; vers <= maxvers; vers++) {
277 1.1 glass addr.sin_port = htons(portnum);
278 1.1 glass to.tv_sec = 5;
279 1.1 glass to.tv_usec = 0;
280 1.1 glass if ((client = clntudp_create(&addr, prognum, vers,
281 1.1 glass to, &sock)) == NULL) {
282 1.1 glass clnt_pcreateerror("rpcinfo");
283 1.1 glass printf("program %lu version %lu is not available\n",
284 1.1 glass prognum, vers);
285 1.1 glass exit(1);
286 1.1 glass }
287 1.1 glass to.tv_sec = 10;
288 1.1 glass to.tv_usec = 0;
289 1.1 glass rpc_stat = clnt_call(client, NULLPROC, xdr_void,
290 1.1 glass (char *)NULL, xdr_void, (char *)NULL, to);
291 1.1 glass if (pstatus(client, prognum, vers) < 0)
292 1.1 glass failure = 1;
293 1.1 glass clnt_destroy(client);
294 1.1 glass }
295 1.1 glass }
296 1.1 glass else {
297 1.1 glass vers = getvers(argv[2]);
298 1.1 glass addr.sin_port = htons(portnum);
299 1.1 glass to.tv_sec = 5;
300 1.1 glass to.tv_usec = 0;
301 1.1 glass if ((client = clntudp_create(&addr, prognum, vers,
302 1.1 glass to, &sock)) == NULL) {
303 1.1 glass clnt_pcreateerror("rpcinfo");
304 1.1 glass printf("program %lu version %lu is not available\n",
305 1.1 glass prognum, vers);
306 1.1 glass exit(1);
307 1.1 glass }
308 1.1 glass to.tv_sec = 10;
309 1.1 glass to.tv_usec = 0;
310 1.1 glass rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
311 1.1 glass xdr_void, (char *)NULL, to);
312 1.1 glass if (pstatus(client, prognum, vers) < 0)
313 1.1 glass failure = 1;
314 1.1 glass }
315 1.1 glass (void) close(sock); /* Close it up again */
316 1.1 glass if (failure)
317 1.1 glass exit(1);
318 1.1 glass }
319 1.1 glass
320 1.1 glass static void
321 1.1 glass tcpping(portnum, argc, argv)
322 1.1 glass u_short portnum;
323 1.1 glass int argc;
324 1.1 glass char **argv;
325 1.1 glass {
326 1.1 glass struct timeval to;
327 1.1 glass struct sockaddr_in addr;
328 1.1 glass enum clnt_stat rpc_stat;
329 1.1 glass CLIENT *client;
330 1.1 glass u_long prognum, vers, minvers, maxvers;
331 1.1 glass int sock = RPC_ANYSOCK;
332 1.1 glass struct rpc_err rpcerr;
333 1.1 glass int failure;
334 1.1 glass
335 1.1 glass if (argc < 2 || argc > 3) {
336 1.1 glass usage();
337 1.1 glass exit(1);
338 1.1 glass }
339 1.1 glass prognum = getprognum(argv[1]);
340 1.1 glass get_inet_address(&addr, argv[0]);
341 1.1 glass failure = 0;
342 1.1 glass if (argc == 2) {
343 1.1 glass /*
344 1.1 glass * A call to version 0 should fail with a program/version
345 1.1 glass * mismatch, and give us the range of versions supported.
346 1.1 glass */
347 1.1 glass addr.sin_port = htons(portnum);
348 1.1 glass if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
349 1.1 glass &sock, 0, 0)) == NULL) {
350 1.1 glass clnt_pcreateerror("rpcinfo");
351 1.1 glass printf("program %lu is not available\n",
352 1.1 glass prognum);
353 1.1 glass exit(1);
354 1.1 glass }
355 1.1 glass to.tv_sec = 10;
356 1.1 glass to.tv_usec = 0;
357 1.1 glass rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
358 1.1 glass xdr_void, (char *)NULL, to);
359 1.1 glass if (rpc_stat == RPC_PROGVERSMISMATCH) {
360 1.1 glass clnt_geterr(client, &rpcerr);
361 1.1 glass minvers = rpcerr.re_vers.low;
362 1.1 glass maxvers = rpcerr.re_vers.high;
363 1.1 glass } else if (rpc_stat == RPC_SUCCESS) {
364 1.1 glass /*
365 1.1 glass * Oh dear, it DOES support version 0.
366 1.1 glass * Let's try version MAX_VERS.
367 1.1 glass */
368 1.1 glass addr.sin_port = htons(portnum);
369 1.1 glass if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
370 1.1 glass &sock, 0, 0)) == NULL) {
371 1.1 glass clnt_pcreateerror("rpcinfo");
372 1.1 glass printf("program %lu version %lu is not available\n",
373 1.1 glass prognum, MAX_VERS);
374 1.1 glass exit(1);
375 1.1 glass }
376 1.1 glass to.tv_sec = 10;
377 1.1 glass to.tv_usec = 0;
378 1.1 glass rpc_stat = clnt_call(client, NULLPROC, xdr_void,
379 1.1 glass (char *)NULL, xdr_void, (char *)NULL, to);
380 1.1 glass if (rpc_stat == RPC_PROGVERSMISMATCH) {
381 1.1 glass clnt_geterr(client, &rpcerr);
382 1.1 glass minvers = rpcerr.re_vers.low;
383 1.1 glass maxvers = rpcerr.re_vers.high;
384 1.1 glass } else if (rpc_stat == RPC_SUCCESS) {
385 1.1 glass /*
386 1.1 glass * It also supports version MAX_VERS.
387 1.1 glass * Looks like we have a wise guy.
388 1.1 glass * OK, we give them information on all
389 1.1 glass * 4 billion versions they support...
390 1.1 glass */
391 1.1 glass minvers = 0;
392 1.1 glass maxvers = MAX_VERS;
393 1.1 glass } else {
394 1.1 glass (void) pstatus(client, prognum, MAX_VERS);
395 1.1 glass exit(1);
396 1.1 glass }
397 1.1 glass } else {
398 1.1 glass (void) pstatus(client, prognum, MIN_VERS);
399 1.1 glass exit(1);
400 1.1 glass }
401 1.1 glass clnt_destroy(client);
402 1.1 glass (void) close(sock);
403 1.1 glass sock = RPC_ANYSOCK; /* Re-initialize it for later */
404 1.1 glass for (vers = minvers; vers <= maxvers; vers++) {
405 1.1 glass addr.sin_port = htons(portnum);
406 1.1 glass if ((client = clnttcp_create(&addr, prognum, vers,
407 1.1 glass &sock, 0, 0)) == NULL) {
408 1.1 glass clnt_pcreateerror("rpcinfo");
409 1.1 glass printf("program %lu version %lu is not available\n",
410 1.1 glass prognum, vers);
411 1.1 glass exit(1);
412 1.1 glass }
413 1.1 glass to.tv_usec = 0;
414 1.1 glass to.tv_sec = 10;
415 1.1 glass rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
416 1.1 glass xdr_void, (char *)NULL, to);
417 1.1 glass if (pstatus(client, prognum, vers) < 0)
418 1.1 glass failure = 1;
419 1.1 glass clnt_destroy(client);
420 1.1 glass (void) close(sock);
421 1.1 glass sock = RPC_ANYSOCK;
422 1.1 glass }
423 1.1 glass }
424 1.1 glass else {
425 1.1 glass vers = getvers(argv[2]);
426 1.1 glass addr.sin_port = htons(portnum);
427 1.1 glass if ((client = clnttcp_create(&addr, prognum, vers, &sock,
428 1.1 glass 0, 0)) == NULL) {
429 1.1 glass clnt_pcreateerror("rpcinfo");
430 1.1 glass printf("program %lu version %lu is not available\n",
431 1.1 glass prognum, vers);
432 1.1 glass exit(1);
433 1.1 glass }
434 1.1 glass to.tv_usec = 0;
435 1.1 glass to.tv_sec = 10;
436 1.1 glass rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
437 1.1 glass xdr_void, (char *)NULL, to);
438 1.1 glass if (pstatus(client, prognum, vers) < 0)
439 1.1 glass failure = 1;
440 1.1 glass }
441 1.1 glass if (failure)
442 1.1 glass exit(1);
443 1.1 glass }
444 1.1 glass
445 1.1 glass /*
446 1.1 glass * This routine should take a pointer to an "rpc_err" structure, rather than
447 1.1 glass * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
448 1.1 glass * a CLIENT structure rather than a pointer to an "rpc_err" structure.
449 1.1 glass * As such, we have to keep the CLIENT structure around in order to print
450 1.1 glass * a good error message.
451 1.1 glass */
452 1.1 glass static int
453 1.1 glass pstatus(client, prognum, vers)
454 1.1 glass register CLIENT *client;
455 1.1 glass u_long prognum;
456 1.1 glass u_long vers;
457 1.1 glass {
458 1.1 glass struct rpc_err rpcerr;
459 1.1 glass
460 1.1 glass clnt_geterr(client, &rpcerr);
461 1.1 glass if (rpcerr.re_status != RPC_SUCCESS) {
462 1.1 glass clnt_perror(client, "rpcinfo");
463 1.1 glass printf("program %lu version %lu is not available\n",
464 1.1 glass prognum, vers);
465 1.1 glass return (-1);
466 1.1 glass } else {
467 1.1 glass printf("program %lu version %lu ready and waiting\n",
468 1.1 glass prognum, vers);
469 1.1 glass return (0);
470 1.1 glass }
471 1.1 glass }
472 1.1 glass
473 1.1 glass static void
474 1.1 glass pmapdump(argc, argv)
475 1.1 glass int argc;
476 1.1 glass char **argv;
477 1.1 glass {
478 1.1 glass struct sockaddr_in server_addr;
479 1.1 glass register struct hostent *hp;
480 1.1 glass struct pmaplist *head = NULL;
481 1.1 glass int socket = RPC_ANYSOCK;
482 1.1 glass struct timeval minutetimeout;
483 1.1 glass register CLIENT *client;
484 1.1 glass struct rpcent *rpc;
485 1.1 glass
486 1.1 glass if (argc > 1) {
487 1.1 glass usage();
488 1.1 glass exit(1);
489 1.1 glass }
490 1.1 glass if (argc == 1)
491 1.1 glass get_inet_address(&server_addr, argv[0]);
492 1.1 glass else {
493 1.1 glass bzero((char *)&server_addr, sizeof server_addr);
494 1.1 glass server_addr.sin_family = AF_INET;
495 1.1 glass if ((hp = gethostbyname("localhost")) != NULL)
496 1.1 glass bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
497 1.1 glass hp->h_length);
498 1.1 glass else
499 1.1 glass server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
500 1.1 glass }
501 1.1 glass minutetimeout.tv_sec = 60;
502 1.1 glass minutetimeout.tv_usec = 0;
503 1.1 glass server_addr.sin_port = htons(PMAPPORT);
504 1.1 glass if ((client = clnttcp_create(&server_addr, PMAPPROG,
505 1.1 glass PMAPVERS, &socket, 50, 500)) == NULL) {
506 1.1 glass clnt_pcreateerror("rpcinfo: can't contact portmapper");
507 1.1 glass exit(1);
508 1.1 glass }
509 1.1 glass if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
510 1.1 glass xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
511 1.1 glass fprintf(stderr, "rpcinfo: can't contact portmapper: ");
512 1.1 glass clnt_perror(client, "rpcinfo");
513 1.1 glass exit(1);
514 1.1 glass }
515 1.1 glass if (head == NULL) {
516 1.1 glass printf("No remote programs registered.\n");
517 1.1 glass } else {
518 1.1 glass printf(" program vers proto port\n");
519 1.1 glass for (; head != NULL; head = head->pml_next) {
520 1.1 glass printf("%10ld%5ld",
521 1.1 glass head->pml_map.pm_prog,
522 1.1 glass head->pml_map.pm_vers);
523 1.1 glass if (head->pml_map.pm_prot == IPPROTO_UDP)
524 1.1 glass printf("%6s", "udp");
525 1.1 glass else if (head->pml_map.pm_prot == IPPROTO_TCP)
526 1.1 glass printf("%6s", "tcp");
527 1.1 glass else
528 1.1 glass printf("%6ld", head->pml_map.pm_prot);
529 1.1 glass printf("%7ld", head->pml_map.pm_port);
530 1.1 glass rpc = getrpcbynumber(head->pml_map.pm_prog);
531 1.1 glass if (rpc)
532 1.1 glass printf(" %s\n", rpc->r_name);
533 1.1 glass else
534 1.1 glass printf("\n");
535 1.1 glass }
536 1.1 glass }
537 1.1 glass }
538 1.1 glass
539 1.1 glass /*
540 1.1 glass * reply_proc collects replies from the broadcast.
541 1.1 glass * to get a unique list of responses the output of rpcinfo should
542 1.1 glass * be piped through sort(1) and then uniq(1).
543 1.1 glass */
544 1.1 glass
545 1.1 glass /*ARGSUSED*/
546 1.1 glass static bool_t
547 1.1 glass reply_proc(res, who)
548 1.1 glass void *res; /* Nothing comes back */
549 1.1 glass struct sockaddr_in *who; /* Who sent us the reply */
550 1.1 glass {
551 1.1 glass register struct hostent *hp;
552 1.1 glass
553 1.1 glass hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
554 1.1 glass AF_INET);
555 1.1 glass printf("%s %s\n", inet_ntoa(who->sin_addr),
556 1.1 glass (hp == NULL) ? "(unknown)" : hp->h_name);
557 1.1 glass return(FALSE);
558 1.1 glass }
559 1.1 glass
560 1.1 glass static void
561 1.1 glass brdcst(argc, argv)
562 1.1 glass int argc;
563 1.1 glass char **argv;
564 1.1 glass {
565 1.1 glass enum clnt_stat rpc_stat;
566 1.1 glass u_long prognum, vers;
567 1.1 glass
568 1.1 glass if (argc != 2) {
569 1.1 glass usage();
570 1.1 glass exit(1);
571 1.1 glass }
572 1.1 glass prognum = getprognum(argv[0]);
573 1.1 glass vers = getvers(argv[1]);
574 1.1 glass rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
575 1.1 glass (char *)NULL, xdr_void, (char *)NULL, reply_proc);
576 1.1 glass if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
577 1.1 glass fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
578 1.1 glass clnt_sperrno(rpc_stat));
579 1.1 glass exit(1);
580 1.1 glass }
581 1.1 glass exit(0);
582 1.1 glass }
583 1.1 glass
584 1.1 glass static void
585 1.1 glass deletereg(argc, argv)
586 1.1 glass int argc;
587 1.1 glass char **argv;
588 1.1 glass { u_long prog_num, version_num ;
589 1.1 glass
590 1.1 glass if (argc != 2) {
591 1.1 glass usage() ;
592 1.1 glass exit(1) ;
593 1.1 glass }
594 1.1 glass if (getuid()) { /* This command allowed only to root */
595 1.1 glass fprintf(stderr, "Sorry. You are not root\n") ;
596 1.1 glass exit(1) ;
597 1.1 glass }
598 1.1 glass prog_num = getprognum(argv[0]);
599 1.1 glass version_num = getvers(argv[1]);
600 1.1 glass if ((pmap_unset(prog_num, version_num)) == 0) {
601 1.1 glass fprintf(stderr, "rpcinfo: Could not delete registration for prog %s version %s\n",
602 1.1 glass argv[0], argv[1]) ;
603 1.1 glass exit(1) ;
604 1.1 glass }
605 1.1 glass }
606 1.1 glass
607 1.1 glass static void
608 1.1 glass usage()
609 1.1 glass {
610 1.1 glass fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n");
611 1.1 glass fprintf(stderr, " rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n");
612 1.1 glass fprintf(stderr, " rpcinfo -p [ host ]\n");
613 1.1 glass fprintf(stderr, " rpcinfo -b prognum versnum\n");
614 1.1 glass fprintf(stderr, " rpcinfo -d prognum versnum\n") ;
615 1.1 glass }
616 1.1 glass
617 1.1 glass static u_long
618 1.1 glass getprognum(arg)
619 1.1 glass char *arg;
620 1.1 glass {
621 1.1 glass register struct rpcent *rpc;
622 1.1 glass register u_long prognum;
623 1.1 glass
624 1.1 glass if (isalpha(*arg)) {
625 1.1 glass rpc = getrpcbyname(arg);
626 1.1 glass if (rpc == NULL) {
627 1.1 glass fprintf(stderr, "rpcinfo: %s is unknown service\n",
628 1.1 glass arg);
629 1.1 glass exit(1);
630 1.1 glass }
631 1.1 glass prognum = rpc->r_number;
632 1.1 glass } else {
633 1.1 glass prognum = (u_long) atoi(arg);
634 1.1 glass }
635 1.1 glass
636 1.1 glass return (prognum);
637 1.1 glass }
638 1.1 glass
639 1.1 glass static u_long
640 1.1 glass getvers(arg)
641 1.1 glass char *arg;
642 1.1 glass {
643 1.1 glass register u_long vers;
644 1.1 glass
645 1.1 glass vers = (int) atoi(arg);
646 1.1 glass return (vers);
647 1.1 glass }
648 1.1 glass
649 1.1 glass static void
650 1.1 glass get_inet_address(addr, host)
651 1.1 glass struct sockaddr_in *addr;
652 1.1 glass char *host;
653 1.1 glass {
654 1.1 glass register struct hostent *hp;
655 1.1 glass
656 1.1 glass bzero((char *)addr, sizeof *addr);
657 1.1 glass addr->sin_addr.s_addr = (u_long) inet_addr(host);
658 1.1 glass if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
659 1.1 glass if ((hp = gethostbyname(host)) == NULL) {
660 1.1 glass fprintf(stderr, "rpcinfo: %s is unknown host\n", host);
661 1.1 glass exit(1);
662 1.1 glass }
663 1.1 glass bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length);
664 1.1 glass }
665 1.1 glass addr->sin_family = AF_INET;
666 1.1 glass }
667