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