yp_ping.c revision 272850
1122394Sharti/*
2122394Sharti * Copyright (c) 1996, 1997
3122394Sharti *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4122394Sharti *
5122394Sharti * Redistribution and use in source and binary forms, with or without
6122394Sharti * modification, are permitted provided that the following conditions
7133211Sharti * are met:
8133211Sharti * 1. Redistributions of source code must retain the above copyright
9133211Sharti *    notice, this list of conditions and the following disclaimer.
10133211Sharti * 2. Redistributions in binary form must reproduce the above copyright
11133211Sharti *    notice, this list of conditions and the following disclaimer in the
12133211Sharti *    documentation and/or other materials provided with the distribution.
13122394Sharti * 3. All advertising materials mentioning features or use of this software
14122394Sharti *    must display the following acknowledgement:
15122394Sharti *	This product includes software developed by Bill Paul.
16133211Sharti * 4. Neither the name of the author nor the names of any co-contributors
17133211Sharti *    may be used to endorse or promote products derived from this software
18133211Sharti *    without specific prior written permission.
19133211Sharti *
20133211Sharti * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23133211Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
24133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28122394Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29156066Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30122394Sharti * SUCH DAMAGE.
31122394Sharti */
32122394Sharti
33122394Sharti/*-
34122394Sharti * Copyright (c) 2009, Sun Microsystems, Inc.
35122394Sharti * All rights reserved.
36122394Sharti *
37122394Sharti * Redistribution and use in source and binary forms, with or without
38122394Sharti * modification, are permitted provided that the following conditions are met:
39122394Sharti * - Redistributions of source code must retain the above copyright notice,
40122394Sharti *   this list of conditions and the following disclaimer.
41122394Sharti * - Redistributions in binary form must reproduce the above copyright notice,
42122394Sharti *   this list of conditions and the following disclaimer in the documentation
43122394Sharti *   and/or other materials provided with the distribution.
44122394Sharti * - Neither the name of Sun Microsystems, Inc. nor the names of its
45122394Sharti *   contributors may be used to endorse or promote products derived
46122394Sharti *   from this software without specific prior written permission.
47122394Sharti *
48122394Sharti * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
49122394Sharti * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50122394Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51122394Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
52122394Sharti * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53122394Sharti * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54122394Sharti * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55122394Sharti * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56122394Sharti * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57122394Sharti * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58122394Sharti * POSSIBILITY OF SUCH DAMAGE.
59122394Sharti */
60122394Sharti#if 0
61122394Sharti#ifndef lint
62122394Shartistatic char *sccsid = "@(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
63122394Shartistatic char *sccsid = "@(#)from: clnt_udp.c	2.2 88/08/01 4.0 RPCSRC";
64122394Sharti#endif
65122394Sharti#endif
66122394Sharti#include <sys/cdefs.h>
67122394Sharti__FBSDID("$FreeBSD: stable/10/usr.sbin/ypbind/yp_ping.c 272850 2014-10-09 23:05:32Z hrs $");
68122394Sharti
69122394Sharti/*
70155602Sharti * clnt_udp.c, Implements a UDP/IP based, client side RPC.
71155602Sharti *
72155602Sharti * Copyright (C) 1984, Sun Microsystems, Inc.
73155602Sharti */
74155602Sharti
75155602Sharti#include <errno.h>
76155602Sharti#include <netdb.h>
77155602Sharti#include <stdio.h>
78155602Sharti#include <stdlib.h>
79155602Sharti#include <string.h>
80155602Sharti#include <unistd.h>
81155602Sharti#include <pthread.h>
82155602Sharti#include <rpc/rpc.h>
83122394Sharti#include <rpc/pmap_clnt.h>
84122394Sharti#include <rpc/pmap_prot.h>
85122394Sharti#include <rpcsvc/yp.h>
86122394Sharti#include <sys/types.h>
87122394Sharti#include <sys/poll.h>
88122394Sharti#include <sys/socket.h>
89122394Sharti#include <sys/signal.h>
90122394Sharti#include <sys/ioctl.h>
91122394Sharti#include <arpa/inet.h>
92122394Sharti#include <net/if.h>
93122394Sharti
94122394Sharti#include "yp_ping.h"
95122394Sharti
96122394Sharti/*
97122394Sharti * pmap_getport.c
98122394Sharti * Client interface to pmap rpc service.
99122394Sharti *
100122394Sharti * Copyright (C) 1984, Sun Microsystems, Inc.
101122394Sharti */
102122394Sharti
103122394Sharti
104122394Shartistatic struct timeval timeout = { 1, 0 };
105122394Shartistatic struct timeval tottimeout = { 1, 0 };
106122394Sharti
107122394Sharti/*
108122394Sharti * Find the mapped port for program,version.
109122394Sharti * Calls the pmap service remotely to do the lookup.
110122394Sharti * Returns 0 if no map exists.
111122394Sharti */
112122394Shartistatic u_short
113122394Sharti__pmap_getport(struct sockaddr_in *address, u_long program, u_long version,
114122394Sharti    u_int protocol)
115122394Sharti{
116122394Sharti	u_short port = 0;
117122394Sharti	int sock = -1;
118122394Sharti	register CLIENT *client;
119122394Sharti	struct pmap parms;
120122394Sharti
121122394Sharti	address->sin_port = htons(PMAPPORT);
122122394Sharti
123122394Sharti	client = clntudp_bufcreate(address, PMAPPROG,
124122394Sharti	    PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
125122394Sharti	if (client != (CLIENT *)NULL) {
126122394Sharti		parms.pm_prog = program;
127122394Sharti		parms.pm_vers = version;
128122394Sharti		parms.pm_prot = protocol;
129122394Sharti		parms.pm_port = 0;  /* not needed or used */
130122394Sharti		if (CLNT_CALL(client, PMAPPROC_GETPORT,
131122394Sharti			(xdrproc_t)xdr_pmap, &parms,
132122394Sharti			(xdrproc_t)xdr_u_short, &port,
133122394Sharti			tottimeout) != RPC_SUCCESS){
134122394Sharti			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
135122394Sharti			clnt_geterr(client, &rpc_createerr.cf_error);
136122394Sharti		} else if (port == 0) {
137122394Sharti			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
138122394Sharti		}
139122394Sharti		CLNT_DESTROY(client);
140122394Sharti	}
141122394Sharti	if (sock != -1)
142122394Sharti		(void)close(sock);
143122394Sharti	address->sin_port = 0;
144122394Sharti	return (port);
145122394Sharti}
146122394Sharti
147122394Sharti/*
148122394Sharti * Transmit to YPPROC_DOMAIN_NONACK, return immediately.
149122394Sharti */
150122394Shartistatic bool_t *
151122394Shartiypproc_domain_nonack_2_send(domainname *argp, CLIENT *clnt)
152122394Sharti{
153122394Sharti	static bool_t clnt_res;
154122394Sharti	struct timeval TIMEOUT = { 0, 0 };
155122394Sharti
156122394Sharti	memset((char *)&clnt_res, 0, sizeof (clnt_res));
157122394Sharti	if (clnt_call(clnt, YPPROC_DOMAIN_NONACK,
158122394Sharti		(xdrproc_t) xdr_domainname, (caddr_t) argp,
159122394Sharti		(xdrproc_t) xdr_bool, (caddr_t) &clnt_res,
160122394Sharti		TIMEOUT) != RPC_SUCCESS) {
161122394Sharti		return (NULL);
162122394Sharti	}
163122394Sharti	return (&clnt_res);
164122394Sharti}
165122394Sharti
166122394Sharti/*
167122394Sharti * Receive response from YPPROC_DOMAIN_NONACK asynchronously.
168122394Sharti */
169122394Shartistatic bool_t *
170122394Shartiypproc_domain_nonack_2_recv(domainname *argp, CLIENT *clnt)
171122394Sharti{
172122394Sharti	static bool_t clnt_res;
173122394Sharti	struct timeval TIMEOUT = { 0, 0 };
174122394Sharti
175122394Sharti	memset((char *)&clnt_res, 0, sizeof (clnt_res));
176122394Sharti	if (clnt_call(clnt, YPPROC_DOMAIN_NONACK,
177122394Sharti		(xdrproc_t) NULL, (caddr_t) argp,
178122394Sharti		(xdrproc_t) xdr_bool, (caddr_t) &clnt_res,
179122394Sharti		TIMEOUT) != RPC_SUCCESS) {
180122394Sharti		return (NULL);
181122394Sharti	}
182122394Sharti	return (&clnt_res);
183122394Sharti}
184122394Sharti
185122394Sharti/*
186122394Sharti * "We have the machine that goes 'ping!'" -- Monty Python
187122394Sharti *
188146525Sharti * This function blasts packets at the YPPROC_DOMAIN_NONACK procedures
189122394Sharti * of the NIS servers listed in restricted_addrs structure.
190122394Sharti * Whoever replies the fastest becomes our chosen server.
191146525Sharti *
192122394Sharti * Note: THIS IS NOT A BROADCAST OPERATION! We could use clnt_broadcast()
193122394Sharti * for this, but that has the following problems:
194122394Sharti * - We only get the address of the machine that replied in the
195122394Sharti *   'eachresult' callback, and on multi-homed machines this can
196122394Sharti *   lead to confusion.
197146525Sharti * - clnt_broadcast() only transmits to local networks, whereas with
198122394Sharti *   NIS+ you can have a perfectly good server located anywhere on or
199122394Sharti *   off the local network.
200122394Sharti * - clnt_broadcast() blocks for an arbitrary amount of time which the
201122394Sharti *   caller can't control -- we want to avoid that.
202155602Sharti *
203155602Sharti * Also note that this has nothing to do with the NIS_PING procedure used
204155602Sharti * for replica updates.
205155602Sharti */
206155602Sharti
207155602Shartistruct ping_req {
208155602Sharti	struct sockaddr_in	sin;
209155602Sharti	u_int32_t		xid;
210155602Sharti};
211155602Sharti
212155602Shartiint
213155602Sharti__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port)
214200063Ssyrinx{
215200063Ssyrinx	struct timeval		tv = { 5, 0 };
216200063Ssyrinx	struct ping_req		**reqs;
217200063Ssyrinx	unsigned long		i;
218200063Ssyrinx	int			async;
219200063Ssyrinx	struct sockaddr_in	sin, *any = NULL;
220200063Ssyrinx	struct netbuf		addr;
221200063Ssyrinx	int			winner = -1;
222122394Sharti	u_int32_t		xid_seed, xid_lookup;
223122394Sharti	int			sock, dontblock = 1;
224122394Sharti	CLIENT			*clnt;
225122394Sharti	char			*foo = dom;
226122394Sharti	int			validsrvs = 0;
227122394Sharti
228122394Sharti	/* Set up handles. */
229122394Sharti	reqs = calloc(1, sizeof(struct ping_req *) * cnt);
230122394Sharti	xid_seed = time(NULL) ^ getpid();
231122394Sharti
232122394Sharti	for (i = 0; i < cnt; i++) {
233122394Sharti		bzero((char *)&sin, sizeof(sin));
234122394Sharti		sin.sin_family = AF_INET;
235122394Sharti		bcopy((char *)&restricted_addrs[i],
236122394Sharti			(char *)&sin.sin_addr, sizeof(struct in_addr));
237122394Sharti		sin.sin_port = htons(__pmap_getport(&sin, YPPROG,
238122394Sharti					YPVERS, IPPROTO_UDP));
239122394Sharti		if (sin.sin_port == 0)
240122394Sharti			continue;
241122394Sharti		reqs[i] = calloc(1, sizeof(struct ping_req));
242122394Sharti		bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin));
243122394Sharti		any = &reqs[i]->sin;
244122394Sharti		reqs[i]->xid = xid_seed;
245122394Sharti		xid_seed++;
246122394Sharti		validsrvs++;
247122394Sharti	}
248122394Sharti
249122394Sharti	/* Make sure at least one server was assigned */
250122394Sharti	if (!validsrvs) {
251122394Sharti		free(reqs);
252122394Sharti		return(-1);
253122394Sharti	}
254122394Sharti
255122394Sharti	/* Create RPC handle */
256122394Sharti	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
257122394Sharti	clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock);
258122394Sharti	if (clnt == NULL) {
259150920Sharti		close(sock);
260150920Sharti		for (i = 0; i < cnt; i++)
261150920Sharti			if (reqs[i] != NULL)
262150920Sharti				free(reqs[i]);
263150920Sharti		free(reqs);
264150920Sharti		return(-1);
265150920Sharti	}
266150920Sharti	clnt->cl_auth = authunix_create_default();
267122394Sharti	tv.tv_sec = 0;
268122394Sharti
269150920Sharti	clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv);
270150920Sharti	async = TRUE;
271150920Sharti	clnt_control(clnt, CLSET_ASYNC, (char *)&async);
272	ioctl(sock, FIONBIO, &dontblock);
273
274	/* Transmit */
275	for (i = 0; i < cnt; i++) {
276		if (reqs[i] != NULL) {
277			clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid);
278			addr.len = sizeof(reqs[i]->sin);
279			addr.buf = (char *) &reqs[i]->sin;
280			clnt_control(clnt, CLSET_SVC_ADDR, &addr);
281			ypproc_domain_nonack_2_send(&foo, clnt);
282		}
283	}
284
285	/* Receive reply */
286	ypproc_domain_nonack_2_recv(&foo, clnt);
287
288	/* Got a winner -- look him up. */
289	clnt_control(clnt, CLGET_XID, (char *)&xid_lookup);
290	for (i = 0; i < cnt; i++) {
291		if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) {
292			winner = i;
293			*port = reqs[i]->sin.sin_port;
294		}
295	}
296
297	/* Shut everything down */
298	auth_destroy(clnt->cl_auth);
299	clnt_destroy(clnt);
300	close(sock);
301
302	for (i = 0; i < cnt; i++)
303		if (reqs[i] != NULL)
304			free(reqs[i]);
305	free(reqs);
306
307	return(winner);
308}
309