2 * Copyright (c) 1996, 1997
3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * @(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro
33 * @(#)from: clnt_udp.c 2.2 88/08/01 4.0 RPCSRC
34 * $FreeBSD: src/usr.sbin/ypbind/yp_ping.c,v 1.17 2008/09/15 14:01:40 dfr Exp $
35 * $DragonFly: src/usr.sbin/ypbind/yp_ping.c,v 1.7 2005/11/24 22:23:02 swildner Exp $
39 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
40 * unrestricted use provided that this legend is included on all tape
41 * media and as a part of the software program in whole or part. Users
42 * may copy or modify Sun RPC without charge, but are not authorized
43 * to license or distribute it to anyone else except as part of a product or
44 * program developed by the user.
46 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
47 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
48 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
50 * Sun RPC is provided with no support and without any obligation on the
51 * part of Sun Microsystems, Inc. to assist in its use, correction,
52 * modification or enhancement.
54 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
55 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
56 * OR ANY PART THEREOF.
58 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
59 * or profits or other special, indirect and consequential damages, even if
60 * Sun has been advised of the possibility of such damages.
62 * Sun Microsystems, Inc.
64 * Mountain View, California 94043
68 * clnt_udp.c, Implements a UDP/IP based, client side RPC.
70 * Copyright (C) 1984, Sun Microsystems, Inc.
81 #include <rpc/pmap_clnt.h>
82 #include <rpc/pmap_prot.h>
83 #include <rpcsvc/yp.h>
84 #include <sys/types.h>
86 #include <sys/socket.h>
87 #include <sys/signal.h>
88 #include <sys/ioctl.h>
89 #include <arpa/inet.h>
96 * Client interface to pmap rpc service.
98 * Copyright (C) 1984, Sun Microsystems, Inc.
102 static struct timeval timeout
= { 1, 0 };
103 static struct timeval tottimeout
= { 1, 0 };
106 * Find the mapped port for program,version.
107 * Calls the pmap service remotely to do the lookup.
108 * Returns 0 if no map exists.
111 __pmap_getport(struct sockaddr_in
*address
, u_long program
, u_long version
,
119 address
->sin_port
= htons(PMAPPORT
);
121 client
= clntudp_bufcreate(address
, PMAPPROG
,
122 PMAPVERS
, timeout
, &sock
, RPCSMALLMSGSIZE
, RPCSMALLMSGSIZE
);
123 if (client
!= NULL
) {
124 parms
.pm_prog
= program
;
125 parms
.pm_vers
= version
;
126 parms
.pm_prot
= protocol
;
127 parms
.pm_port
= 0; /* not needed or used */
128 if (CLNT_CALL(client
, PMAPPROC_GETPORT
,
129 (xdrproc_t
)xdr_pmap
, &parms
,
130 (xdrproc_t
)xdr_u_short
, &port
,
131 tottimeout
) != RPC_SUCCESS
){
132 rpc_createerr
.cf_stat
= RPC_PMAPFAILURE
;
133 clnt_geterr(client
, &rpc_createerr
.cf_error
);
134 } else if (port
== 0) {
135 rpc_createerr
.cf_stat
= RPC_PROGNOTREGISTERED
;
137 CLNT_DESTROY(client
);
141 address
->sin_port
= 0;
146 * Transmit to YPPROC_DOMAIN_NONACK, return immediately.
149 ypproc_domain_nonack_2_send(domainname
*argp
, CLIENT
*clnt
)
151 static bool_t clnt_res
;
152 struct timeval TIMEOUT
= { 0, 0 };
154 memset((char *)&clnt_res
, 0, sizeof (clnt_res
));
155 if (clnt_call(clnt
, YPPROC_DOMAIN_NONACK
,
156 (xdrproc_t
) xdr_domainname
, (caddr_t
) argp
,
157 (xdrproc_t
) xdr_bool
, (caddr_t
) &clnt_res
,
158 TIMEOUT
) != RPC_SUCCESS
) {
165 * Receive response from YPPROC_DOMAIN_NONACK asynchronously.
168 ypproc_domain_nonack_2_recv(domainname
*argp
, CLIENT
*clnt
)
170 static bool_t clnt_res
;
171 struct timeval TIMEOUT
= { 0, 0 };
173 memset((char *)&clnt_res
, 0, sizeof (clnt_res
));
174 if (clnt_call(clnt
, YPPROC_DOMAIN_NONACK
,
175 (xdrproc_t
) NULL
, (caddr_t
) argp
,
176 (xdrproc_t
) xdr_bool
, (caddr_t
) &clnt_res
,
177 TIMEOUT
) != RPC_SUCCESS
) {
184 * "We have the machine that goes 'ping!'" -- Monty Python
186 * This function blasts packets at the YPPROC_DOMAIN_NONACK procedures
187 * of the NIS servers listed in restricted_addrs structure.
188 * Whoever replies the fastest becomes our chosen server.
190 * Note: THIS IS NOT A BROADCAST OPERATION! We could use clnt_broadcast()
191 * for this, but that has the following problems:
192 * - We only get the address of the machine that replied in the
193 * 'eachresult' callback, and on multi-homed machines this can
195 * - clnt_broadcast() only transmits to local networks, whereas with
196 * NIS+ you can have a perfectly good server located anywhere on or
197 * off the local network.
198 * - clnt_broadcast() blocks for an arbitrary amount of time which the
199 * caller can't control -- we want to avoid that.
201 * Also note that this has nothing to do with the NIS_PING procedure used
202 * for replica updates.
206 struct sockaddr_in sin
;
211 __yp_ping(struct in_addr
*restricted_addrs
, int cnt
, char *dom
, short *port
)
213 struct timeval tv
= { 5, 0 };
214 struct ping_req
**reqs
;
217 struct sockaddr_in sin
, *any
= NULL
;
220 u_int32_t xid_seed
, xid_lookup
;
221 int sock
, dontblock
= 1;
226 /* Set up handles. */
227 reqs
= calloc(1, sizeof(struct ping_req
*) * cnt
);
228 xid_seed
= time(NULL
) ^ getpid();
230 for (i
= 0; i
< cnt
; i
++) {
231 bzero((char *)&sin
, sizeof(sin
));
232 sin
.sin_family
= AF_INET
;
233 bcopy((char *)&restricted_addrs
[i
],
234 (char *)&sin
.sin_addr
, sizeof(struct in_addr
));
235 sin
.sin_port
= htons(__pmap_getport(&sin
, YPPROG
,
236 YPVERS
, IPPROTO_UDP
));
237 if (sin
.sin_port
== 0)
239 reqs
[i
] = calloc(1, sizeof(struct ping_req
));
240 bcopy((char *)&sin
, (char *)&reqs
[i
]->sin
, sizeof(sin
));
242 reqs
[i
]->xid
= xid_seed
;
247 /* Make sure at least one server was assigned */
253 /* Create RPC handle */
254 sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
255 clnt
= clntudp_create(any
, YPPROG
, YPVERS
, tv
, &sock
);
258 for (i
= 0; i
< cnt
; i
++)
264 clnt
->cl_auth
= authunix_create_default();
267 clnt_control(clnt
, CLSET_TIMEOUT
, (char *)&tv
);
269 clnt_control(clnt
, CLSET_ASYNC
, (char *)&async
);
270 ioctl(sock
, FIONBIO
, &dontblock
);
273 for (i
= 0; i
< cnt
; i
++) {
274 if (reqs
[i
] != NULL
) {
275 clnt_control(clnt
, CLSET_XID
, (char *)&reqs
[i
]->xid
);
276 addr
.len
= sizeof(reqs
[i
]->sin
);
277 addr
.buf
= (char *) &reqs
[i
]->sin
;
278 clnt_control(clnt
, CLSET_SVC_ADDR
, &addr
);
279 ypproc_domain_nonack_2_send(&foo
, clnt
);
284 ypproc_domain_nonack_2_recv(&foo
, clnt
);
286 /* Got a winner -- look him up. */
287 clnt_control(clnt
, CLGET_XID
, (char *)&xid_lookup
);
288 for (i
= 0; i
< cnt
; i
++) {
289 if (reqs
[i
] != NULL
&& reqs
[i
]->xid
== xid_lookup
) {
291 *port
= reqs
[i
]->sin
.sin_port
;
295 /* Shut everything down */
296 auth_destroy(clnt
->cl_auth
);
300 for (i
= 0; i
< cnt
; i
++)