1b2845e83SBill Paul /* 2b2845e83SBill Paul * Copyright (c) 1996, 1997 3b2845e83SBill Paul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4b2845e83SBill Paul * 5b2845e83SBill Paul * Redistribution and use in source and binary forms, with or without 6b2845e83SBill Paul * modification, are permitted provided that the following conditions 7b2845e83SBill Paul * are met: 8b2845e83SBill Paul * 1. Redistributions of source code must retain the above copyright 9b2845e83SBill Paul * notice, this list of conditions and the following disclaimer. 10b2845e83SBill Paul * 2. Redistributions in binary form must reproduce the above copyright 11b2845e83SBill Paul * notice, this list of conditions and the following disclaimer in the 12b2845e83SBill Paul * documentation and/or other materials provided with the distribution. 13b2845e83SBill Paul * 3. All advertising materials mentioning features or use of this software 14b2845e83SBill Paul * must display the following acknowledgement: 15b2845e83SBill Paul * This product includes software developed by Bill Paul. 16b2845e83SBill Paul * 4. Neither the name of the author nor the names of any co-contributors 17b2845e83SBill Paul * may be used to endorse or promote products derived from this software 18b2845e83SBill Paul * without specific prior written permission. 19b2845e83SBill Paul * 20b2845e83SBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21b2845e83SBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22b2845e83SBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23b2845e83SBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24b2845e83SBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25b2845e83SBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26b2845e83SBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27b2845e83SBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28b2845e83SBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29b2845e83SBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30b2845e83SBill Paul * SUCH DAMAGE. 31b2845e83SBill Paul */ 32b2845e83SBill Paul 33b2845e83SBill Paul /* 34b2845e83SBill Paul * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 35b2845e83SBill Paul * unrestricted use provided that this legend is included on all tape 36b2845e83SBill Paul * media and as a part of the software program in whole or part. Users 37b2845e83SBill Paul * may copy or modify Sun RPC without charge, but are not authorized 38b2845e83SBill Paul * to license or distribute it to anyone else except as part of a product or 39b2845e83SBill Paul * program developed by the user. 40b2845e83SBill Paul * 41b2845e83SBill Paul * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 42b2845e83SBill Paul * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 43b2845e83SBill Paul * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 44b2845e83SBill Paul * 45b2845e83SBill Paul * Sun RPC is provided with no support and without any obligation on the 46b2845e83SBill Paul * part of Sun Microsystems, Inc. to assist in its use, correction, 47b2845e83SBill Paul * modification or enhancement. 48b2845e83SBill Paul * 49b2845e83SBill Paul * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 50b2845e83SBill Paul * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 51b2845e83SBill Paul * OR ANY PART THEREOF. 52b2845e83SBill Paul * 53b2845e83SBill Paul * In no event will Sun Microsystems, Inc. be liable for any lost revenue 54b2845e83SBill Paul * or profits or other special, indirect and consequential damages, even if 55b2845e83SBill Paul * Sun has been advised of the possibility of such damages. 56b2845e83SBill Paul * 57b2845e83SBill Paul * Sun Microsystems, Inc. 58b2845e83SBill Paul * 2550 Garcia Avenue 59b2845e83SBill Paul * Mountain View, California 94043 60b2845e83SBill Paul */ 61b2845e83SBill Paul 62b2845e83SBill Paul #ifndef lint 6377cbf0b3SPhilippe Charnier #if 0 6477cbf0b3SPhilippe Charnier static char *sccsid = "@(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro"; 6577cbf0b3SPhilippe Charnier static char *sccsid = "@(#)from: clnt_udp.c 2.2 88/08/01 4.0 RPCSRC"; 6677cbf0b3SPhilippe Charnier #endif 6777cbf0b3SPhilippe Charnier static const char rcsid[] = 6897d92980SPeter Wemm "$FreeBSD$"; 69b2845e83SBill Paul #endif 70b2845e83SBill Paul 71b2845e83SBill Paul /* 72b2845e83SBill Paul * clnt_udp.c, Implements a UDP/IP based, client side RPC. 73b2845e83SBill Paul * 74b2845e83SBill Paul * Copyright (C) 1984, Sun Microsystems, Inc. 75b2845e83SBill Paul */ 76b2845e83SBill Paul 7777cbf0b3SPhilippe Charnier #include <errno.h> 7877cbf0b3SPhilippe Charnier #include <netdb.h> 79b2845e83SBill Paul #include <stdio.h> 80b2845e83SBill Paul #include <stdlib.h> 81b2845e83SBill Paul #include <string.h> 8277cbf0b3SPhilippe Charnier #include <unistd.h> 838de34b25SBill Paul #include <pthread.h> 84b2845e83SBill Paul #include <rpc/rpc.h> 85b2845e83SBill Paul #include <rpc/pmap_clnt.h> 86b2845e83SBill Paul #include <rpc/pmap_prot.h> 87b2845e83SBill Paul #include <rpcsvc/yp.h> 888de34b25SBill Paul #include <sys/types.h> 898de34b25SBill Paul #include <sys/poll.h> 9077cbf0b3SPhilippe Charnier #include <sys/socket.h> 918de34b25SBill Paul #include <sys/signal.h> 9277cbf0b3SPhilippe Charnier #include <sys/ioctl.h> 9377cbf0b3SPhilippe Charnier #include <net/if.h> 948de34b25SBill Paul 95b2845e83SBill Paul #include "yp_ping.h" 96b2845e83SBill Paul 97b2845e83SBill Paul struct cu_data { 988de34b25SBill Paul int cu_fd; /* connections fd */ 998de34b25SBill Paul bool_t cu_closeit; /* opened by library */ 1008de34b25SBill Paul struct sockaddr_storage cu_raddr; /* remote address */ 101b2845e83SBill Paul int cu_rlen; 1028de34b25SBill Paul struct timeval cu_wait; /* retransmit interval */ 1038de34b25SBill Paul struct timeval cu_total; /* total time for the call */ 104b2845e83SBill Paul struct rpc_err cu_error; 105b2845e83SBill Paul XDR cu_outxdrs; 106b2845e83SBill Paul u_int cu_xdrpos; 1078de34b25SBill Paul u_int cu_sendsz; /* send size */ 108b2845e83SBill Paul char *cu_outbuf; 1098de34b25SBill Paul u_int cu_recvsz; /* recv size */ 1108de34b25SBill Paul struct pollfd pfdp; 1118de34b25SBill Paul int cu_async; 112b2845e83SBill Paul char cu_inbuf[1]; 113b2845e83SBill Paul }; 114b2845e83SBill Paul 115b2845e83SBill Paul /* 116b2845e83SBill Paul * pmap_getport.c 117b2845e83SBill Paul * Client interface to pmap rpc service. 118b2845e83SBill Paul * 119b2845e83SBill Paul * Copyright (C) 1984, Sun Microsystems, Inc. 120b2845e83SBill Paul */ 121b2845e83SBill Paul 122b2845e83SBill Paul 123b2845e83SBill Paul static struct timeval timeout = { 1, 0 }; 124b2845e83SBill Paul static struct timeval tottimeout = { 1, 0 }; 125b2845e83SBill Paul 126b2845e83SBill Paul /* 127b2845e83SBill Paul * Find the mapped port for program,version. 128b2845e83SBill Paul * Calls the pmap service remotely to do the lookup. 129b2845e83SBill Paul * Returns 0 if no map exists. 130b2845e83SBill Paul */ 131b2845e83SBill Paul static u_short 132b2845e83SBill Paul __pmap_getport(address, program, version, protocol) 133b2845e83SBill Paul struct sockaddr_in *address; 134b2845e83SBill Paul u_long program; 135b2845e83SBill Paul u_long version; 136b2845e83SBill Paul u_int protocol; 137b2845e83SBill Paul { 138b2845e83SBill Paul u_short port = 0; 139b2845e83SBill Paul int sock = -1; 140b2845e83SBill Paul register CLIENT *client; 141b2845e83SBill Paul struct pmap parms; 142b2845e83SBill Paul 143b2845e83SBill Paul address->sin_port = htons(PMAPPORT); 144b2845e83SBill Paul 145b2845e83SBill Paul client = clntudp_bufcreate(address, PMAPPROG, 146b2845e83SBill Paul PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); 147b2845e83SBill Paul if (client != (CLIENT *)NULL) { 148b2845e83SBill Paul parms.pm_prog = program; 149b2845e83SBill Paul parms.pm_vers = version; 150b2845e83SBill Paul parms.pm_prot = protocol; 151b2845e83SBill Paul parms.pm_port = 0; /* not needed or used */ 152b2845e83SBill Paul if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms, 153b2845e83SBill Paul xdr_u_short, &port, tottimeout) != RPC_SUCCESS){ 154b2845e83SBill Paul rpc_createerr.cf_stat = RPC_PMAPFAILURE; 155b2845e83SBill Paul clnt_geterr(client, &rpc_createerr.cf_error); 156b2845e83SBill Paul } else if (port == 0) { 157b2845e83SBill Paul rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 158b2845e83SBill Paul } 159b2845e83SBill Paul CLNT_DESTROY(client); 160b2845e83SBill Paul } 161b2845e83SBill Paul if (sock != -1) 162b2845e83SBill Paul (void)close(sock); 163b2845e83SBill Paul address->sin_port = 0; 164b2845e83SBill Paul return (port); 165b2845e83SBill Paul } 166b2845e83SBill Paul 167b2845e83SBill Paul /* 168b2845e83SBill Paul * Transmit to YPPROC_DOMAIN_NONACK, return immediately. 169b2845e83SBill Paul */ 170b2845e83SBill Paul static bool_t * 171b2845e83SBill Paul ypproc_domain_nonack_2_send(domainname *argp, CLIENT *clnt) 172b2845e83SBill Paul { 173b2845e83SBill Paul static bool_t clnt_res; 174b2845e83SBill Paul struct timeval TIMEOUT = { 0, 0 }; 175b2845e83SBill Paul 176b2845e83SBill Paul memset((char *)&clnt_res, 0, sizeof (clnt_res)); 177b2845e83SBill Paul if (clnt_call(clnt, YPPROC_DOMAIN_NONACK, 178b2845e83SBill Paul (xdrproc_t) xdr_domainname, (caddr_t) argp, 179b2845e83SBill Paul (xdrproc_t) xdr_bool, (caddr_t) &clnt_res, 180b2845e83SBill Paul TIMEOUT) != RPC_SUCCESS) { 181b2845e83SBill Paul return (NULL); 182b2845e83SBill Paul } 183b2845e83SBill Paul return (&clnt_res); 184b2845e83SBill Paul } 185b2845e83SBill Paul 186b2845e83SBill Paul /* 187b2845e83SBill Paul * Receive response from YPPROC_DOMAIN_NONACK asynchronously. 188b2845e83SBill Paul */ 189b2845e83SBill Paul static bool_t * 190b2845e83SBill Paul ypproc_domain_nonack_2_recv(domainname *argp, CLIENT *clnt) 191b2845e83SBill Paul { 192b2845e83SBill Paul static bool_t clnt_res; 193b2845e83SBill Paul struct timeval TIMEOUT = { 0, 0 }; 194b2845e83SBill Paul 195b2845e83SBill Paul memset((char *)&clnt_res, 0, sizeof (clnt_res)); 196b2845e83SBill Paul if (clnt_call(clnt, YPPROC_DOMAIN_NONACK, 197b2845e83SBill Paul (xdrproc_t) NULL, (caddr_t) argp, 198b2845e83SBill Paul (xdrproc_t) xdr_bool, (caddr_t) &clnt_res, 199b2845e83SBill Paul TIMEOUT) != RPC_SUCCESS) { 200b2845e83SBill Paul return (NULL); 201b2845e83SBill Paul } 202b2845e83SBill Paul return (&clnt_res); 203b2845e83SBill Paul } 204b2845e83SBill Paul 205b2845e83SBill Paul /* 206b2845e83SBill Paul * "We have the machine that goes 'ping!'" -- Monty Python 207b2845e83SBill Paul * 208b2845e83SBill Paul * This function blasts packets at the YPPROC_DOMAIN_NONACK procedures 209b2845e83SBill Paul * of the NIS servers listed in restricted_addrs structure. 210b2845e83SBill Paul * Whoever replies the fastest becomes our chosen server. 211b2845e83SBill Paul * 212b2845e83SBill Paul * Note: THIS IS NOT A BROADCAST OPERATION! We could use clnt_broadcast() 213b2845e83SBill Paul * for this, but that has the following problems: 214b2845e83SBill Paul * - We only get the address of the machine that replied in the 215b2845e83SBill Paul * 'eachresult' callback, and on multi-homed machines this can 216b2845e83SBill Paul * lead to confusion. 217b2845e83SBill Paul * - clnt_broadcast() only transmits to local networks, whereas with 218b2845e83SBill Paul * NIS+ you can have a perfectly good server located anywhere on or 219b2845e83SBill Paul * off the local network. 220b2845e83SBill Paul * - clnt_broadcast() blocks for an arbitrary amount of time which the 221b2845e83SBill Paul * caller can't control -- we want to avoid that. 222b2845e83SBill Paul * 223b2845e83SBill Paul * Also note that this has nothing to do with the NIS_PING procedure used 224b2845e83SBill Paul * for replica updates. 225b2845e83SBill Paul */ 226b2845e83SBill Paul 227b2845e83SBill Paul struct ping_req { 228b2845e83SBill Paul struct sockaddr_in sin; 229b2845e83SBill Paul unsigned long xid; 230b2845e83SBill Paul }; 231b2845e83SBill Paul 232b2845e83SBill Paul int __yp_ping(restricted_addrs, cnt, dom, port) 233b2845e83SBill Paul struct in_addr *restricted_addrs; 234b2845e83SBill Paul int cnt; 235b2845e83SBill Paul char *dom; 236b2845e83SBill Paul short *port; 237b2845e83SBill Paul { 238b2845e83SBill Paul struct timeval tv = { 5 , 0 }; 239b2845e83SBill Paul struct ping_req **reqs; 240b2845e83SBill Paul unsigned long i; 2418de34b25SBill Paul int async; 242844812c4SBill Paul struct sockaddr_in sin, *any = NULL; 243b2845e83SBill Paul int winner = -1; 244b2845e83SBill Paul time_t xid_seed, xid_lookup; 245b2845e83SBill Paul int sock, dontblock = 1; 246b2845e83SBill Paul CLIENT *clnt; 247b2845e83SBill Paul char *foo = dom; 248b2845e83SBill Paul struct cu_data *cu; 249b2845e83SBill Paul enum clnt_stat (*oldfunc)(); 250bfb109dfSBill Paul int validsrvs = 0; 251b2845e83SBill Paul 252b2845e83SBill Paul /* Set up handles. */ 253b2845e83SBill Paul reqs = calloc(1, sizeof(struct ping_req *) * cnt); 254b2845e83SBill Paul xid_seed = time(NULL) ^ getpid(); 255b2845e83SBill Paul 256b2845e83SBill Paul for (i = 0; i < cnt; i++) { 257b2845e83SBill Paul bzero((char *)&sin, sizeof(sin)); 258b2845e83SBill Paul sin.sin_family = AF_INET; 259b2845e83SBill Paul bcopy((char *)&restricted_addrs[i], 260b2845e83SBill Paul (char *)&sin.sin_addr, sizeof(struct in_addr)); 261b2845e83SBill Paul sin.sin_port = htons(__pmap_getport(&sin, YPPROG, 262b2845e83SBill Paul YPVERS, IPPROTO_UDP)); 263b2845e83SBill Paul if (sin.sin_port == 0) 264b2845e83SBill Paul continue; 265b2845e83SBill Paul reqs[i] = calloc(1, sizeof(struct ping_req)); 266b2845e83SBill Paul bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin)); 267b2845e83SBill Paul any = &reqs[i]->sin; 268b2845e83SBill Paul reqs[i]->xid = xid_seed; 269b2845e83SBill Paul xid_seed++; 270bfb109dfSBill Paul validsrvs++; 271b2845e83SBill Paul } 272b2845e83SBill Paul 273b2845e83SBill Paul /* Make sure at least one server was assigned */ 274bfb109dfSBill Paul if (!validsrvs) { 275b2845e83SBill Paul free(reqs); 276b2845e83SBill Paul return(-1); 277b2845e83SBill Paul } 278b2845e83SBill Paul 279b2845e83SBill Paul /* Create RPC handle */ 280b2845e83SBill Paul sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 281b2845e83SBill Paul clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock); 282b2845e83SBill Paul if (clnt == NULL) { 283b2845e83SBill Paul close(sock); 284b2845e83SBill Paul for (i = 0; i < cnt; i++) 285b2845e83SBill Paul if (reqs[i] != NULL) 286b2845e83SBill Paul free(reqs[i]); 287b2845e83SBill Paul free(reqs); 288b2845e83SBill Paul return(-1); 289b2845e83SBill Paul } 290b2845e83SBill Paul clnt->cl_auth = authunix_create_default(); 291b2845e83SBill Paul cu = (struct cu_data *)clnt->cl_private; 292b2845e83SBill Paul tv.tv_sec = 0; 2938de34b25SBill Paul 2948360efbdSAlfred Perlstein clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv); 2958de34b25SBill Paul async = TRUE; 2968de34b25SBill Paul clnt_control(clnt, CLSET_ASYNC, (char *)&async); 297b2845e83SBill Paul ioctl(sock, FIONBIO, &dontblock); 298b2845e83SBill Paul 299b2845e83SBill Paul /* Transmit */ 300b2845e83SBill Paul for (i = 0; i < cnt; i++) { 301b2845e83SBill Paul if (reqs[i] != NULL) { 3028de34b25SBill Paul clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid); 303b2845e83SBill Paul bcopy((char *)&reqs[i]->sin, (char *)&cu->cu_raddr, 304b2845e83SBill Paul sizeof(struct sockaddr_in)); 305b2845e83SBill Paul ypproc_domain_nonack_2_send(&foo, clnt); 306b2845e83SBill Paul } 307b2845e83SBill Paul } 308b2845e83SBill Paul 309b2845e83SBill Paul /* Receive reply */ 310b2845e83SBill Paul ypproc_domain_nonack_2_recv(&foo, clnt); 311b2845e83SBill Paul 312b2845e83SBill Paul /* Got a winner -- look him up. */ 3138de34b25SBill Paul clnt_control(clnt, CLGET_XID, (char *)&xid_lookup); 314b2845e83SBill Paul for (i = 0; i < cnt; i++) { 315b2845e83SBill Paul if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) { 316b2845e83SBill Paul winner = i; 317b2845e83SBill Paul *port = reqs[i]->sin.sin_port; 318b2845e83SBill Paul } 319b2845e83SBill Paul } 320b2845e83SBill Paul 321b2845e83SBill Paul /* Shut everything down */ 322b2845e83SBill Paul auth_destroy(clnt->cl_auth); 323b2845e83SBill Paul clnt_destroy(clnt); 324b2845e83SBill Paul close(sock); 325b2845e83SBill Paul 326b2845e83SBill Paul for (i = 0; i < cnt; i++) 327b2845e83SBill Paul if (reqs[i] != NULL) 328b2845e83SBill Paul free(reqs[i]); 329b2845e83SBill Paul free(reqs); 330b2845e83SBill Paul 331b2845e83SBill Paul return(winner); 332b2845e83SBill Paul } 333