126135Swpaul/*
226135Swpaul * Copyright (c) 1996, 1997
326135Swpaul *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
426135Swpaul *
526135Swpaul * Redistribution and use in source and binary forms, with or without
626135Swpaul * modification, are permitted provided that the following conditions
726135Swpaul * are met:
826135Swpaul * 1. Redistributions of source code must retain the above copyright
926135Swpaul *    notice, this list of conditions and the following disclaimer.
1026135Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1126135Swpaul *    notice, this list of conditions and the following disclaimer in the
1226135Swpaul *    documentation and/or other materials provided with the distribution.
1326135Swpaul * 3. All advertising materials mentioning features or use of this software
1426135Swpaul *    must display the following acknowledgement:
1526135Swpaul *	This product includes software developed by Bill Paul.
1626135Swpaul * 4. Neither the name of the author nor the names of any co-contributors
1726135Swpaul *    may be used to endorse or promote products derived from this software
1826135Swpaul *    without specific prior written permission.
1926135Swpaul *
2026135Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2126135Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2226135Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2326135Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2426135Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2526135Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2626135Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2726135Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2826135Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2926135Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3026135Swpaul * SUCH DAMAGE.
3126135Swpaul */
3226135Swpaul
33259417Shrs/*-
34259417Shrs * Copyright (c) 2009, Sun Microsystems, Inc.
35259417Shrs * All rights reserved.
3626135Swpaul *
37259417Shrs * Redistribution and use in source and binary forms, with or without
38259417Shrs * modification, are permitted provided that the following conditions are met:
39259417Shrs * - Redistributions of source code must retain the above copyright notice,
40259417Shrs *   this list of conditions and the following disclaimer.
41259417Shrs * - Redistributions in binary form must reproduce the above copyright notice,
42259417Shrs *   this list of conditions and the following disclaimer in the documentation
43259417Shrs *   and/or other materials provided with the distribution.
44259417Shrs * - Neither the name of Sun Microsystems, Inc. nor the names of its
45259417Shrs *   contributors may be used to endorse or promote products derived
46259417Shrs *   from this software without specific prior written permission.
47259417Shrs *
48259417Shrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
49259417Shrs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50259417Shrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51259417Shrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
52259417Shrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53259417Shrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54259417Shrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55259417Shrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56259417Shrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57259417Shrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58259417Shrs * POSSIBILITY OF SUCH DAMAGE.
5926135Swpaul */
60114601Sobrien#if 0
6126135Swpaul#ifndef lint
6230762Scharnierstatic char *sccsid = "@(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
6330762Scharnierstatic char *sccsid = "@(#)from: clnt_udp.c	2.2 88/08/01 4.0 RPCSRC";
6426135Swpaul#endif
6530762Scharnier#endif
66114601Sobrien#include <sys/cdefs.h>
67114601Sobrien__FBSDID("$FreeBSD: stable/11/usr.sbin/ypbind/yp_ping.c 315599 2017-03-20 00:54:45Z pfg $");
6826135Swpaul
6926135Swpaul/*
7026135Swpaul * clnt_udp.c, Implements a UDP/IP based, client side RPC.
7126135Swpaul *
7226135Swpaul * Copyright (C) 1984, Sun Microsystems, Inc.
7326135Swpaul */
7426135Swpaul
7530762Scharnier#include <errno.h>
7630762Scharnier#include <netdb.h>
7726135Swpaul#include <stdio.h>
7826135Swpaul#include <stdlib.h>
7930762Scharnier#include <string.h>
8026135Swpaul#include <unistd.h>
8174880Swpaul#include <pthread.h>
8226135Swpaul#include <rpc/rpc.h>
8326135Swpaul#include <rpc/pmap_clnt.h>
8426135Swpaul#include <rpc/pmap_prot.h>
8526135Swpaul#include <rpcsvc/yp.h>
8674880Swpaul#include <sys/types.h>
8774880Swpaul#include <sys/poll.h>
8830762Scharnier#include <sys/socket.h>
8974880Swpaul#include <sys/signal.h>
9030762Scharnier#include <sys/ioctl.h>
9190868Smike#include <arpa/inet.h>
9230762Scharnier#include <net/if.h>
9374880Swpaul
9426135Swpaul#include "yp_ping.h"
9526135Swpaul
9626135Swpaul/*
9726135Swpaul * pmap_getport.c
9826135Swpaul * Client interface to pmap rpc service.
9926135Swpaul *
10026135Swpaul * Copyright (C) 1984, Sun Microsystems, Inc.
10126135Swpaul */
10226135Swpaul
10326135Swpaul
10426135Swpaulstatic struct timeval timeout = { 1, 0 };
10526135Swpaulstatic struct timeval tottimeout = { 1, 0 };
10626135Swpaul
10726135Swpaul/*
10826135Swpaul * Find the mapped port for program,version.
10926135Swpaul * Calls the pmap service remotely to do the lookup.
11026135Swpaul * Returns 0 if no map exists.
11126135Swpaul */
11226135Swpaulstatic u_short
11390298Sdes__pmap_getport(struct sockaddr_in *address, u_long program, u_long version,
11490298Sdes    u_int protocol)
11526135Swpaul{
11626135Swpaul	u_short port = 0;
11726135Swpaul	int sock = -1;
11826135Swpaul	register CLIENT *client;
11926135Swpaul	struct pmap parms;
12026135Swpaul
12126135Swpaul	address->sin_port = htons(PMAPPORT);
12226135Swpaul
12326135Swpaul	client = clntudp_bufcreate(address, PMAPPROG,
12426135Swpaul	    PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
12526135Swpaul	if (client != (CLIENT *)NULL) {
12626135Swpaul		parms.pm_prog = program;
12726135Swpaul		parms.pm_vers = version;
12826135Swpaul		parms.pm_prot = protocol;
12926135Swpaul		parms.pm_port = 0;  /* not needed or used */
13095658Sdes		if (CLNT_CALL(client, PMAPPROC_GETPORT,
13195658Sdes			(xdrproc_t)xdr_pmap, &parms,
13295658Sdes			(xdrproc_t)xdr_u_short, &port,
13395658Sdes			tottimeout) != RPC_SUCCESS){
13426135Swpaul			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
13526135Swpaul			clnt_geterr(client, &rpc_createerr.cf_error);
13626135Swpaul		} else if (port == 0) {
13726135Swpaul			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
13826135Swpaul		}
13926135Swpaul		CLNT_DESTROY(client);
14026135Swpaul	}
14126135Swpaul	if (sock != -1)
14226135Swpaul		(void)close(sock);
14326135Swpaul	address->sin_port = 0;
14426135Swpaul	return (port);
14526135Swpaul}
14626135Swpaul
14726135Swpaul/*
14826135Swpaul * Transmit to YPPROC_DOMAIN_NONACK, return immediately.
14926135Swpaul */
15026135Swpaulstatic bool_t *
15126135Swpaulypproc_domain_nonack_2_send(domainname *argp, CLIENT *clnt)
15226135Swpaul{
15326135Swpaul	static bool_t clnt_res;
15426135Swpaul	struct timeval TIMEOUT = { 0, 0 };
15526135Swpaul
15626135Swpaul	memset((char *)&clnt_res, 0, sizeof (clnt_res));
15726135Swpaul	if (clnt_call(clnt, YPPROC_DOMAIN_NONACK,
15826135Swpaul		(xdrproc_t) xdr_domainname, (caddr_t) argp,
15926135Swpaul		(xdrproc_t) xdr_bool, (caddr_t) &clnt_res,
16026135Swpaul		TIMEOUT) != RPC_SUCCESS) {
16126135Swpaul		return (NULL);
16226135Swpaul	}
16326135Swpaul	return (&clnt_res);
16426135Swpaul}
16526135Swpaul
16626135Swpaul/*
16726135Swpaul * Receive response from YPPROC_DOMAIN_NONACK asynchronously.
16826135Swpaul */
16926135Swpaulstatic bool_t *
17026135Swpaulypproc_domain_nonack_2_recv(domainname *argp, CLIENT *clnt)
17126135Swpaul{
17226135Swpaul	static bool_t clnt_res;
17326135Swpaul	struct timeval TIMEOUT = { 0, 0 };
17426135Swpaul
17526135Swpaul	memset((char *)&clnt_res, 0, sizeof (clnt_res));
17626135Swpaul	if (clnt_call(clnt, YPPROC_DOMAIN_NONACK,
17726135Swpaul		(xdrproc_t) NULL, (caddr_t) argp,
17826135Swpaul		(xdrproc_t) xdr_bool, (caddr_t) &clnt_res,
17926135Swpaul		TIMEOUT) != RPC_SUCCESS) {
18026135Swpaul		return (NULL);
18126135Swpaul	}
18226135Swpaul	return (&clnt_res);
18326135Swpaul}
18426135Swpaul
18526135Swpaul/*
18626135Swpaul * "We have the machine that goes 'ping!'" -- Monty Python
18726135Swpaul *
18826135Swpaul * This function blasts packets at the YPPROC_DOMAIN_NONACK procedures
18926135Swpaul * of the NIS servers listed in restricted_addrs structure.
19026135Swpaul * Whoever replies the fastest becomes our chosen server.
19126135Swpaul *
19226135Swpaul * Note: THIS IS NOT A BROADCAST OPERATION! We could use clnt_broadcast()
19326135Swpaul * for this, but that has the following problems:
19426135Swpaul * - We only get the address of the machine that replied in the
19526135Swpaul *   'eachresult' callback, and on multi-homed machines this can
19626135Swpaul *   lead to confusion.
19726135Swpaul * - clnt_broadcast() only transmits to local networks, whereas with
19826135Swpaul *   NIS+ you can have a perfectly good server located anywhere on or
19926135Swpaul *   off the local network.
20026135Swpaul * - clnt_broadcast() blocks for an arbitrary amount of time which the
20126135Swpaul *   caller can't control -- we want to avoid that.
20226135Swpaul *
20326135Swpaul * Also note that this has nothing to do with the NIS_PING procedure used
20426135Swpaul * for replica updates.
20526135Swpaul */
20626135Swpaul
20726135Swpaulstruct ping_req {
20826135Swpaul	struct sockaddr_in	sin;
209103428Sfenner	u_int32_t		xid;
21026135Swpaul};
21126135Swpaul
21290298Sdesint
21390298Sdes__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port)
21426135Swpaul{
21590297Sdes	struct timeval		tv = { 5, 0 };
21626135Swpaul	struct ping_req		**reqs;
21726135Swpaul	unsigned long		i;
21874880Swpaul	int			async;
21932631Swpaul	struct sockaddr_in	sin, *any = NULL;
220183038Sdfr	struct netbuf		addr;
22126135Swpaul	int			winner = -1;
222103428Sfenner	u_int32_t		xid_seed, xid_lookup;
22326135Swpaul	int			sock, dontblock = 1;
22426135Swpaul	CLIENT			*clnt;
22526135Swpaul	char			*foo = dom;
22630252Swpaul	int			validsrvs = 0;
22726135Swpaul
22826135Swpaul	/* Set up handles. */
229315599Spfg	reqs = calloc(cnt, sizeof(struct ping_req *));
23026135Swpaul	xid_seed = time(NULL) ^ getpid();
23126135Swpaul
23226135Swpaul	for (i = 0; i < cnt; i++) {
23326135Swpaul		bzero((char *)&sin, sizeof(sin));
23426135Swpaul		sin.sin_family = AF_INET;
23526135Swpaul		bcopy((char *)&restricted_addrs[i],
23626135Swpaul			(char *)&sin.sin_addr, sizeof(struct in_addr));
23726135Swpaul		sin.sin_port = htons(__pmap_getport(&sin, YPPROG,
23826135Swpaul					YPVERS, IPPROTO_UDP));
23926135Swpaul		if (sin.sin_port == 0)
24026135Swpaul			continue;
24126135Swpaul		reqs[i] = calloc(1, sizeof(struct ping_req));
24226135Swpaul		bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin));
24326135Swpaul		any = &reqs[i]->sin;
24426135Swpaul		reqs[i]->xid = xid_seed;
24526135Swpaul		xid_seed++;
24630252Swpaul		validsrvs++;
24726135Swpaul	}
24826135Swpaul
24926135Swpaul	/* Make sure at least one server was assigned */
25030252Swpaul	if (!validsrvs) {
25126135Swpaul		free(reqs);
25226135Swpaul		return(-1);
25326135Swpaul	}
25426135Swpaul
25526135Swpaul	/* Create RPC handle */
25626135Swpaul	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
25726135Swpaul	clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock);
25826135Swpaul	if (clnt == NULL) {
25926135Swpaul		close(sock);
26026135Swpaul		for (i = 0; i < cnt; i++)
26126135Swpaul			if (reqs[i] != NULL)
26226135Swpaul				free(reqs[i]);
26326135Swpaul		free(reqs);
26426135Swpaul		return(-1);
26526135Swpaul	}
26626135Swpaul	clnt->cl_auth = authunix_create_default();
26726135Swpaul	tv.tv_sec = 0;
26874880Swpaul
26974462Salfred	clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv);
27074880Swpaul	async = TRUE;
27174880Swpaul	clnt_control(clnt, CLSET_ASYNC, (char *)&async);
27226135Swpaul	ioctl(sock, FIONBIO, &dontblock);
27326135Swpaul
27426135Swpaul	/* Transmit */
27526135Swpaul	for (i = 0; i < cnt; i++) {
27626135Swpaul		if (reqs[i] != NULL) {
27774880Swpaul			clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid);
278183038Sdfr			addr.len = sizeof(reqs[i]->sin);
279183038Sdfr			addr.buf = (char *) &reqs[i]->sin;
280183038Sdfr			clnt_control(clnt, CLSET_SVC_ADDR, &addr);
28126135Swpaul			ypproc_domain_nonack_2_send(&foo, clnt);
28226135Swpaul		}
28326135Swpaul	}
28426135Swpaul
28526135Swpaul	/* Receive reply */
28626135Swpaul	ypproc_domain_nonack_2_recv(&foo, clnt);
28726135Swpaul
28826135Swpaul	/* Got a winner -- look him up. */
28974880Swpaul	clnt_control(clnt, CLGET_XID, (char *)&xid_lookup);
29026135Swpaul	for (i = 0; i < cnt; i++) {
29126135Swpaul		if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) {
29226135Swpaul			winner = i;
29326135Swpaul			*port = reqs[i]->sin.sin_port;
29426135Swpaul		}
29526135Swpaul	}
29626135Swpaul
29726135Swpaul	/* Shut everything down */
29826135Swpaul	auth_destroy(clnt->cl_auth);
29926135Swpaul	clnt_destroy(clnt);
30026135Swpaul	close(sock);
30126135Swpaul
30226135Swpaul	for (i = 0; i < cnt; i++)
30326135Swpaul		if (reqs[i] != NULL)
30426135Swpaul			free(reqs[i]);
30526135Swpaul	free(reqs);
30626135Swpaul
30726135Swpaul	return(winner);
30826135Swpaul}
309