Annotation of src/usr.bin/rpcinfo/rpcinfo.c, Revision 1.14
1.14 ! millert 1: /* $OpenBSD: rpcinfo.c,v 1.13 2009/10/27 23:59:42 deraadt Exp $ */
1.1 deraadt 2:
3: /*
1.14 ! millert 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.
1.1 deraadt 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>
1.7 pvalchev 46: #include <string.h>
47: #include <stdlib.h>
48: #include <unistd.h>
1.1 deraadt 49: #include <ctype.h>
1.5 deraadt 50: #include <errno.h>
1.11 millert 51: #include <limits.h>
1.1 deraadt 52: #include <arpa/inet.h>
53:
54: #define MAXHOSTLEN 256
55:
56: #define MIN_VERS ((u_long) 0)
57: #define MAX_VERS ((u_long) 4294967295UL)
58:
1.5 deraadt 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);
1.6 millert 63: bool_t reply_proc(caddr_t res, struct sockaddr_in *who);
1.5 deraadt 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);
1.1 deraadt 71:
72: /*
73: * Functions to be performed.
74: */
75: #define NONE 0 /* no function */
76: #define PMAPDUMP 1 /* dump portmapper registrations */
77: #define TCPPING 2 /* ping TCP service */
78: #define UDPPING 3 /* ping UDP service */
79: #define BRDCST 4 /* ping broadcast UDP service */
80: #define DELETES 5 /* delete registration for the service */
1.5 deraadt 81: #define SETS 6 /* set registration for the service */
1.1 deraadt 82:
83: int
1.9 deraadt 84: main(int argc, char *argv[])
1.1 deraadt 85: {
1.8 mpech 86: int c;
1.1 deraadt 87: extern char *optarg;
88: extern int optind;
89: int errflg;
90: int function;
91: u_short portnum;
1.5 deraadt 92: u_long tmp;
1.1 deraadt 93:
94: function = NONE;
95: portnum = 0;
96: errflg = 0;
1.5 deraadt 97: while ((c = getopt(argc, argv, "ptubdsn:")) != -1) {
1.1 deraadt 98: switch (c) {
99:
100: case 'p':
101: if (function != NONE)
102: errflg = 1;
103: else
104: function = PMAPDUMP;
105: break;
106:
107: case 't':
108: if (function != NONE)
109: errflg = 1;
110: else
111: function = TCPPING;
112: break;
113:
114: case 'u':
115: if (function != NONE)
116: errflg = 1;
117: else
118: function = UDPPING;
119: break;
120:
121: case 'b':
122: if (function != NONE)
123: errflg = 1;
124: else
125: function = BRDCST;
126: break;
127:
128: case 'n':
1.5 deraadt 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;
1.1 deraadt 134: break;
135:
136: case 'd':
137: if (function != NONE)
138: errflg = 1;
139: else
140: function = DELETES;
141: break;
142:
1.5 deraadt 143: case 's':
144: if (function != NONE)
145: errflg = 1;
146: else
147: function = SETS;
148: break;
149:
150:
1.1 deraadt 151: case '?':
152: errflg = 1;
153: }
154: }
155:
1.5 deraadt 156: if (errflg || function == NONE)
157: usage(NULL);
1.1 deraadt 158:
159: switch (function) {
160:
161: case PMAPDUMP:
1.5 deraadt 162: if (portnum != 0)
163: usage(NULL);
1.1 deraadt 164: pmapdump(argc - optind, argv + optind);
165: break;
166:
167: case UDPPING:
168: udpping(portnum, argc - optind, argv + optind);
169: break;
170:
171: case TCPPING:
172: tcpping(portnum, argc - optind, argv + optind);
173: break;
174:
175: case BRDCST:
1.5 deraadt 176: if (portnum != 0)
177: usage(NULL);
178:
1.1 deraadt 179: brdcst(argc - optind, argv + optind);
180: break;
181:
182: case DELETES:
183: deletereg(argc - optind, argv + optind);
184: break;
1.5 deraadt 185:
186: case SETS:
187: setreg(argc - optind, argv + optind);
188: break;
1.1 deraadt 189: }
190:
191: return (0);
192: }
193:
1.5 deraadt 194: void
1.9 deraadt 195: udpping(u_short portnum, int argc, char **argv)
1.1 deraadt 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;
203: struct rpc_err rpcerr;
204: int failure;
205:
1.5 deraadt 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:
1.1 deraadt 213: get_inet_address(&addr, argv[0]);
214: /* Open the socket here so it will survive calls to clnt_destroy */
1.3 deraadt 215: sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1.1 deraadt 216: if (sock < 0) {
217: perror("rpcinfo: socket");
218: exit(1);
219: }
1.3 deraadt 220: if (getuid() == 0)
221: bindresvport(sock, NULL);
1.1 deraadt 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);
229: to.tv_sec = 5;
230: to.tv_usec = 0;
231: if ((client = clntudp_create(&addr, prognum, (u_long)0,
232: to, &sock)) == NULL) {
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,
241: xdr_void, (char *)NULL, to);
242: if (rpc_stat == RPC_PROGVERSMISMATCH) {
243: clnt_geterr(client, &rpcerr);
244: minvers = rpcerr.re_vers.low;
245: maxvers = rpcerr.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);
252: to.tv_sec = 5;
253: to.tv_usec = 0;
254: if ((client = clntudp_create(&addr, prognum, MAX_VERS,
255: to, &sock)) == NULL) {
256: clnt_pcreateerror("rpcinfo");
257: printf("program %lu version %lu is not available\n",
258: prognum, MAX_VERS);
259: exit(1);
260: }
261: to.tv_sec = 10;
262: to.tv_usec = 0;
263: rpc_stat = clnt_call(client, NULLPROC, xdr_void,
264: (char *)NULL, xdr_void, (char *)NULL, to);
265: if (rpc_stat == RPC_PROGVERSMISMATCH) {
266: clnt_geterr(client, &rpcerr);
267: minvers = rpcerr.re_vers.low;
268: maxvers = rpcerr.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;
278: } else {
279: (void) pstatus(client, prognum, MAX_VERS);
280: exit(1);
281: }
282: } else {
283: (void) pstatus(client, prognum, (u_long)0);
284: exit(1);
285: }
286: clnt_destroy(client);
287: for (vers = minvers; vers <= maxvers; vers++) {
288: addr.sin_port = htons(portnum);
289: to.tv_sec = 5;
290: to.tv_usec = 0;
291: if ((client = clntudp_create(&addr, prognum, vers,
292: to, &sock)) == NULL) {
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,
301: (char *)NULL, xdr_void, (char *)NULL, to);
302: if (pstatus(client, prognum, vers) < 0)
303: failure = 1;
304: clnt_destroy(client);
305: }
1.5 deraadt 306: } else {
307: getul(argv[2], &vers); /* XXX */
1.1 deraadt 308: addr.sin_port = htons(portnum);
309: to.tv_sec = 5;
310: to.tv_usec = 0;
311: if ((client = clntudp_create(&addr, prognum, vers,
312: to, &sock)) == NULL) {
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,
321: xdr_void, (char *)NULL, 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:
1.5 deraadt 330: void
1.9 deraadt 331: tcpping(u_short portnum, int argc, char **argv)
1.1 deraadt 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;
339: struct rpc_err rpcerr;
340: int failure;
341:
1.5 deraadt 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:
1.1 deraadt 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);
357: if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
358: &sock, 0, 0)) == NULL) {
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,
367: xdr_void, (char *)NULL, to);
368: if (rpc_stat == RPC_PROGVERSMISMATCH) {
369: clnt_geterr(client, &rpcerr);
370: minvers = rpcerr.re_vers.low;
371: maxvers = rpcerr.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);
378: if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
379: &sock, 0, 0)) == NULL) {
380: clnt_pcreateerror("rpcinfo");
381: printf("program %lu version %lu is not available\n",
382: prognum, MAX_VERS);
383: exit(1);
384: }
385: to.tv_sec = 10;
386: to.tv_usec = 0;
387: rpc_stat = clnt_call(client, NULLPROC, xdr_void,
388: (char *)NULL, xdr_void, (char *)NULL, to);
389: if (rpc_stat == RPC_PROGVERSMISMATCH) {
390: clnt_geterr(client, &rpcerr);
391: minvers = rpcerr.re_vers.low;
392: maxvers = rpcerr.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;
402: } else {
403: (void) pstatus(client, prognum, MAX_VERS);
404: exit(1);
405: }
406: } else {
407: (void) pstatus(client, prognum, MIN_VERS);
408: exit(1);
409: }
410: clnt_destroy(client);
411: (void) close(sock);
412: sock = RPC_ANYSOCK; /* Re-initialize it for later */
413: for (vers = minvers; vers <= maxvers; vers++) {
414: addr.sin_port = htons(portnum);
415: if ((client = clnttcp_create(&addr, prognum, vers,
416: &sock, 0, 0)) == NULL) {
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,
425: xdr_void, (char *)NULL, to);
426: if (pstatus(client, prognum, vers) < 0)
427: failure = 1;
428: clnt_destroy(client);
429: (void) close(sock);
430: sock = RPC_ANYSOCK;
431: }
1.5 deraadt 432: } else {
433: getul(argv[2], &vers); /* XXX */
1.1 deraadt 434: addr.sin_port = htons(portnum);
435: if ((client = clnttcp_create(&addr, prognum, vers, &sock,
436: 0, 0)) == NULL) {
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,
445: xdr_void, (char *)NULL, 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: */
1.5 deraadt 460: int
1.9 deraadt 461: pstatus(CLIENT *client, u_long prognum, u_long vers)
1.1 deraadt 462: {
463: struct rpc_err rpcerr;
464:
465: clnt_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:
1.5 deraadt 478: void
1.9 deraadt 479: pmapdump(int argc, char **argv)
1.1 deraadt 480: {
481: struct sockaddr_in server_addr;
1.8 mpech 482: struct hostent *hp;
1.1 deraadt 483: struct pmaplist *head = NULL;
484: int socket = RPC_ANYSOCK;
485: struct timeval minutetimeout;
1.8 mpech 486: CLIENT *client;
1.1 deraadt 487: struct rpcent *rpc;
488:
1.5 deraadt 489: if (argc > 1)
490: usage("too many arguments");
491:
1.1 deraadt 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_INET;
497: if ((hp = gethostbyname("localhost")) != NULL)
498: bcopy(hp->h_addr, (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);
506: if ((client = clnttcp_create(&server_addr, PMAPPROG,
507: PMAPVERS, &socket, 50, 500)) == NULL) {
508: clnt_pcreateerror("rpcinfo: can't contact portmapper");
509: exit(1);
510: }
511: if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
512: xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
513: fprintf(stderr, "rpcinfo: can't contact portmapper: ");
514: clnt_perror(client, "rpcinfo");
515: exit(1);
516: }
517: if (head == NULL) {
518: printf("No remote programs registered.\n");
519: } else {
520: printf(" program vers proto port\n");
521: for (; head != NULL; 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_UDP)
526: printf("%6s", "udp");
527: else if (head->pml_map.pm_prot == IPPROTO_TCP)
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*/
1.5 deraadt 547: bool_t
1.9 deraadt 548: reply_proc(caddr_t res, struct sockaddr_in *who)
1.1 deraadt 549: {
1.8 mpech 550: struct hostent *hp;
1.1 deraadt 551:
552: hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
553: AF_INET);
554: printf("%s %s\n", inet_ntoa(who->sin_addr),
555: (hp == NULL) ? "(unknown)" : hp->h_name);
556: return(FALSE);
557: }
558:
1.5 deraadt 559: void
1.9 deraadt 560: brdcst(int argc, char **argv)
1.1 deraadt 561: {
562: enum clnt_stat rpc_stat;
1.5 deraadt 563: u_long prognum, vers_num;
1.1 deraadt 564:
1.5 deraadt 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, xdr_void,
1.6 millert 573: (char *)NULL, xdr_void, (char *)NULL, reply_proc);
1.1 deraadt 574: if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
575: fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
576: clnt_sperrno(rpc_stat));
577: exit(1);
578: }
579: exit(0);
580: }
581:
1.5 deraadt 582: void
1.9 deraadt 583: deletereg(int argc, char **argv)
1.5 deraadt 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");
1.1 deraadt 593:
1.5 deraadt 594: if ((pmap_unset(prog_num, version_num)) == 0) {
595: fprintf(stderr, "rpcinfo: Could not delete "
596: "registration for prog %s version %s\n",
597: argv[0], argv[1]);
598: exit(1);
1.1 deraadt 599: }
1.5 deraadt 600: }
601:
602: void
1.9 deraadt 603: setreg(int argc, char **argv)
1.5 deraadt 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:
1.10 deraadt 618: if ((pmap_set(prog_num, version_num, IPPROTO_TCP,
1.5 deraadt 619: (u_short)port_num)) == 0) {
620: fprintf(stderr, "rpcinfo: Could not set registration "
1.10 deraadt 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_UDP,
626: (u_short)port_num)) == 0) {
627: fprintf(stderr, "rpcinfo: Could not set registration "
628: "for prog %s version %s port %s protocol IPPROTO_UDP\n",
1.5 deraadt 629: argv[0], argv[1], argv[2]);
630: exit(1);
1.1 deraadt 631: }
632: }
633:
1.5 deraadt 634: void
635: usage(char *msg)
1.1 deraadt 636: {
1.5 deraadt 637: if (msg)
638: fprintf(stderr,
639: "rpcinfo: %s\n", msg);
1.12 jmc 640: fprintf(stderr, "usage: rpcinfo -b program version\n");
641: fprintf(stderr, " rpcinfo -d program version\n");
642: fprintf(stderr, " rpcinfo -p [host]\n");
643: fprintf(stderr, " rpcinfo -s program version port\n");
1.5 deraadt 644: fprintf(stderr,
1.12 jmc 645: " rpcinfo [-n portnum] -t host program [version]\n");
1.5 deraadt 646: fprintf(stderr,
1.12 jmc 647: " rpcinfo [-n portnum] -u host program [version]\n");
1.5 deraadt 648: exit(1);
1.1 deraadt 649: }
650:
1.5 deraadt 651: int
1.9 deraadt 652: getprognum(char *arg, u_long *ulp)
1.1 deraadt 653: {
1.8 mpech 654: struct rpcent *rpc;
1.1 deraadt 655:
656: if (isalpha(*arg)) {
657: rpc = getrpcbyname(arg);
658: if (rpc == NULL) {
659: fprintf(stderr, "rpcinfo: %s is unknown service\n",
660: arg);
661: exit(1);
662: }
1.5 deraadt 663: *ulp = rpc->r_number;
664: return 0;
1.1 deraadt 665: }
1.5 deraadt 666: return getul(arg, ulp);
1.1 deraadt 667: }
668:
1.5 deraadt 669: int
1.9 deraadt 670: getul(char *arg, u_long *ulp)
1.1 deraadt 671: {
1.5 deraadt 672: u_long ul;
673: int save_errno = errno;
674: char *ep;
675: int ret = 1;
676:
677: errno = 0;
678: ul = strtoul(arg, &ep, 10);
679: if (arg[0] == '\0' || *ep != '\0')
680: goto fail;
681: if (errno == ERANGE && ul == ULONG_MAX)
682: goto fail;
683: *ulp = ul;
684: ret = 0;
685: fail:
686: errno = save_errno;
687: return (ret);
1.1 deraadt 688: }
689:
1.5 deraadt 690: void
1.9 deraadt 691: get_inet_address(struct sockaddr_in *addr, char *host)
1.1 deraadt 692: {
1.8 mpech 693: struct hostent *hp;
1.1 deraadt 694:
695: bzero((char *)addr, sizeof *addr);
696: if (inet_aton(host, &addr->sin_addr) == 0) {
697: if ((hp = gethostbyname(host)) == NULL) {
1.5 deraadt 698: fprintf(stderr, "rpcinfo: %s is unknown host\n",
699: host);
1.1 deraadt 700: exit(1);
701: }
702: bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length);
703: }
704: addr->sin_family = AF_INET;
705: }