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 3326135Swpaul/* 3426135Swpaul * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3526135Swpaul * unrestricted use provided that this legend is included on all tape 3626135Swpaul * media and as a part of the software program in whole or part. Users 3726135Swpaul * may copy or modify Sun RPC without charge, but are not authorized 3826135Swpaul * to license or distribute it to anyone else except as part of a product or 3926135Swpaul * program developed by the user. 4026135Swpaul * 4126135Swpaul * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 4226135Swpaul * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 4326135Swpaul * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 4426135Swpaul * 4526135Swpaul * Sun RPC is provided with no support and without any obligation on the 4626135Swpaul * part of Sun Microsystems, Inc. to assist in its use, correction, 4726135Swpaul * modification or enhancement. 4826135Swpaul * 4926135Swpaul * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 5026135Swpaul * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 5126135Swpaul * OR ANY PART THEREOF. 5226135Swpaul * 5326135Swpaul * In no event will Sun Microsystems, Inc. be liable for any lost revenue 5426135Swpaul * or profits or other special, indirect and consequential damages, even if 5526135Swpaul * Sun has been advised of the possibility of such damages. 5626135Swpaul * 5726135Swpaul * Sun Microsystems, Inc. 5826135Swpaul * 2550 Garcia Avenue 5926135Swpaul * Mountain View, California 94043 6026135Swpaul */ 6126135Swpaul 62114601Sobrien#if 0 6326135Swpaul#ifndef lint 6430762Scharnierstatic char *sccsid = "@(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro"; 6530762Scharnierstatic char *sccsid = "@(#)from: clnt_udp.c 2.2 88/08/01 4.0 RPCSRC"; 6626135Swpaul#endif 6730762Scharnier#endif 68114601Sobrien#include <sys/cdefs.h> 69114601Sobrien__FBSDID("$FreeBSD$"); 7026135Swpaul 7126135Swpaul/* 7226135Swpaul * clnt_udp.c, Implements a UDP/IP based, client side RPC. 7326135Swpaul * 7426135Swpaul * Copyright (C) 1984, Sun Microsystems, Inc. 7526135Swpaul */ 7626135Swpaul 7730762Scharnier#include <errno.h> 7830762Scharnier#include <netdb.h> 7926135Swpaul#include <stdio.h> 8026135Swpaul#include <stdlib.h> 8130762Scharnier#include <string.h> 8226135Swpaul#include <unistd.h> 8374880Swpaul#include <pthread.h> 8426135Swpaul#include <rpc/rpc.h> 8526135Swpaul#include <rpc/pmap_clnt.h> 8626135Swpaul#include <rpc/pmap_prot.h> 8726135Swpaul#include <rpcsvc/yp.h> 8874880Swpaul#include <sys/types.h> 8974880Swpaul#include <sys/poll.h> 9030762Scharnier#include <sys/socket.h> 9174880Swpaul#include <sys/signal.h> 9230762Scharnier#include <sys/ioctl.h> 9390868Smike#include <arpa/inet.h> 9430762Scharnier#include <net/if.h> 9574880Swpaul 9626135Swpaul#include "yp_ping.h" 9726135Swpaul 9826135Swpaul/* 9926135Swpaul * pmap_getport.c 10026135Swpaul * Client interface to pmap rpc service. 10126135Swpaul * 10226135Swpaul * Copyright (C) 1984, Sun Microsystems, Inc. 10326135Swpaul */ 10426135Swpaul 10526135Swpaul 10626135Swpaulstatic struct timeval timeout = { 1, 0 }; 10726135Swpaulstatic struct timeval tottimeout = { 1, 0 }; 10826135Swpaul 10926135Swpaul/* 11026135Swpaul * Find the mapped port for program,version. 11126135Swpaul * Calls the pmap service remotely to do the lookup. 11226135Swpaul * Returns 0 if no map exists. 11326135Swpaul */ 11426135Swpaulstatic u_short 11590298Sdes__pmap_getport(struct sockaddr_in *address, u_long program, u_long version, 11690298Sdes u_int protocol) 11726135Swpaul{ 11826135Swpaul u_short port = 0; 11926135Swpaul int sock = -1; 12026135Swpaul register CLIENT *client; 12126135Swpaul struct pmap parms; 12226135Swpaul 12326135Swpaul address->sin_port = htons(PMAPPORT); 12426135Swpaul 12526135Swpaul client = clntudp_bufcreate(address, PMAPPROG, 12626135Swpaul PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); 12726135Swpaul if (client != (CLIENT *)NULL) { 12826135Swpaul parms.pm_prog = program; 12926135Swpaul parms.pm_vers = version; 13026135Swpaul parms.pm_prot = protocol; 13126135Swpaul parms.pm_port = 0; /* not needed or used */ 13295658Sdes if (CLNT_CALL(client, PMAPPROC_GETPORT, 13395658Sdes (xdrproc_t)xdr_pmap, &parms, 13495658Sdes (xdrproc_t)xdr_u_short, &port, 13595658Sdes tottimeout) != RPC_SUCCESS){ 13626135Swpaul rpc_createerr.cf_stat = RPC_PMAPFAILURE; 13726135Swpaul clnt_geterr(client, &rpc_createerr.cf_error); 13826135Swpaul } else if (port == 0) { 13926135Swpaul rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 14026135Swpaul } 14126135Swpaul CLNT_DESTROY(client); 14226135Swpaul } 14326135Swpaul if (sock != -1) 14426135Swpaul (void)close(sock); 14526135Swpaul address->sin_port = 0; 14626135Swpaul return (port); 14726135Swpaul} 14826135Swpaul 14926135Swpaul/* 15026135Swpaul * Transmit to YPPROC_DOMAIN_NONACK, return immediately. 15126135Swpaul */ 15226135Swpaulstatic bool_t * 15326135Swpaulypproc_domain_nonack_2_send(domainname *argp, CLIENT *clnt) 15426135Swpaul{ 15526135Swpaul static bool_t clnt_res; 15626135Swpaul struct timeval TIMEOUT = { 0, 0 }; 15726135Swpaul 15826135Swpaul memset((char *)&clnt_res, 0, sizeof (clnt_res)); 15926135Swpaul if (clnt_call(clnt, YPPROC_DOMAIN_NONACK, 16026135Swpaul (xdrproc_t) xdr_domainname, (caddr_t) argp, 16126135Swpaul (xdrproc_t) xdr_bool, (caddr_t) &clnt_res, 16226135Swpaul TIMEOUT) != RPC_SUCCESS) { 16326135Swpaul return (NULL); 16426135Swpaul } 16526135Swpaul return (&clnt_res); 16626135Swpaul} 16726135Swpaul 16826135Swpaul/* 16926135Swpaul * Receive response from YPPROC_DOMAIN_NONACK asynchronously. 17026135Swpaul */ 17126135Swpaulstatic bool_t * 17226135Swpaulypproc_domain_nonack_2_recv(domainname *argp, CLIENT *clnt) 17326135Swpaul{ 17426135Swpaul static bool_t clnt_res; 17526135Swpaul struct timeval TIMEOUT = { 0, 0 }; 17626135Swpaul 17726135Swpaul memset((char *)&clnt_res, 0, sizeof (clnt_res)); 17826135Swpaul if (clnt_call(clnt, YPPROC_DOMAIN_NONACK, 17926135Swpaul (xdrproc_t) NULL, (caddr_t) argp, 18026135Swpaul (xdrproc_t) xdr_bool, (caddr_t) &clnt_res, 18126135Swpaul TIMEOUT) != RPC_SUCCESS) { 18226135Swpaul return (NULL); 18326135Swpaul } 18426135Swpaul return (&clnt_res); 18526135Swpaul} 18626135Swpaul 18726135Swpaul/* 18826135Swpaul * "We have the machine that goes 'ping!'" -- Monty Python 18926135Swpaul * 19026135Swpaul * This function blasts packets at the YPPROC_DOMAIN_NONACK procedures 19126135Swpaul * of the NIS servers listed in restricted_addrs structure. 19226135Swpaul * Whoever replies the fastest becomes our chosen server. 19326135Swpaul * 19426135Swpaul * Note: THIS IS NOT A BROADCAST OPERATION! We could use clnt_broadcast() 19526135Swpaul * for this, but that has the following problems: 19626135Swpaul * - We only get the address of the machine that replied in the 19726135Swpaul * 'eachresult' callback, and on multi-homed machines this can 19826135Swpaul * lead to confusion. 19926135Swpaul * - clnt_broadcast() only transmits to local networks, whereas with 20026135Swpaul * NIS+ you can have a perfectly good server located anywhere on or 20126135Swpaul * off the local network. 20226135Swpaul * - clnt_broadcast() blocks for an arbitrary amount of time which the 20326135Swpaul * caller can't control -- we want to avoid that. 20426135Swpaul * 20526135Swpaul * Also note that this has nothing to do with the NIS_PING procedure used 20626135Swpaul * for replica updates. 20726135Swpaul */ 20826135Swpaul 20926135Swpaulstruct ping_req { 21026135Swpaul struct sockaddr_in sin; 211103428Sfenner u_int32_t xid; 21226135Swpaul}; 21326135Swpaul 21490298Sdesint 21590298Sdes__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port) 21626135Swpaul{ 21790297Sdes struct timeval tv = { 5, 0 }; 21826135Swpaul struct ping_req **reqs; 21926135Swpaul unsigned long i; 22074880Swpaul int async; 22132631Swpaul struct sockaddr_in sin, *any = NULL; 222183038Sdfr struct netbuf addr; 22326135Swpaul int winner = -1; 224103428Sfenner u_int32_t xid_seed, xid_lookup; 22526135Swpaul int sock, dontblock = 1; 22626135Swpaul CLIENT *clnt; 22726135Swpaul char *foo = dom; 22830252Swpaul int validsrvs = 0; 22926135Swpaul 23026135Swpaul /* Set up handles. */ 23126135Swpaul reqs = calloc(1, sizeof(struct ping_req *) * cnt); 23226135Swpaul xid_seed = time(NULL) ^ getpid(); 23326135Swpaul 23426135Swpaul for (i = 0; i < cnt; i++) { 23526135Swpaul bzero((char *)&sin, sizeof(sin)); 23626135Swpaul sin.sin_family = AF_INET; 23726135Swpaul bcopy((char *)&restricted_addrs[i], 23826135Swpaul (char *)&sin.sin_addr, sizeof(struct in_addr)); 23926135Swpaul sin.sin_port = htons(__pmap_getport(&sin, YPPROG, 24026135Swpaul YPVERS, IPPROTO_UDP)); 24126135Swpaul if (sin.sin_port == 0) 24226135Swpaul continue; 24326135Swpaul reqs[i] = calloc(1, sizeof(struct ping_req)); 24426135Swpaul bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin)); 24526135Swpaul any = &reqs[i]->sin; 24626135Swpaul reqs[i]->xid = xid_seed; 24726135Swpaul xid_seed++; 24830252Swpaul validsrvs++; 24926135Swpaul } 25026135Swpaul 25126135Swpaul /* Make sure at least one server was assigned */ 25230252Swpaul if (!validsrvs) { 25326135Swpaul free(reqs); 25426135Swpaul return(-1); 25526135Swpaul } 25626135Swpaul 25726135Swpaul /* Create RPC handle */ 25826135Swpaul sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 25926135Swpaul clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock); 26026135Swpaul if (clnt == NULL) { 26126135Swpaul close(sock); 26226135Swpaul for (i = 0; i < cnt; i++) 26326135Swpaul if (reqs[i] != NULL) 26426135Swpaul free(reqs[i]); 26526135Swpaul free(reqs); 26626135Swpaul return(-1); 26726135Swpaul } 26826135Swpaul clnt->cl_auth = authunix_create_default(); 26926135Swpaul tv.tv_sec = 0; 27074880Swpaul 27174462Salfred clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv); 27274880Swpaul async = TRUE; 27374880Swpaul clnt_control(clnt, CLSET_ASYNC, (char *)&async); 27426135Swpaul ioctl(sock, FIONBIO, &dontblock); 27526135Swpaul 27626135Swpaul /* Transmit */ 27726135Swpaul for (i = 0; i < cnt; i++) { 27826135Swpaul if (reqs[i] != NULL) { 27974880Swpaul clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid); 280183038Sdfr addr.len = sizeof(reqs[i]->sin); 281183038Sdfr addr.buf = (char *) &reqs[i]->sin; 282183038Sdfr clnt_control(clnt, CLSET_SVC_ADDR, &addr); 28326135Swpaul ypproc_domain_nonack_2_send(&foo, clnt); 28426135Swpaul } 28526135Swpaul } 28626135Swpaul 28726135Swpaul /* Receive reply */ 28826135Swpaul ypproc_domain_nonack_2_recv(&foo, clnt); 28926135Swpaul 29026135Swpaul /* Got a winner -- look him up. */ 29174880Swpaul clnt_control(clnt, CLGET_XID, (char *)&xid_lookup); 29226135Swpaul for (i = 0; i < cnt; i++) { 29326135Swpaul if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) { 29426135Swpaul winner = i; 29526135Swpaul *port = reqs[i]->sin.sin_port; 29626135Swpaul } 29726135Swpaul } 29826135Swpaul 29926135Swpaul /* Shut everything down */ 30026135Swpaul auth_destroy(clnt->cl_auth); 30126135Swpaul clnt_destroy(clnt); 30226135Swpaul close(sock); 30326135Swpaul 30426135Swpaul for (i = 0; i < cnt; i++) 30526135Swpaul if (reqs[i] != NULL) 30626135Swpaul free(reqs[i]); 30726135Swpaul free(reqs); 30826135Swpaul 30926135Swpaul return(winner); 31026135Swpaul} 311