File: | src/usr.bin/rpcinfo/rpcinfo.c |
Warning: | line 320, column 3 Value stored to 'rpc_stat' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: rpcinfo.c,v 1.16 2023/03/08 04:43:12 guenther Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2010, Oracle America, Inc. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions are |
8 | * met: |
9 | * |
10 | * * Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * * Redistributions in binary form must reproduce the above |
13 | * copyright notice, this list of conditions and the following |
14 | * disclaimer in the documentation and/or other materials |
15 | * provided with the distribution. |
16 | * * Neither the name of the "Oracle America, Inc." nor the names of its |
17 | * contributors may be used to endorse or promote products derived |
18 | * from this software without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
27 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | |
34 | /* |
35 | * rpcinfo: ping a particular rpc program |
36 | * or dump the portmapper |
37 | */ |
38 | |
39 | #include <rpc/rpc.h> |
40 | #include <stdio.h> |
41 | #include <sys/socket.h> |
42 | #include <netdb.h> |
43 | #include <rpc/pmap_prot.h> |
44 | #include <rpc/pmap_clnt.h> |
45 | #include <signal.h> |
46 | #include <string.h> |
47 | #include <stdlib.h> |
48 | #include <unistd.h> |
49 | #include <ctype.h> |
50 | #include <errno(*__errno()).h> |
51 | #include <limits.h> |
52 | #include <arpa/inet.h> |
53 | |
54 | #define MAXHOSTLEN256 256 |
55 | |
56 | #define MIN_VERS((u_long) 0) ((u_long) 0) |
57 | #define MAX_VERS((u_long) 4294967295UL) ((u_long) 4294967295UL) |
58 | |
59 | void udpping(u_short portflag, int argc, char **argv); |
60 | void tcpping(u_short portflag, int argc, char **argv); |
61 | int pstatus(CLIENT *client, u_long prognum, u_long vers); |
62 | void pmapdump(int argc, char **argv); |
63 | bool_tint32_t reply_proc(caddr_t res, struct sockaddr_in *who); |
64 | void brdcst(int argc, char **argv); |
65 | void deletereg(int argc, char **argv); |
66 | void setreg(int argc, char **argv); |
67 | void usage(char *); |
68 | int getprognum(char *arg, u_long *ulp); |
69 | int getul(char *arg, u_long *ulp); |
70 | void get_inet_address(struct sockaddr_in *addr, char *host); |
71 | |
72 | /* |
73 | * Functions to be performed. |
74 | */ |
75 | #define NONE0 0 /* no function */ |
76 | #define PMAPDUMP1 1 /* dump portmapper registrations */ |
77 | #define TCPPING2 2 /* ping TCP service */ |
78 | #define UDPPING3 3 /* ping UDP service */ |
79 | #define BRDCST4 4 /* ping broadcast UDP service */ |
80 | #define DELETES5 5 /* delete registration for the service */ |
81 | #define SETS6 6 /* set registration for the service */ |
82 | |
83 | int |
84 | main(int argc, char *argv[]) |
85 | { |
86 | int c; |
87 | extern char *optarg; |
88 | extern int optind; |
89 | int errflg; |
90 | int function; |
91 | u_short portnum; |
92 | u_long tmp; |
93 | |
94 | function = NONE0; |
95 | portnum = 0; |
96 | errflg = 0; |
97 | while ((c = getopt(argc, argv, "ptubdsn:")) != -1) { |
98 | switch (c) { |
99 | |
100 | case 'p': |
101 | if (function != NONE0) |
102 | errflg = 1; |
103 | else |
104 | function = PMAPDUMP1; |
105 | break; |
106 | |
107 | case 't': |
108 | if (function != NONE0) |
109 | errflg = 1; |
110 | else |
111 | function = TCPPING2; |
112 | break; |
113 | |
114 | case 'u': |
115 | if (function != NONE0) |
116 | errflg = 1; |
117 | else |
118 | function = UDPPING3; |
119 | break; |
120 | |
121 | case 'b': |
122 | if (function != NONE0) |
123 | errflg = 1; |
124 | else |
125 | function = BRDCST4; |
126 | break; |
127 | |
128 | case 'n': |
129 | if (getul(optarg, &tmp)) |
130 | usage("invalid port number"); |
131 | if (tmp >= 65536) |
132 | usage("port number out of range"); |
133 | portnum = (u_short)tmp; |
134 | break; |
135 | |
136 | case 'd': |
137 | if (function != NONE0) |
138 | errflg = 1; |
139 | else |
140 | function = DELETES5; |
141 | break; |
142 | |
143 | case 's': |
144 | if (function != NONE0) |
145 | errflg = 1; |
146 | else |
147 | function = SETS6; |
148 | break; |
149 | |
150 | |
151 | case '?': |
152 | errflg = 1; |
153 | } |
154 | } |
155 | |
156 | if (errflg || function == NONE0) |
157 | usage(NULL0); |
158 | |
159 | switch (function) { |
160 | |
161 | case PMAPDUMP1: |
162 | if (portnum != 0) |
163 | usage(NULL0); |
164 | pmapdump(argc - optind, argv + optind); |
165 | break; |
166 | |
167 | case UDPPING3: |
168 | udpping(portnum, argc - optind, argv + optind); |
169 | break; |
170 | |
171 | case TCPPING2: |
172 | tcpping(portnum, argc - optind, argv + optind); |
173 | break; |
174 | |
175 | case BRDCST4: |
176 | if (portnum != 0) |
177 | usage(NULL0); |
178 | |
179 | brdcst(argc - optind, argv + optind); |
180 | break; |
181 | |
182 | case DELETES5: |
183 | deletereg(argc - optind, argv + optind); |
184 | break; |
185 | |
186 | case SETS6: |
187 | setreg(argc - optind, argv + optind); |
188 | break; |
189 | } |
190 | |
191 | return (0); |
192 | } |
193 | |
194 | void |
195 | udpping(u_short portnum, int argc, char **argv) |
196 | { |
197 | struct timeval to; |
198 | struct sockaddr_in addr; |
199 | enum clnt_stat rpc_stat; |
200 | CLIENT *client; |
201 | u_long prognum, vers, minvers, maxvers; |
202 | int sock = RPC_ANYSOCK-1; |
203 | struct rpc_err rpcerr; |
204 | int failure; |
205 | |
206 | if (argc < 2) |
207 | usage("too few arguments"); |
208 | if (argc > 3) |
209 | usage("too many arguments"); |
210 | if (getprognum(argv[1], &prognum)) |
211 | usage("program number out of range"); |
212 | |
213 | get_inet_address(&addr, argv[0]); |
214 | /* Open the socket here so it will survive calls to clnt_destroy */ |
215 | sock = socket(AF_INET2, SOCK_DGRAM2, IPPROTO_UDP17); |
216 | if (sock == -1) { |
217 | perror("rpcinfo: socket"); |
218 | exit(1); |
219 | } |
220 | if (getuid() == 0) |
221 | bindresvport(sock, NULL0); |
222 | failure = 0; |
223 | if (argc == 2) { |
224 | /* |
225 | * A call to version 0 should fail with a program/version |
226 | * mismatch, and give us the range of versions supported. |
227 | */ |
228 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
229 | to.tv_sec = 5; |
230 | to.tv_usec = 0; |
231 | if ((client = clntudp_create(&addr, prognum, (u_long)0, |
232 | to, &sock)) == NULL0) { |
233 | clnt_pcreateerror("rpcinfo"); |
234 | printf("program %lu is not available\n", |
235 | prognum); |
236 | exit(1); |
237 | } |
238 | to.tv_sec = 10; |
239 | to.tv_usec = 0; |
240 | rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
241 | xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
242 | if (rpc_stat == RPC_PROGVERSMISMATCH) { |
243 | clnt_geterr(client, &rpcerr)((*(client)->cl_ops->cl_geterr)(client, &rpcerr)); |
244 | minvers = rpcerr.re_versru.RE_vers.low; |
245 | maxvers = rpcerr.re_versru.RE_vers.high; |
246 | } else if (rpc_stat == RPC_SUCCESS) { |
247 | /* |
248 | * Oh dear, it DOES support version 0. |
249 | * Let's try version MAX_VERS. |
250 | */ |
251 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
252 | to.tv_sec = 5; |
253 | to.tv_usec = 0; |
254 | if ((client = clntudp_create(&addr, prognum, MAX_VERS((u_long) 4294967295UL), |
255 | to, &sock)) == NULL0) { |
256 | clnt_pcreateerror("rpcinfo"); |
257 | printf("program %lu version %lu is not available\n", |
258 | prognum, MAX_VERS((u_long) 4294967295UL)); |
259 | exit(1); |
260 | } |
261 | to.tv_sec = 10; |
262 | to.tv_usec = 0; |
263 | rpc_stat = clnt_call(client, NULLPROC, xdr_void,((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
264 | (char *)NULL, xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
265 | if (rpc_stat == RPC_PROGVERSMISMATCH) { |
266 | clnt_geterr(client, &rpcerr)((*(client)->cl_ops->cl_geterr)(client, &rpcerr)); |
267 | minvers = rpcerr.re_versru.RE_vers.low; |
268 | maxvers = rpcerr.re_versru.RE_vers.high; |
269 | } else if (rpc_stat == RPC_SUCCESS) { |
270 | /* |
271 | * It also supports version MAX_VERS. |
272 | * Looks like we have a wise guy. |
273 | * OK, we give them information on all |
274 | * 4 billion versions they support... |
275 | */ |
276 | minvers = 0; |
277 | maxvers = MAX_VERS((u_long) 4294967295UL); |
278 | } else { |
279 | (void) pstatus(client, prognum, MAX_VERS((u_long) 4294967295UL)); |
280 | exit(1); |
281 | } |
282 | } else { |
283 | (void) pstatus(client, prognum, (u_long)0); |
284 | exit(1); |
285 | } |
286 | clnt_destroy(client)((*(client)->cl_ops->cl_destroy)(client)); |
287 | for (vers = minvers; vers <= maxvers; vers++) { |
288 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
289 | to.tv_sec = 5; |
290 | to.tv_usec = 0; |
291 | if ((client = clntudp_create(&addr, prognum, vers, |
292 | to, &sock)) == NULL0) { |
293 | clnt_pcreateerror("rpcinfo"); |
294 | printf("program %lu version %lu is not available\n", |
295 | prognum, vers); |
296 | exit(1); |
297 | } |
298 | to.tv_sec = 10; |
299 | to.tv_usec = 0; |
300 | rpc_stat = clnt_call(client, NULLPROC, xdr_void,((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
301 | (char *)NULL, xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
302 | if (pstatus(client, prognum, vers) < 0) |
303 | failure = 1; |
304 | clnt_destroy(client)((*(client)->cl_ops->cl_destroy)(client)); |
305 | } |
306 | } else { |
307 | getul(argv[2], &vers); /* XXX */ |
308 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
309 | to.tv_sec = 5; |
310 | to.tv_usec = 0; |
311 | if ((client = clntudp_create(&addr, prognum, vers, |
312 | to, &sock)) == NULL0) { |
313 | clnt_pcreateerror("rpcinfo"); |
314 | printf("program %lu version %lu is not available\n", |
315 | prognum, vers); |
316 | exit(1); |
317 | } |
318 | to.tv_sec = 10; |
319 | to.tv_usec = 0; |
320 | rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,((*(client)->cl_ops->cl_call)(client, 0, xdr_void, (caddr_t )(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
Value stored to 'rpc_stat' is never read | |
321 | xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, 0, xdr_void, (caddr_t )(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
322 | if (pstatus(client, prognum, vers) < 0) |
323 | failure = 1; |
324 | } |
325 | (void) close(sock); /* Close it up again */ |
326 | if (failure) |
327 | exit(1); |
328 | } |
329 | |
330 | void |
331 | tcpping(u_short portnum, int argc, char **argv) |
332 | { |
333 | struct timeval to; |
334 | struct sockaddr_in addr; |
335 | enum clnt_stat rpc_stat; |
336 | CLIENT *client; |
337 | u_long prognum, vers, minvers, maxvers; |
338 | int sock = RPC_ANYSOCK-1; |
339 | struct rpc_err rpcerr; |
340 | int failure; |
341 | |
342 | if (argc < 2) |
343 | usage("too few arguments"); |
344 | if (argc > 3) |
345 | usage("too many arguments"); |
346 | if (getprognum(argv[1], &prognum)) |
347 | usage("program number out of range"); |
348 | |
349 | get_inet_address(&addr, argv[0]); |
350 | failure = 0; |
351 | if (argc == 2) { |
352 | /* |
353 | * A call to version 0 should fail with a program/version |
354 | * mismatch, and give us the range of versions supported. |
355 | */ |
356 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
357 | if ((client = clnttcp_create(&addr, prognum, MIN_VERS((u_long) 0), |
358 | &sock, 0, 0)) == NULL0) { |
359 | clnt_pcreateerror("rpcinfo"); |
360 | printf("program %lu is not available\n", |
361 | prognum); |
362 | exit(1); |
363 | } |
364 | to.tv_sec = 10; |
365 | to.tv_usec = 0; |
366 | rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
367 | xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
368 | if (rpc_stat == RPC_PROGVERSMISMATCH) { |
369 | clnt_geterr(client, &rpcerr)((*(client)->cl_ops->cl_geterr)(client, &rpcerr)); |
370 | minvers = rpcerr.re_versru.RE_vers.low; |
371 | maxvers = rpcerr.re_versru.RE_vers.high; |
372 | } else if (rpc_stat == RPC_SUCCESS) { |
373 | /* |
374 | * Oh dear, it DOES support version 0. |
375 | * Let's try version MAX_VERS. |
376 | */ |
377 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
378 | if ((client = clnttcp_create(&addr, prognum, MAX_VERS((u_long) 4294967295UL), |
379 | &sock, 0, 0)) == NULL0) { |
380 | clnt_pcreateerror("rpcinfo"); |
381 | printf("program %lu version %lu is not available\n", |
382 | prognum, MAX_VERS((u_long) 4294967295UL)); |
383 | exit(1); |
384 | } |
385 | to.tv_sec = 10; |
386 | to.tv_usec = 0; |
387 | rpc_stat = clnt_call(client, NULLPROC, xdr_void,((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
388 | (char *)NULL, xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, ((unsigned int)0) , xdr_void, (caddr_t)(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
389 | if (rpc_stat == RPC_PROGVERSMISMATCH) { |
390 | clnt_geterr(client, &rpcerr)((*(client)->cl_ops->cl_geterr)(client, &rpcerr)); |
391 | minvers = rpcerr.re_versru.RE_vers.low; |
392 | maxvers = rpcerr.re_versru.RE_vers.high; |
393 | } else if (rpc_stat == RPC_SUCCESS) { |
394 | /* |
395 | * It also supports version MAX_VERS. |
396 | * Looks like we have a wise guy. |
397 | * OK, we give them information on all |
398 | * 4 billion versions they support... |
399 | */ |
400 | minvers = 0; |
401 | maxvers = MAX_VERS((u_long) 4294967295UL); |
402 | } else { |
403 | (void) pstatus(client, prognum, MAX_VERS((u_long) 4294967295UL)); |
404 | exit(1); |
405 | } |
406 | } else { |
407 | (void) pstatus(client, prognum, MIN_VERS((u_long) 0)); |
408 | exit(1); |
409 | } |
410 | clnt_destroy(client)((*(client)->cl_ops->cl_destroy)(client)); |
411 | (void) close(sock); |
412 | sock = RPC_ANYSOCK-1; /* Re-initialize it for later */ |
413 | for (vers = minvers; vers <= maxvers; vers++) { |
414 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
415 | if ((client = clnttcp_create(&addr, prognum, vers, |
416 | &sock, 0, 0)) == NULL0) { |
417 | clnt_pcreateerror("rpcinfo"); |
418 | printf("program %lu version %lu is not available\n", |
419 | prognum, vers); |
420 | exit(1); |
421 | } |
422 | to.tv_usec = 0; |
423 | to.tv_sec = 10; |
424 | rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,((*(client)->cl_ops->cl_call)(client, 0, xdr_void, (caddr_t )(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
425 | xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, 0, xdr_void, (caddr_t )(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
426 | if (pstatus(client, prognum, vers) < 0) |
427 | failure = 1; |
428 | clnt_destroy(client)((*(client)->cl_ops->cl_destroy)(client)); |
429 | (void) close(sock); |
430 | sock = RPC_ANYSOCK-1; |
431 | } |
432 | } else { |
433 | getul(argv[2], &vers); /* XXX */ |
434 | addr.sin_port = htons(portnum)(__uint16_t)(__builtin_constant_p(portnum) ? (__uint16_t)(((__uint16_t )(portnum) & 0xffU) << 8 | ((__uint16_t)(portnum) & 0xff00U) >> 8) : __swap16md(portnum)); |
435 | if ((client = clnttcp_create(&addr, prognum, vers, &sock, |
436 | 0, 0)) == NULL0) { |
437 | clnt_pcreateerror("rpcinfo"); |
438 | printf("program %lu version %lu is not available\n", |
439 | prognum, vers); |
440 | exit(1); |
441 | } |
442 | to.tv_usec = 0; |
443 | to.tv_sec = 10; |
444 | rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,((*(client)->cl_ops->cl_call)(client, 0, xdr_void, (caddr_t )(char *)0, xdr_void, (caddr_t)(char *)0, to)) |
445 | xdr_void, (char *)NULL, to)((*(client)->cl_ops->cl_call)(client, 0, xdr_void, (caddr_t )(char *)0, xdr_void, (caddr_t)(char *)0, to)); |
446 | if (pstatus(client, prognum, vers) < 0) |
447 | failure = 1; |
448 | } |
449 | if (failure) |
450 | exit(1); |
451 | } |
452 | |
453 | /* |
454 | * This routine should take a pointer to an "rpc_err" structure, rather than |
455 | * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to |
456 | * a CLIENT structure rather than a pointer to an "rpc_err" structure. |
457 | * As such, we have to keep the CLIENT structure around in order to print |
458 | * a good error message. |
459 | */ |
460 | int |
461 | pstatus(CLIENT *client, u_long prognum, u_long vers) |
462 | { |
463 | struct rpc_err rpcerr; |
464 | |
465 | clnt_geterr(client, &rpcerr)((*(client)->cl_ops->cl_geterr)(client, &rpcerr)); |
466 | if (rpcerr.re_status != RPC_SUCCESS) { |
467 | clnt_perror(client, "rpcinfo"); |
468 | printf("program %lu version %lu is not available\n", |
469 | prognum, vers); |
470 | return (-1); |
471 | } else { |
472 | printf("program %lu version %lu ready and waiting\n", |
473 | prognum, vers); |
474 | return (0); |
475 | } |
476 | } |
477 | |
478 | void |
479 | pmapdump(int argc, char **argv) |
480 | { |
481 | struct sockaddr_in server_addr; |
482 | struct hostent *hp; |
483 | struct pmaplist *head = NULL0; |
484 | int socket = RPC_ANYSOCK-1; |
485 | struct timeval minutetimeout; |
486 | CLIENT *client; |
487 | struct rpcent *rpc; |
488 | |
489 | if (argc > 1) |
490 | usage("too many arguments"); |
491 | |
492 | if (argc == 1) |
493 | get_inet_address(&server_addr, argv[0]); |
494 | else { |
495 | bzero((char *)&server_addr, sizeof server_addr); |
496 | server_addr.sin_family = AF_INET2; |
497 | if ((hp = gethostbyname("localhost")) != NULL0) |
498 | bcopy(hp->h_addrh_addr_list[0], (caddr_t)&server_addr.sin_addr, |
499 | hp->h_length); |
500 | else |
501 | (void) inet_aton("0.0.0.0", &server_addr.sin_addr); |
502 | } |
503 | minutetimeout.tv_sec = 60; |
504 | minutetimeout.tv_usec = 0; |
505 | server_addr.sin_port = htons(PMAPPORT)(__uint16_t)(__builtin_constant_p(((unsigned short)111)) ? (__uint16_t )(((__uint16_t)(((unsigned short)111)) & 0xffU) << 8 | ((__uint16_t)(((unsigned short)111)) & 0xff00U) >> 8) : __swap16md(((unsigned short)111))); |
506 | if ((client = clnttcp_create(&server_addr, PMAPPROG((unsigned long)100000), |
507 | PMAPVERS((unsigned long)2), &socket, 50, 500)) == NULL0) { |
508 | clnt_pcreateerror("rpcinfo: can't contact portmapper"); |
509 | exit(1); |
510 | } |
511 | if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,((*(client)->cl_ops->cl_call)(client, ((unsigned long)4 ), xdr_void, (caddr_t)0, xdr_pmaplist, (caddr_t)&head, minutetimeout )) |
512 | xdr_pmaplist, &head, minutetimeout)((*(client)->cl_ops->cl_call)(client, ((unsigned long)4 ), xdr_void, (caddr_t)0, xdr_pmaplist, (caddr_t)&head, minutetimeout )) != RPC_SUCCESS) { |
513 | fprintf(stderr(&__sF[2]), "rpcinfo: can't contact portmapper: "); |
514 | clnt_perror(client, "rpcinfo"); |
515 | exit(1); |
516 | } |
517 | if (head == NULL0) { |
518 | printf("No remote programs registered.\n"); |
519 | } else { |
520 | printf(" program vers proto port\n"); |
521 | for (; head != NULL0; head = head->pml_next) { |
522 | printf("%10ld%5ld", |
523 | head->pml_map.pm_prog, |
524 | head->pml_map.pm_vers); |
525 | if (head->pml_map.pm_prot == IPPROTO_UDP17) |
526 | printf("%6s", "udp"); |
527 | else if (head->pml_map.pm_prot == IPPROTO_TCP6) |
528 | printf("%6s", "tcp"); |
529 | else |
530 | printf("%6ld", head->pml_map.pm_prot); |
531 | printf("%7ld", head->pml_map.pm_port); |
532 | rpc = getrpcbynumber(head->pml_map.pm_prog); |
533 | if (rpc) |
534 | printf(" %s\n", rpc->r_name); |
535 | else |
536 | printf("\n"); |
537 | } |
538 | } |
539 | } |
540 | |
541 | /* |
542 | * reply_proc collects replies from the broadcast. |
543 | * to get a unique list of responses the output of rpcinfo should |
544 | * be piped through sort(1) and then uniq(1). |
545 | */ |
546 | bool_tint32_t |
547 | reply_proc(caddr_t res, struct sockaddr_in *who) |
548 | { |
549 | struct hostent *hp; |
550 | |
551 | hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr, |
552 | AF_INET2); |
553 | printf("%s %s\n", inet_ntoa(who->sin_addr), |
554 | (hp == NULL0) ? "(unknown)" : hp->h_name); |
555 | return(FALSE(0)); |
556 | } |
557 | |
558 | void |
559 | brdcst(int argc, char **argv) |
560 | { |
561 | enum clnt_stat rpc_stat; |
562 | u_long prognum, vers_num; |
563 | |
564 | if (argc != 2) |
565 | usage("incorrect number of arguments"); |
566 | if (getprognum(argv[1], &prognum)) |
567 | usage("program number out of range"); |
568 | if (getul(argv[1], &vers_num)) |
569 | usage("version number out of range"); |
570 | |
571 | rpc_stat = clnt_broadcast(prognum, vers_num, NULLPROC((unsigned int)0), xdr_void, |
572 | (char *)NULL0, xdr_void, (char *)NULL0, reply_proc); |
573 | if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) { |
574 | fprintf(stderr(&__sF[2]), "rpcinfo: broadcast failed: %s\n", |
575 | clnt_sperrno(rpc_stat)); |
576 | exit(1); |
577 | } |
578 | exit(0); |
579 | } |
580 | |
581 | void |
582 | deletereg(int argc, char **argv) |
583 | { |
584 | u_long prog_num, version_num; |
585 | |
586 | if (argc != 2) |
587 | usage("incorrect number of arguments"); |
588 | if (getprognum(argv[0], &prog_num)) |
589 | usage("program number out of range"); |
590 | if (getul(argv[1], &version_num)) |
591 | usage("version number out of range"); |
592 | |
593 | if ((pmap_unset(prog_num, version_num)) == 0) { |
594 | fprintf(stderr(&__sF[2]), "rpcinfo: Could not delete " |
595 | "registration for prog %s version %s\n", |
596 | argv[0], argv[1]); |
597 | exit(1); |
598 | } |
599 | } |
600 | |
601 | void |
602 | setreg(int argc, char **argv) |
603 | { |
604 | u_long prog_num, version_num, port_num; |
605 | |
606 | if (argc != 3) |
607 | usage("incorrect number of arguments"); |
608 | if (getprognum(argv[0], &prog_num)) |
609 | usage("cannot parse program number"); |
610 | if (getul(argv[1], &version_num)) |
611 | usage("cannot parse version number"); |
612 | if (getul(argv[2], &port_num)) |
613 | usage("cannot parse port number"); |
614 | if (port_num >= 65536) |
615 | usage("port number out of range"); |
616 | |
617 | if ((pmap_set(prog_num, version_num, IPPROTO_TCP6, |
618 | (u_short)port_num)) == 0) { |
619 | fprintf(stderr(&__sF[2]), "rpcinfo: Could not set registration " |
620 | "for prog %s version %s port %s protocol IPPROTO_TCP\n", |
621 | argv[0], argv[1], argv[2]); |
622 | exit(1); |
623 | } |
624 | if ((pmap_set(prog_num, version_num, IPPROTO_UDP17, |
625 | (u_short)port_num)) == 0) { |
626 | fprintf(stderr(&__sF[2]), "rpcinfo: Could not set registration " |
627 | "for prog %s version %s port %s protocol IPPROTO_UDP\n", |
628 | argv[0], argv[1], argv[2]); |
629 | exit(1); |
630 | } |
631 | } |
632 | |
633 | void |
634 | usage(char *msg) |
635 | { |
636 | if (msg) |
637 | fprintf(stderr(&__sF[2]), |
638 | "rpcinfo: %s\n", msg); |
639 | fprintf(stderr(&__sF[2]), "usage: rpcinfo -b program version\n"); |
640 | fprintf(stderr(&__sF[2]), " rpcinfo -d program version\n"); |
641 | fprintf(stderr(&__sF[2]), " rpcinfo -p [host]\n"); |
642 | fprintf(stderr(&__sF[2]), " rpcinfo -s program version port\n"); |
643 | fprintf(stderr(&__sF[2]), |
644 | " rpcinfo [-n portnum] -t host program [version]\n"); |
645 | fprintf(stderr(&__sF[2]), |
646 | " rpcinfo [-n portnum] -u host program [version]\n"); |
647 | exit(1); |
648 | } |
649 | |
650 | int |
651 | getprognum(char *arg, u_long *ulp) |
652 | { |
653 | struct rpcent *rpc; |
654 | |
655 | if (isalpha(*arg)) { |
656 | rpc = getrpcbyname(arg); |
657 | if (rpc == NULL0) { |
658 | fprintf(stderr(&__sF[2]), "rpcinfo: %s is unknown service\n", |
659 | arg); |
660 | exit(1); |
661 | } |
662 | *ulp = rpc->r_number; |
663 | return 0; |
664 | } |
665 | return getul(arg, ulp); |
666 | } |
667 | |
668 | int |
669 | getul(char *arg, u_long *ulp) |
670 | { |
671 | u_long ul; |
672 | int save_errno = errno(*__errno()); |
673 | char *ep; |
674 | int ret = 1; |
675 | |
676 | errno(*__errno()) = 0; |
677 | ul = strtoul(arg, &ep, 10); |
678 | if (arg[0] == '\0' || *ep != '\0') |
679 | goto fail; |
680 | if (errno(*__errno()) == ERANGE34 && ul == ULONG_MAX0xffffffffffffffffUL) |
681 | goto fail; |
682 | *ulp = ul; |
683 | ret = 0; |
684 | fail: |
685 | errno(*__errno()) = save_errno; |
686 | return (ret); |
687 | } |
688 | |
689 | void |
690 | get_inet_address(struct sockaddr_in *addr, char *host) |
691 | { |
692 | struct hostent *hp; |
693 | |
694 | bzero((char *)addr, sizeof *addr); |
695 | if (inet_aton(host, &addr->sin_addr) == 0) { |
696 | if ((hp = gethostbyname(host)) == NULL0) { |
697 | fprintf(stderr(&__sF[2]), "rpcinfo: %s is unknown host\n", |
698 | host); |
699 | exit(1); |
700 | } |
701 | bcopy(hp->h_addrh_addr_list[0], (char *)&addr->sin_addr, hp->h_length); |
702 | } |
703 | addr->sin_family = AF_INET2; |
704 | } |