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