File: | src/usr.bin/rpcinfo/rpcinfo.c |
Warning: | line 435, column 17 3rd function call argument is an uninitialized value |
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
| ||||
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
| ||||
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)) | ||||
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 | } |