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