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