Bug Summary

File:src/usr.bin/rpcinfo/rpcinfo.c
Warning:line 424, column 4
Value stored to 'rpc_stat' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name rpcinfo.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/rpcinfo/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/rpcinfo/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/rpcinfo/rpcinfo.c
1/* $OpenBSD: rpcinfo.c,v 1.15 2019/06/28 13:35:03 deraadt 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
59void udpping(u_short portflag, int argc, char **argv);
60void tcpping(u_short portflag, int argc, char **argv);
61int pstatus(CLIENT *client, u_long prognum, u_long vers);
62void pmapdump(int argc, char **argv);
63bool_tint32_t reply_proc(caddr_t res, struct sockaddr_in *who);
64void brdcst(int argc, char **argv);
65void deletereg(int argc, char **argv);
66void setreg(int argc, char **argv);
67void usage(char *);
68int getprognum(char *arg, u_long *ulp);
69int getul(char *arg, u_long *ulp);
70void 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
83int
84main(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
194void
195udpping(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
330void
331tcpping(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))
Value stored to 'rpc_stat' is never read
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 */
460int
461pstatus(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
478void
479pmapdump(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/*ARGSUSED*/
547bool_tint32_t
548reply_proc(caddr_t res, struct sockaddr_in *who)
549{
550 struct hostent *hp;
551
552 hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
553 AF_INET2);
554 printf("%s %s\n", inet_ntoa(who->sin_addr),
555 (hp == NULL0) ? "(unknown)" : hp->h_name);
556 return(FALSE(0));
557}
558
559void
560brdcst(int argc, char **argv)
561{
562 enum clnt_stat rpc_stat;
563 u_long prognum, vers_num;
564
565 if (argc != 2)
566 usage("incorrect number of arguments");
567 if (getprognum(argv[1], &prognum))
568 usage("program number out of range");
569 if (getul(argv[1], &vers_num))
570 usage("version number out of range");
571
572 rpc_stat = clnt_broadcast(prognum, vers_num, NULLPROC((unsigned int)0), xdr_void,
573 (char *)NULL0, xdr_void, (char *)NULL0, reply_proc);
574 if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
575 fprintf(stderr(&__sF[2]), "rpcinfo: broadcast failed: %s\n",
576 clnt_sperrno(rpc_stat));
577 exit(1);
578 }
579 exit(0);
580}
581
582void
583deletereg(int argc, char **argv)
584{
585 u_long prog_num, version_num;
586
587 if (argc != 2)
588 usage("incorrect number of arguments");
589 if (getprognum(argv[0], &prog_num))
590 usage("program number out of range");
591 if (getul(argv[1], &version_num))
592 usage("version number out of range");
593
594 if ((pmap_unset(prog_num, version_num)) == 0) {
595 fprintf(stderr(&__sF[2]), "rpcinfo: Could not delete "
596 "registration for prog %s version %s\n",
597 argv[0], argv[1]);
598 exit(1);
599 }
600}
601
602void
603setreg(int argc, char **argv)
604{
605 u_long prog_num, version_num, port_num;
606
607 if (argc != 3)
608 usage("incorrect number of arguments");
609 if (getprognum(argv[0], &prog_num))
610 usage("cannot parse program number");
611 if (getul(argv[1], &version_num))
612 usage("cannot parse version number");
613 if (getul(argv[2], &port_num))
614 usage("cannot parse port number");
615 if (port_num >= 65536)
616 usage("port number out of range");
617
618 if ((pmap_set(prog_num, version_num, IPPROTO_TCP6,
619 (u_short)port_num)) == 0) {
620 fprintf(stderr(&__sF[2]), "rpcinfo: Could not set registration "
621 "for prog %s version %s port %s protocol IPPROTO_TCP\n",
622 argv[0], argv[1], argv[2]);
623 exit(1);
624 }
625 if ((pmap_set(prog_num, version_num, IPPROTO_UDP17,
626 (u_short)port_num)) == 0) {
627 fprintf(stderr(&__sF[2]), "rpcinfo: Could not set registration "
628 "for prog %s version %s port %s protocol IPPROTO_UDP\n",
629 argv[0], argv[1], argv[2]);
630 exit(1);
631 }
632}
633
634void
635usage(char *msg)
636{
637 if (msg)
638 fprintf(stderr(&__sF[2]),
639 "rpcinfo: %s\n", msg);
640 fprintf(stderr(&__sF[2]), "usage: rpcinfo -b program version\n");
641 fprintf(stderr(&__sF[2]), " rpcinfo -d program version\n");
642 fprintf(stderr(&__sF[2]), " rpcinfo -p [host]\n");
643 fprintf(stderr(&__sF[2]), " rpcinfo -s program version port\n");
644 fprintf(stderr(&__sF[2]),
645 " rpcinfo [-n portnum] -t host program [version]\n");
646 fprintf(stderr(&__sF[2]),
647 " rpcinfo [-n portnum] -u host program [version]\n");
648 exit(1);
649}
650
651int
652getprognum(char *arg, u_long *ulp)
653{
654 struct rpcent *rpc;
655
656 if (isalpha(*arg)) {
657 rpc = getrpcbyname(arg);
658 if (rpc == NULL0) {
659 fprintf(stderr(&__sF[2]), "rpcinfo: %s is unknown service\n",
660 arg);
661 exit(1);
662 }
663 *ulp = rpc->r_number;
664 return 0;
665 }
666 return getul(arg, ulp);
667}
668
669int
670getul(char *arg, u_long *ulp)
671{
672 u_long ul;
673 int save_errno = errno(*__errno());
674 char *ep;
675 int ret = 1;
676
677 errno(*__errno()) = 0;
678 ul = strtoul(arg, &ep, 10);
679 if (arg[0] == '\0' || *ep != '\0')
680 goto fail;
681 if (errno(*__errno()) == ERANGE34 && ul == ULONG_MAX(9223372036854775807L *2UL+1UL))
682 goto fail;
683 *ulp = ul;
684 ret = 0;
685fail:
686 errno(*__errno()) = save_errno;
687 return (ret);
688}
689
690void
691get_inet_address(struct sockaddr_in *addr, char *host)
692{
693 struct hostent *hp;
694
695 bzero((char *)addr, sizeof *addr);
696 if (inet_aton(host, &addr->sin_addr) == 0) {
697 if ((hp = gethostbyname(host)) == NULL0) {
698 fprintf(stderr(&__sF[2]), "rpcinfo: %s is unknown host\n",
699 host);
700 exit(1);
701 }
702 bcopy(hp->h_addrh_addr_list[0], (char *)&addr->sin_addr, hp->h_length);
703 }
704 addr->sin_family = AF_INET2;
705}