]>
git.saurik.com Git - apple/network_cmds.git/blob - rpcinfo.tproj/rpcinfo.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC */
27 static char sccsid
[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
31 * Copyright (C) 1986, Sun Microsystems, Inc.
35 * rpcinfo: ping a particular rpc program
36 * or dump the portmapper
40 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
41 * unrestricted use provided that this legend is included on all tape
42 * media and as a part of the software program in whole or part. Users
43 * may copy or modify Sun RPC without charge, but are not authorized
44 * to license or distribute it to anyone else except as part of a product or
45 * program developed by the user.
47 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
48 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
51 * Sun RPC is provided with no support and without any obligation on the
52 * part of Sun Microsystems, Inc. to assist in its use, correction,
53 * modification or enhancement.
55 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
56 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
57 * OR ANY PART THEREOF.
59 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
60 * or profits or other special, indirect and consequential damages, even if
61 * Sun has been advised of the possibility of such damages.
63 * Sun Microsystems, Inc.
65 * Mountain View, California 94043
72 #include <sys/socket.h>
74 #include <rpc/pmap_prot.h>
75 #include <rpc/pmap_clnt.h>
79 #define MAXHOSTLEN 256
81 #define MIN_VERS ((u_long) 0)
82 #define MAX_VERS ((u_long) 4294967295L)
84 static void udpping(/*u_short portflag, int argc, char **argv*/);
85 static void tcpping(/*u_short portflag, int argc, char **argv*/);
86 static int pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
87 static void pmapdump(/*int argc, char **argv*/);
88 static bool_t
reply_proc(/*void *res, struct sockaddr_in *who*/);
89 static void brdcst(/*int argc, char **argv*/);
90 static void deletereg(/* int argc, char **argv */) ;
91 static void usage(/*void*/);
92 static u_long
getprognum(/*char *arg*/);
93 static u_long
getvers(/*char *arg*/);
94 static void get_inet_address(/*struct sockaddr_in *addr, char *host*/);
95 extern u_long
inet_addr(); /* in 4.2BSD, arpa/inet.h called that a in_addr */
96 extern char *inet_ntoa();
99 * Functions to be performed.
101 #define NONE 0 /* no function */
102 #define PMAPDUMP 1 /* dump portmapper registrations */
103 #define TCPPING 2 /* ping TCP service */
104 #define UDPPING 3 /* ping UDP service */
105 #define BRDCST 4 /* ping broadcast UDP service */
106 #define DELETES 5 /* delete registration for the service */
123 while ((c
= getopt(argc
, argv
, "ptubdn:")) != EOF
) {
127 if (function
!= NONE
)
134 if (function
!= NONE
)
141 if (function
!= NONE
)
148 if (function
!= NONE
)
155 portnum
= (u_short
) atoi(optarg
); /* hope we don't get bogus # */
159 if (function
!= NONE
)
170 if (errflg
|| function
== NONE
) {
182 pmapdump(argc
- optind
, argv
+ optind
);
186 udpping(portnum
, argc
- optind
, argv
+ optind
);
190 tcpping(portnum
, argc
- optind
, argv
+ optind
);
198 brdcst(argc
- optind
, argv
+ optind
);
202 deletereg(argc
- optind
, argv
+ optind
);
210 udpping(portnum
, argc
, argv
)
216 struct sockaddr_in addr
;
217 enum clnt_stat rpc_stat
;
219 u_long prognum
, vers
, minvers
, maxvers
;
220 int sock
= RPC_ANYSOCK
;
221 struct rpc_err rpcerr
;
224 if (argc
< 2 || argc
> 3) {
228 prognum
= getprognum(argv
[1]);
229 get_inet_address(&addr
, argv
[0]);
230 /* Open the socket here so it will survive calls to clnt_destroy */
231 sock
= socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
233 perror("rpcinfo: socket");
239 * A call to version 0 should fail with a program/version
240 * mismatch, and give us the range of versions supported.
242 addr
.sin_port
= htons(portnum
);
245 if ((client
= clntudp_create(&addr
, prognum
, (u_long
)0,
246 to
, &sock
)) == NULL
) {
247 clnt_pcreateerror("rpcinfo");
248 printf("program %lu is not available\n",
254 rpc_stat
= clnt_call(client
, NULLPROC
, xdr_void
, (char *)NULL
,
255 xdr_void
, (char *)NULL
, to
);
256 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
257 clnt_geterr(client
, &rpcerr
);
258 minvers
= rpcerr
.re_vers
.low
;
259 maxvers
= rpcerr
.re_vers
.high
;
260 } else if (rpc_stat
== RPC_SUCCESS
) {
262 * Oh dear, it DOES support version 0.
263 * Let's try version MAX_VERS.
265 addr
.sin_port
= htons(portnum
);
268 if ((client
= clntudp_create(&addr
, prognum
, MAX_VERS
,
269 to
, &sock
)) == NULL
) {
270 clnt_pcreateerror("rpcinfo");
271 printf("program %lu version %lu is not available\n",
277 rpc_stat
= clnt_call(client
, NULLPROC
, xdr_void
,
278 (char *)NULL
, xdr_void
, (char *)NULL
, to
);
279 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
280 clnt_geterr(client
, &rpcerr
);
281 minvers
= rpcerr
.re_vers
.low
;
282 maxvers
= rpcerr
.re_vers
.high
;
283 } else if (rpc_stat
== RPC_SUCCESS
) {
285 * It also supports version MAX_VERS.
286 * Looks like we have a wise guy.
287 * OK, we give them information on all
288 * 4 billion versions they support...
293 (void) pstatus(client
, prognum
, MAX_VERS
);
297 (void) pstatus(client
, prognum
, (u_long
)0);
300 clnt_destroy(client
);
301 for (vers
= minvers
; vers
<= maxvers
; vers
++) {
302 addr
.sin_port
= htons(portnum
);
305 if ((client
= clntudp_create(&addr
, prognum
, vers
,
306 to
, &sock
)) == NULL
) {
307 clnt_pcreateerror("rpcinfo");
308 printf("program %lu version %lu is not available\n",
314 rpc_stat
= clnt_call(client
, NULLPROC
, xdr_void
,
315 (char *)NULL
, xdr_void
, (char *)NULL
, to
);
316 if (pstatus(client
, prognum
, vers
) < 0)
318 clnt_destroy(client
);
322 vers
= getvers(argv
[2]);
323 addr
.sin_port
= htons(portnum
);
326 if ((client
= clntudp_create(&addr
, prognum
, vers
,
327 to
, &sock
)) == NULL
) {
328 clnt_pcreateerror("rpcinfo");
329 printf("program %lu version %lu is not available\n",
335 rpc_stat
= clnt_call(client
, 0, xdr_void
, (char *)NULL
,
336 xdr_void
, (char *)NULL
, to
);
337 if (pstatus(client
, prognum
, vers
) < 0)
340 (void) close(sock
); /* Close it up again */
346 tcpping(portnum
, argc
, argv
)
352 struct sockaddr_in addr
;
353 enum clnt_stat rpc_stat
;
355 u_long prognum
, vers
, minvers
, maxvers
;
356 int sock
= RPC_ANYSOCK
;
357 struct rpc_err rpcerr
;
360 if (argc
< 2 || argc
> 3) {
364 prognum
= getprognum(argv
[1]);
365 get_inet_address(&addr
, argv
[0]);
369 * A call to version 0 should fail with a program/version
370 * mismatch, and give us the range of versions supported.
372 addr
.sin_port
= htons(portnum
);
373 if ((client
= clnttcp_create(&addr
, prognum
, MIN_VERS
,
374 &sock
, 0, 0)) == NULL
) {
375 clnt_pcreateerror("rpcinfo");
376 printf("program %lu is not available\n",
382 rpc_stat
= clnt_call(client
, NULLPROC
, xdr_void
, (char *)NULL
,
383 xdr_void
, (char *)NULL
, to
);
384 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
385 clnt_geterr(client
, &rpcerr
);
386 minvers
= rpcerr
.re_vers
.low
;
387 maxvers
= rpcerr
.re_vers
.high
;
388 } else if (rpc_stat
== RPC_SUCCESS
) {
390 * Oh dear, it DOES support version 0.
391 * Let's try version MAX_VERS.
393 addr
.sin_port
= htons(portnum
);
394 if ((client
= clnttcp_create(&addr
, prognum
, MAX_VERS
,
395 &sock
, 0, 0)) == NULL
) {
396 clnt_pcreateerror("rpcinfo");
397 printf("program %lu version %lu is not available\n",
403 rpc_stat
= clnt_call(client
, NULLPROC
, xdr_void
,
404 (char *)NULL
, xdr_void
, (char *)NULL
, to
);
405 if (rpc_stat
== RPC_PROGVERSMISMATCH
) {
406 clnt_geterr(client
, &rpcerr
);
407 minvers
= rpcerr
.re_vers
.low
;
408 maxvers
= rpcerr
.re_vers
.high
;
409 } else if (rpc_stat
== RPC_SUCCESS
) {
411 * It also supports version MAX_VERS.
412 * Looks like we have a wise guy.
413 * OK, we give them information on all
414 * 4 billion versions they support...
419 (void) pstatus(client
, prognum
, MAX_VERS
);
423 (void) pstatus(client
, prognum
, MIN_VERS
);
426 clnt_destroy(client
);
428 sock
= RPC_ANYSOCK
; /* Re-initialize it for later */
429 for (vers
= minvers
; vers
<= maxvers
; vers
++) {
430 addr
.sin_port
= htons(portnum
);
431 if ((client
= clnttcp_create(&addr
, prognum
, vers
,
432 &sock
, 0, 0)) == NULL
) {
433 clnt_pcreateerror("rpcinfo");
434 printf("program %lu version %lu is not available\n",
440 rpc_stat
= clnt_call(client
, 0, xdr_void
, (char *)NULL
,
441 xdr_void
, (char *)NULL
, to
);
442 if (pstatus(client
, prognum
, vers
) < 0)
444 clnt_destroy(client
);
450 vers
= getvers(argv
[2]);
451 addr
.sin_port
= htons(portnum
);
452 if ((client
= clnttcp_create(&addr
, prognum
, vers
, &sock
,
454 clnt_pcreateerror("rpcinfo");
455 printf("program %lu version %lu is not available\n",
461 rpc_stat
= clnt_call(client
, 0, xdr_void
, (char *)NULL
,
462 xdr_void
, (char *)NULL
, to
);
463 if (pstatus(client
, prognum
, vers
) < 0)
471 * This routine should take a pointer to an "rpc_err" structure, rather than
472 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
473 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
474 * As such, we have to keep the CLIENT structure around in order to print
475 * a good error message.
478 pstatus(client
, prognum
, vers
)
479 register CLIENT
*client
;
483 struct rpc_err rpcerr
;
485 clnt_geterr(client
, &rpcerr
);
486 if (rpcerr
.re_status
!= RPC_SUCCESS
) {
487 clnt_perror(client
, "rpcinfo");
488 printf("program %lu version %lu is not available\n",
492 printf("program %lu version %lu ready and waiting\n",
503 struct sockaddr_in server_addr
;
504 register struct hostent
*hp
;
505 struct pmaplist
*head
= NULL
;
506 int socket
= RPC_ANYSOCK
;
507 struct timeval minutetimeout
;
508 register CLIENT
*client
;
516 get_inet_address(&server_addr
, argv
[0]);
518 bzero((char *)&server_addr
, sizeof server_addr
);
519 server_addr
.sin_family
= AF_INET
;
520 if ((hp
= gethostbyname("localhost")) != NULL
)
521 bcopy(hp
->h_addr
, (caddr_t
)&server_addr
.sin_addr
,
524 server_addr
.sin_addr
.s_addr
= inet_addr("0.0.0.0");
526 minutetimeout
.tv_sec
= 60;
527 minutetimeout
.tv_usec
= 0;
528 server_addr
.sin_port
= htons(PMAPPORT
);
529 if ((client
= clnttcp_create(&server_addr
, PMAPPROG
,
530 PMAPVERS
, &socket
, 50, 500)) == NULL
) {
531 clnt_pcreateerror("rpcinfo: can't contact portmapper");
534 if (clnt_call(client
, PMAPPROC_DUMP
, xdr_void
, NULL
,
535 xdr_pmaplist
, &head
, minutetimeout
) != RPC_SUCCESS
) {
536 fprintf(stderr
, "rpcinfo: can't contact portmapper: ");
537 clnt_perror(client
, "rpcinfo");
541 printf("No remote programs registered.\n");
543 printf(" program vers proto port\n");
544 for (; head
!= NULL
; head
= head
->pml_next
) {
546 head
->pml_map
.pm_prog
,
547 head
->pml_map
.pm_vers
);
548 if (head
->pml_map
.pm_prot
== IPPROTO_UDP
)
549 printf("%6s", "udp");
550 else if (head
->pml_map
.pm_prot
== IPPROTO_TCP
)
551 printf("%6s", "tcp");
553 printf("%6ld", head
->pml_map
.pm_prot
);
554 printf("%7ld", head
->pml_map
.pm_port
);
555 rpc
= getrpcbynumber(head
->pml_map
.pm_prog
);
557 printf(" %s\n", rpc
->r_name
);
565 * reply_proc collects replies from the broadcast.
566 * to get a unique list of responses the output of rpcinfo should
567 * be piped through sort(1) and then uniq(1).
573 void *res
; /* Nothing comes back */
574 struct sockaddr_in
*who
; /* Who sent us the reply */
576 register struct hostent
*hp
;
578 hp
= gethostbyaddr((char *) &who
->sin_addr
, sizeof who
->sin_addr
,
580 printf("%s %s\n", inet_ntoa(who
->sin_addr
),
581 (hp
== NULL
) ? "(unknown)" : hp
->h_name
);
590 enum clnt_stat rpc_stat
;
591 u_long prognum
, vers
;
597 prognum
= getprognum(argv
[0]);
598 vers
= getvers(argv
[1]);
599 rpc_stat
= clnt_broadcast(prognum
, vers
, NULLPROC
, xdr_void
,
600 (char *)NULL
, xdr_void
, (char *)NULL
, reply_proc
);
601 if ((rpc_stat
!= RPC_SUCCESS
) && (rpc_stat
!= RPC_TIMEDOUT
)) {
602 fprintf(stderr
, "rpcinfo: broadcast failed: %s\n",
603 clnt_sperrno(rpc_stat
));
610 deletereg(argc
, argv
)
613 { u_long prog_num
, version_num
;
619 if (getuid()) { /* This command allowed only to root */
620 fprintf(stderr
, "Sorry. You are not root\n") ;
623 prog_num
= getprognum(argv
[0]);
624 version_num
= getvers(argv
[1]);
625 if ((pmap_unset(prog_num
, version_num
)) == 0) {
626 fprintf(stderr
, "rpcinfo: Could not delete registration for prog %s version %s\n",
635 fprintf(stderr
, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n");
636 fprintf(stderr
, " rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n");
637 fprintf(stderr
, " rpcinfo -p [ host ]\n");
638 fprintf(stderr
, " rpcinfo -b prognum versnum\n");
639 fprintf(stderr
, " rpcinfo -d prognum versnum\n") ;
646 register struct rpcent
*rpc
;
647 register u_long prognum
;
650 rpc
= getrpcbyname(arg
);
652 fprintf(stderr
, "rpcinfo: %s is unknown service\n",
656 prognum
= rpc
->r_number
;
658 prognum
= (u_long
) atoi(arg
);
668 register u_long vers
;
670 vers
= (int) atoi(arg
);
675 get_inet_address(addr
, host
)
676 struct sockaddr_in
*addr
;
679 register struct hostent
*hp
;
681 bzero((char *)addr
, sizeof *addr
);
682 addr
->sin_addr
.s_addr
= (u_long
) inet_addr(host
);
683 if (addr
->sin_addr
.s_addr
== -1 || addr
->sin_addr
.s_addr
== 0) {
684 if ((hp
= gethostbyname(host
)) == NULL
) {
685 fprintf(stderr
, "rpcinfo: %s is unknown host\n", host
);
688 bcopy(hp
->h_addr
, (char *)&addr
->sin_addr
, hp
->h_length
);
690 addr
->sin_family
= AF_INET
;