clnt_bcast.c revision 92990
174462Salfred/* $NetBSD: clnt_bcast.c,v 1.3 2000/07/06 03:05:20 christos Exp $ */ 274462Salfred 374462Salfred/* 474462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 574462Salfred * unrestricted use provided that this legend is included on all tape 674462Salfred * media and as a part of the software program in whole or part. Users 774462Salfred * may copy or modify Sun RPC without charge, but are not authorized 874462Salfred * to license or distribute it to anyone else except as part of a product or 974462Salfred * program developed by the user. 1074462Salfred * 1174462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1274462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1374462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1474462Salfred * 1574462Salfred * Sun RPC is provided with no support and without any obligation on the 1674462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction, 1774462Salfred * modification or enhancement. 1874462Salfred * 1974462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2074462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2174462Salfred * OR ANY PART THEREOF. 2274462Salfred * 2374462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2474462Salfred * or profits or other special, indirect and consequential damages, even if 2574462Salfred * Sun has been advised of the possibility of such damages. 2674462Salfred * 2774462Salfred * Sun Microsystems, Inc. 2874462Salfred * 2550 Garcia Avenue 2974462Salfred * Mountain View, California 94043 3074462Salfred */ 3174462Salfred/* 3274462Salfred * Copyright (c) 1986-1991 by Sun Microsystems Inc. 3374462Salfred */ 3474462Salfred 3574462Salfred/* #ident "@(#)clnt_bcast.c 1.18 94/05/03 SMI" */ 3674462Salfred 3774462Salfred#if !defined(lint) && defined(SCCSIDS) 3874462Salfredstatic char sccsid[] = "@(#)clnt_bcast.c 1.15 89/04/21 Copyr 1988 Sun Micro"; 3974462Salfred#endif 4092990Sobrien#include <sys/cdefs.h> 4192990Sobrien__FBSDID("$FreeBSD: head/lib/libc/rpc/clnt_bcast.c 92990 2002-03-22 23:18:37Z obrien $"); 4274462Salfred 4374462Salfred 4474462Salfred/* 4574462Salfred * clnt_bcast.c 4674462Salfred * Client interface to broadcast service. 4774462Salfred * 4874462Salfred * Copyright (C) 1988, Sun Microsystems, Inc. 4974462Salfred * 5074462Salfred * The following is kludged-up support for simple rpc broadcasts. 5174462Salfred * Someday a large, complicated system will replace these routines. 5274462Salfred */ 5374462Salfred 5474462Salfred#include "namespace.h" 5574462Salfred#include <sys/types.h> 5674462Salfred#include <sys/socket.h> 5774462Salfred#include <sys/queue.h> 5874462Salfred#include <net/if.h> 5974462Salfred#include <netinet/in.h> 6074462Salfred#include <ifaddrs.h> 6174462Salfred#include <sys/poll.h> 6274462Salfred#include <rpc/rpc.h> 6374462Salfred#ifdef PORTMAP 6474462Salfred#include <rpc/pmap_prot.h> 6574462Salfred#include <rpc/pmap_clnt.h> 6674462Salfred#include <rpc/pmap_rmt.h> 6774462Salfred#endif /* PORTMAP */ 6874462Salfred#include <rpc/nettype.h> 6974462Salfred#include <arpa/inet.h> 7074462Salfred#ifdef RPC_DEBUG 7174462Salfred#include <stdio.h> 7274462Salfred#endif 7374462Salfred#include <errno.h> 7474462Salfred#include <stdlib.h> 7574462Salfred#include <unistd.h> 7674462Salfred#include <netdb.h> 7774462Salfred#include <err.h> 7874462Salfred#include <string.h> 7974462Salfred#include "un-namespace.h" 8074462Salfred 8174462Salfred#include "rpc_com.h" 8274462Salfred 8374462Salfred#define MAXBCAST 20 /* Max no of broadcasting transports */ 8474462Salfred#define INITTIME 4000 /* Time to wait initially */ 8574462Salfred#define WAITTIME 8000 /* Maximum time to wait */ 8674462Salfred 8774462Salfred/* 8874462Salfred * If nettype is NULL, it broadcasts on all the available 8974462Salfred * datagram_n transports. May potentially lead to broadacst storms 9074462Salfred * and hence should be used with caution, care and courage. 9174462Salfred * 9274462Salfred * The current parameter xdr packet size is limited by the max tsdu 9374462Salfred * size of the transport. If the max tsdu size of any transport is 9474462Salfred * smaller than the parameter xdr packet, then broadcast is not 9574462Salfred * sent on that transport. 9674462Salfred * 9774462Salfred * Also, the packet size should be less the packet size of 9874462Salfred * the data link layer (for ethernet it is 1400 bytes). There is 9974462Salfred * no easy way to find out the max size of the data link layer and 10074462Salfred * we are assuming that the args would be smaller than that. 10174462Salfred * 10274462Salfred * The result size has to be smaller than the transport tsdu size. 10374462Salfred * 10474462Salfred * If PORTMAP has been defined, we send two packets for UDP, one for 10574462Salfred * rpcbind and one for portmap. For those machines which support 10674462Salfred * both rpcbind and portmap, it will cause them to reply twice, and 10774462Salfred * also here it will get two responses ... inefficient and clumsy. 10874462Salfred */ 10974462Salfred 11074462Salfredstruct broadif { 11174462Salfred int index; 11274462Salfred struct sockaddr_storage broadaddr; 11374462Salfred TAILQ_ENTRY(broadif) link; 11474462Salfred}; 11574462Salfred 11674462Salfredtypedef TAILQ_HEAD(, broadif) broadlist_t; 11774462Salfred 11892905Sobrienint __rpc_getbroadifs(int, int, int, broadlist_t *); 11992905Sobrienvoid __rpc_freebroadifs(broadlist_t *); 12092905Sobrienint __rpc_broadenable(int, int, struct broadif *); 12174462Salfred 12274462Salfredint __rpc_lowvers = 0; 12374462Salfred 12474462Salfredint 12574462Salfred__rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list) 12674462Salfred{ 12774462Salfred int count = 0; 12874462Salfred struct broadif *bip; 12974462Salfred struct ifaddrs *ifap, *ifp; 13074462Salfred#ifdef INET6 13174462Salfred struct sockaddr_in6 *sin6; 13274462Salfred#endif 13374462Salfred struct sockaddr_in *sin; 13474462Salfred struct addrinfo hints, *res; 13574462Salfred 13674462Salfred if (getifaddrs(&ifp) < 0) 13774462Salfred return 0; 13874462Salfred 13974462Salfred memset(&hints, 0, sizeof hints); 14074462Salfred 14174462Salfred hints.ai_family = af; 14274462Salfred hints.ai_protocol = proto; 14374462Salfred hints.ai_socktype = socktype; 14474462Salfred 14574462Salfred if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0) 14674462Salfred return 0; 14774462Salfred 14874462Salfred for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { 14974462Salfred if (ifap->ifa_addr->sa_family != af || 15074462Salfred !(ifap->ifa_flags & IFF_UP)) 15174462Salfred continue; 15274462Salfred#ifdef INET6 15374462Salfred if ((af == AF_INET6 && !(ifap->ifa_flags & IFF_MULTICAST)) || 15474462Salfred !(ifap->ifa_flags & IFF_BROADCAST)) 15574462Salfred continue; 15674462Salfred#endif 15774462Salfred bip = (struct broadif *)malloc(sizeof *bip); 15874462Salfred if (bip == NULL) 15974462Salfred break; 16074462Salfred bip->index = if_nametoindex(ifap->ifa_name); 16174462Salfred#ifdef INET6 16274462Salfred if (af != AF_INET6 && (ifap->ifa_flags & IFF_BROADCAST)) { 16374462Salfred#else 16474462Salfred if (ifap->ifa_flags & IFF_BROADCAST) { 16574462Salfred#endif 16674462Salfred memcpy(&bip->broadaddr, ifap->ifa_broadaddr, 16774462Salfred (size_t)ifap->ifa_broadaddr->sa_len); 16874462Salfred sin = (struct sockaddr_in *)(void *)&bip->broadaddr; 16974462Salfred sin->sin_port = 17074462Salfred ((struct sockaddr_in *) 17174462Salfred (void *)res->ai_addr)->sin_port; 17274462Salfred#ifdef INET6 17374462Salfred } else if (af == AF_INET6) { 17474462Salfred sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr; 17574462Salfred inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr); 17674462Salfred sin6->sin6_family = af; 17774462Salfred sin6->sin6_len = sizeof *sin6; 17874462Salfred sin6->sin6_port = 17974462Salfred ((struct sockaddr_in6 *) 18074462Salfred (void *)res->ai_addr)->sin6_port; 18174462Salfred sin6->sin6_scope_id = bip->index; 18274462Salfred#endif 18374462Salfred } 18474462Salfred TAILQ_INSERT_TAIL(list, bip, link); 18574462Salfred count++; 18674462Salfred } 18774462Salfred freeifaddrs(ifp); 18874462Salfred freeaddrinfo(res); 18974462Salfred 19074462Salfred return count; 19174462Salfred} 19274462Salfred 19374462Salfredvoid 19474462Salfred__rpc_freebroadifs(broadlist_t *list) 19574462Salfred{ 19674462Salfred struct broadif *bip, *next; 19774462Salfred 19874462Salfred bip = TAILQ_FIRST(list); 19974462Salfred 20074462Salfred while (bip != NULL) { 20174462Salfred next = TAILQ_NEXT(bip, link); 20274462Salfred free(bip); 20374462Salfred bip = next; 20474462Salfred } 20574462Salfred} 20674462Salfred 20774462Salfredint 20874462Salfred/*ARGSUSED*/ 20974462Salfred__rpc_broadenable(int af, int s, struct broadif *bip) 21074462Salfred{ 21174462Salfred int o = 1; 21274462Salfred 21374462Salfred#if 0 21474462Salfred if (af == AF_INET6) { 21574462Salfred fprintf(stderr, "set v6 multicast if to %d\n", bip->index); 21674462Salfred if (_setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index, 21774462Salfred sizeof bip->index) < 0) 21874462Salfred return -1; 21974462Salfred } else 22074462Salfred#endif 22174462Salfred if (_setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) < 0) 22274462Salfred return -1; 22374462Salfred 22474462Salfred return 0; 22574462Salfred} 22674462Salfred 22774462Salfred 22874462Salfredenum clnt_stat 22974462Salfredrpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, 23074462Salfred eachresult, inittime, waittime, nettype) 23174462Salfred rpcprog_t prog; /* program number */ 23274462Salfred rpcvers_t vers; /* version number */ 23374462Salfred rpcproc_t proc; /* procedure number */ 23474462Salfred xdrproc_t xargs; /* xdr routine for args */ 23574462Salfred caddr_t argsp; /* pointer to args */ 23674462Salfred xdrproc_t xresults; /* xdr routine for results */ 23774462Salfred caddr_t resultsp; /* pointer to results */ 23874462Salfred resultproc_t eachresult; /* call with each result obtained */ 23974462Salfred int inittime; /* how long to wait initially */ 24074462Salfred int waittime; /* maximum time to wait */ 24174462Salfred const char *nettype; /* transport type */ 24274462Salfred{ 24374462Salfred enum clnt_stat stat = RPC_SUCCESS; /* Return status */ 24474462Salfred XDR xdr_stream; /* XDR stream */ 24574462Salfred XDR *xdrs = &xdr_stream; 24674462Salfred struct rpc_msg msg; /* RPC message */ 24774462Salfred struct timeval t; 24874462Salfred char *outbuf = NULL; /* Broadcast msg buffer */ 24974462Salfred char *inbuf = NULL; /* Reply buf */ 25074462Salfred int inlen; 25174462Salfred u_int maxbufsize = 0; 25274462Salfred AUTH *sys_auth = authunix_create_default(); 25374462Salfred int i; 25474462Salfred void *handle; 25574462Salfred char uaddress[1024]; /* A self imposed limit */ 25674462Salfred char *uaddrp = uaddress; 25774462Salfred int pmap_reply_flag; /* reply recvd from PORTMAP */ 25874462Salfred /* An array of all the suitable broadcast transports */ 25974462Salfred struct { 26074462Salfred int fd; /* File descriptor */ 26174462Salfred int af; 26274462Salfred int proto; 26374462Salfred struct netconfig *nconf; /* Netconfig structure */ 26474462Salfred u_int asize; /* Size of the addr buf */ 26574462Salfred u_int dsize; /* Size of the data buf */ 26674462Salfred struct sockaddr_storage raddr; /* Remote address */ 26774462Salfred broadlist_t nal; 26874462Salfred } fdlist[MAXBCAST]; 26974462Salfred struct pollfd pfd[MAXBCAST]; 27074462Salfred size_t fdlistno = 0; 27174462Salfred struct r_rpcb_rmtcallargs barg; /* Remote arguments */ 27274462Salfred struct r_rpcb_rmtcallres bres; /* Remote results */ 27390271Salfred size_t outlen; 27474462Salfred struct netconfig *nconf; 27574462Salfred int msec; 27674462Salfred int pollretval; 27774462Salfred int fds_found; 27874462Salfred 27974462Salfred#ifdef PORTMAP 28090271Salfred size_t outlen_pmap = 0; 28174462Salfred u_long port; /* Remote port number */ 28274462Salfred int pmap_flag = 0; /* UDP exists ? */ 28374462Salfred char *outbuf_pmap = NULL; 28474462Salfred struct rmtcallargs barg_pmap; /* Remote arguments */ 28574462Salfred struct rmtcallres bres_pmap; /* Remote results */ 28674462Salfred u_int udpbufsz = 0; 28774462Salfred#endif /* PORTMAP */ 28874462Salfred 28974462Salfred if (sys_auth == NULL) { 29074462Salfred return (RPC_SYSTEMERROR); 29174462Salfred } 29274462Salfred /* 29374462Salfred * initialization: create a fd, a broadcast address, and send the 29474462Salfred * request on the broadcast transport. 29574462Salfred * Listen on all of them and on replies, call the user supplied 29674462Salfred * function. 29774462Salfred */ 29874462Salfred 29974462Salfred if (nettype == NULL) 30074462Salfred nettype = "datagram_n"; 30174462Salfred if ((handle = __rpc_setconf(nettype)) == NULL) { 30274462Salfred return (RPC_UNKNOWNPROTO); 30374462Salfred } 30474462Salfred while ((nconf = __rpc_getconf(handle)) != NULL) { 30574462Salfred int fd; 30674462Salfred struct __rpc_sockinfo si; 30774462Salfred 30874462Salfred if (nconf->nc_semantics != NC_TPI_CLTS) 30974462Salfred continue; 31074462Salfred if (fdlistno >= MAXBCAST) 31174462Salfred break; /* No more slots available */ 31274462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 31374462Salfred continue; 31474462Salfred 31574462Salfred TAILQ_INIT(&fdlist[fdlistno].nal); 31674462Salfred if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype, 31774462Salfred &fdlist[fdlistno].nal) == 0) 31874462Salfred continue; 31974462Salfred 32074462Salfred fd = _socket(si.si_af, si.si_socktype, si.si_proto); 32174462Salfred if (fd < 0) { 32274462Salfred stat = RPC_CANTSEND; 32374462Salfred continue; 32474462Salfred } 32574462Salfred fdlist[fdlistno].af = si.si_af; 32674462Salfred fdlist[fdlistno].proto = si.si_proto; 32774462Salfred fdlist[fdlistno].fd = fd; 32874462Salfred fdlist[fdlistno].nconf = nconf; 32974462Salfred fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af); 33074462Salfred pfd[fdlistno].events = POLLIN | POLLPRI | 33174462Salfred POLLRDNORM | POLLRDBAND; 33274462Salfred pfd[fdlistno].fd = fdlist[fdlistno].fd = fd; 33374462Salfred fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto, 33474462Salfred 0); 33574462Salfred 33674462Salfred if (maxbufsize <= fdlist[fdlistno].dsize) 33774462Salfred maxbufsize = fdlist[fdlistno].dsize; 33874462Salfred 33974462Salfred#ifdef PORTMAP 34074462Salfred if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) { 34174462Salfred udpbufsz = fdlist[fdlistno].dsize; 34274462Salfred if ((outbuf_pmap = malloc(udpbufsz)) == NULL) { 34374462Salfred _close(fd); 34474462Salfred stat = RPC_SYSTEMERROR; 34574462Salfred goto done_broad; 34674462Salfred } 34774462Salfred pmap_flag = 1; 34874462Salfred } 34974462Salfred#endif /* PORTMAP */ 35074462Salfred fdlistno++; 35174462Salfred } 35274462Salfred 35374462Salfred if (fdlistno == 0) { 35474462Salfred if (stat == RPC_SUCCESS) 35574462Salfred stat = RPC_UNKNOWNPROTO; 35674462Salfred goto done_broad; 35774462Salfred } 35874462Salfred if (maxbufsize == 0) { 35974462Salfred if (stat == RPC_SUCCESS) 36074462Salfred stat = RPC_CANTSEND; 36174462Salfred goto done_broad; 36274462Salfred } 36374462Salfred inbuf = malloc(maxbufsize); 36474462Salfred outbuf = malloc(maxbufsize); 36574462Salfred if ((inbuf == NULL) || (outbuf == NULL)) { 36674462Salfred stat = RPC_SYSTEMERROR; 36774462Salfred goto done_broad; 36874462Salfred } 36974462Salfred 37074462Salfred /* Serialize all the arguments which have to be sent */ 37174462Salfred (void) gettimeofday(&t, NULL); 37274462Salfred msg.rm_xid = __RPC_GETXID(&t); 37374462Salfred msg.rm_direction = CALL; 37474462Salfred msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 37574462Salfred msg.rm_call.cb_prog = RPCBPROG; 37674462Salfred msg.rm_call.cb_vers = RPCBVERS; 37774462Salfred msg.rm_call.cb_proc = RPCBPROC_CALLIT; 37874462Salfred barg.prog = prog; 37974462Salfred barg.vers = vers; 38074462Salfred barg.proc = proc; 38174462Salfred barg.args.args_val = argsp; 38274462Salfred barg.xdr_args = xargs; 38374462Salfred bres.addr = uaddrp; 38474462Salfred bres.results.results_val = resultsp; 38574462Salfred bres.xdr_res = xresults; 38674462Salfred msg.rm_call.cb_cred = sys_auth->ah_cred; 38774462Salfred msg.rm_call.cb_verf = sys_auth->ah_verf; 38874462Salfred xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE); 38974462Salfred if ((!xdr_callmsg(xdrs, &msg)) || 39074462Salfred (!xdr_rpcb_rmtcallargs(xdrs, 39174462Salfred (struct rpcb_rmtcallargs *)(void *)&barg))) { 39274462Salfred stat = RPC_CANTENCODEARGS; 39374462Salfred goto done_broad; 39474462Salfred } 39574462Salfred outlen = xdr_getpos(xdrs); 39674462Salfred xdr_destroy(xdrs); 39774462Salfred 39874462Salfred#ifdef PORTMAP 39974462Salfred /* Prepare the packet for version 2 PORTMAP */ 40074462Salfred if (pmap_flag) { 40174462Salfred msg.rm_xid++; /* One way to distinguish */ 40274462Salfred msg.rm_call.cb_prog = PMAPPROG; 40374462Salfred msg.rm_call.cb_vers = PMAPVERS; 40474462Salfred msg.rm_call.cb_proc = PMAPPROC_CALLIT; 40574462Salfred barg_pmap.prog = prog; 40674462Salfred barg_pmap.vers = vers; 40774462Salfred barg_pmap.proc = proc; 40874462Salfred barg_pmap.args_ptr = argsp; 40974462Salfred barg_pmap.xdr_args = xargs; 41074462Salfred bres_pmap.port_ptr = &port; 41174462Salfred bres_pmap.xdr_results = xresults; 41274462Salfred bres_pmap.results_ptr = resultsp; 41374462Salfred xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE); 41474462Salfred if ((! xdr_callmsg(xdrs, &msg)) || 41574462Salfred (! xdr_rmtcall_args(xdrs, &barg_pmap))) { 41674462Salfred stat = RPC_CANTENCODEARGS; 41774462Salfred goto done_broad; 41874462Salfred } 41974462Salfred outlen_pmap = xdr_getpos(xdrs); 42074462Salfred xdr_destroy(xdrs); 42174462Salfred } 42287966Speter#endif /* PORTMAP */ 42374462Salfred 42474462Salfred /* 42574462Salfred * Basic loop: broadcast the packets to transports which 42674462Salfred * support data packets of size such that one can encode 42774462Salfred * all the arguments. 42874462Salfred * Wait a while for response(s). 42974462Salfred * The response timeout grows larger per iteration. 43074462Salfred */ 43174462Salfred for (msec = inittime; msec <= waittime; msec += msec) { 43274462Salfred struct broadif *bip; 43374462Salfred 43474462Salfred /* Broadcast all the packets now */ 43574462Salfred for (i = 0; i < fdlistno; i++) { 43674462Salfred if (fdlist[i].dsize < outlen) { 43774462Salfred stat = RPC_CANTSEND; 43874462Salfred continue; 43974462Salfred } 44074462Salfred for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL; 44174462Salfred bip = TAILQ_NEXT(bip, link)) { 44274462Salfred void *addr; 44374462Salfred 44474462Salfred addr = &bip->broadaddr; 44574462Salfred 44674462Salfred __rpc_broadenable(fdlist[i].af, fdlist[i].fd, 44774462Salfred bip); 44874462Salfred 44974462Salfred /* 45074462Salfred * Only use version 3 if lowvers is not set 45174462Salfred */ 45274462Salfred 45374462Salfred if (!__rpc_lowvers) 45474462Salfred if (_sendto(fdlist[i].fd, outbuf, 45574462Salfred outlen, 0, (struct sockaddr*)addr, 45674462Salfred (size_t)fdlist[i].asize) != 45774462Salfred outlen) { 45874462Salfred#ifdef RPC_DEBUG 45974462Salfred perror("sendto"); 46074462Salfred#endif 46174462Salfred warnx("clnt_bcast: cannot send" 46274462Salfred "broadcast packet"); 46374462Salfred stat = RPC_CANTSEND; 46474462Salfred continue; 46574462Salfred }; 46674462Salfred#ifdef RPC_DEBUG 46774462Salfred if (!__rpc_lowvers) 46874462Salfred fprintf(stderr, "Broadcast packet sent " 46974462Salfred "for %s\n", 47074462Salfred fdlist[i].nconf->nc_netid); 47174462Salfred#endif 47274462Salfred#ifdef PORTMAP 47374462Salfred /* 47474462Salfred * Send the version 2 packet also 47574462Salfred * for UDP/IP 47674462Salfred */ 47774462Salfred if (fdlist[i].proto == IPPROTO_UDP) { 47874462Salfred if (_sendto(fdlist[i].fd, outbuf_pmap, 47974462Salfred outlen_pmap, 0, addr, 48074462Salfred (size_t)fdlist[i].asize) != 48174462Salfred outlen_pmap) { 48274462Salfred warnx("clnt_bcast: " 48374462Salfred "Cannot send broadcast packet"); 48474462Salfred stat = RPC_CANTSEND; 48574462Salfred continue; 48674462Salfred } 48774462Salfred } 48874462Salfred#ifdef RPC_DEBUG 48974462Salfred fprintf(stderr, "PMAP Broadcast packet " 49074462Salfred "sent for %s\n", 49174462Salfred fdlist[i].nconf->nc_netid); 49274462Salfred#endif 49374462Salfred#endif /* PORTMAP */ 49474462Salfred } 49574462Salfred /* End for sending all packets on this transport */ 49674462Salfred } /* End for sending on all transports */ 49774462Salfred 49874462Salfred if (eachresult == NULL) { 49974462Salfred stat = RPC_SUCCESS; 50074462Salfred goto done_broad; 50174462Salfred } 50274462Salfred 50374462Salfred /* 50474462Salfred * Get all the replies from these broadcast requests 50574462Salfred */ 50674462Salfred recv_again: 50774462Salfred 50874462Salfred switch (pollretval = _poll(pfd, fdlistno, msec)) { 50974462Salfred case 0: /* timed out */ 51074462Salfred stat = RPC_TIMEDOUT; 51174462Salfred continue; 51274462Salfred case -1: /* some kind of error - we ignore it */ 51374462Salfred goto recv_again; 51474462Salfred } /* end of poll results switch */ 51574462Salfred 51674462Salfred for (i = fds_found = 0; 51774462Salfred i < fdlistno && fds_found < pollretval; i++) { 51874462Salfred bool_t done = FALSE; 51974462Salfred 52074462Salfred if (pfd[i].revents == 0) 52174462Salfred continue; 52274462Salfred else if (pfd[i].revents & POLLNVAL) { 52374462Salfred /* 52474462Salfred * Something bad has happened to this descri- 52574462Salfred * ptor. We can cause _poll() to ignore 52674462Salfred * it simply by using a negative fd. We do that 52774462Salfred * rather than compacting the pfd[] and fdlist[] 52874462Salfred * arrays. 52974462Salfred */ 53074462Salfred pfd[i].fd = -1; 53174462Salfred fds_found++; 53274462Salfred continue; 53374462Salfred } else 53474462Salfred fds_found++; 53574462Salfred#ifdef RPC_DEBUG 53674462Salfred fprintf(stderr, "response for %s\n", 53774462Salfred fdlist[i].nconf->nc_netid); 53874462Salfred#endif 53974462Salfred try_again: 54074462Salfred inlen = _recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize, 54174462Salfred 0, (struct sockaddr *)(void *)&fdlist[i].raddr, 54274462Salfred &fdlist[i].asize); 54374462Salfred if (inlen < 0) { 54474462Salfred if (errno == EINTR) 54574462Salfred goto try_again; 54674462Salfred warnx("clnt_bcast: Cannot receive reply to " 54774462Salfred "broadcast"); 54874462Salfred stat = RPC_CANTRECV; 54974462Salfred continue; 55074462Salfred } 55174462Salfred if (inlen < sizeof (u_int32_t)) 55274462Salfred continue; /* Drop that and go ahead */ 55374462Salfred /* 55474462Salfred * see if reply transaction id matches sent id. 55574462Salfred * If so, decode the results. If return id is xid + 1 55674462Salfred * it was a PORTMAP reply 55774462Salfred */ 55874462Salfred if (*((u_int32_t *)(void *)(inbuf)) == 55974462Salfred *((u_int32_t *)(void *)(outbuf))) { 56074462Salfred pmap_reply_flag = 0; 56174462Salfred msg.acpted_rply.ar_verf = _null_auth; 56274462Salfred msg.acpted_rply.ar_results.where = 56374462Salfred (caddr_t)(void *)&bres; 56474462Salfred msg.acpted_rply.ar_results.proc = 56574462Salfred (xdrproc_t)xdr_rpcb_rmtcallres; 56674462Salfred#ifdef PORTMAP 56774462Salfred } else if (pmap_flag && 56874462Salfred *((u_int32_t *)(void *)(inbuf)) == 56974462Salfred *((u_int32_t *)(void *)(outbuf_pmap))) { 57074462Salfred pmap_reply_flag = 1; 57174462Salfred msg.acpted_rply.ar_verf = _null_auth; 57274462Salfred msg.acpted_rply.ar_results.where = 57374462Salfred (caddr_t)(void *)&bres_pmap; 57474462Salfred msg.acpted_rply.ar_results.proc = 57574462Salfred (xdrproc_t)xdr_rmtcallres; 57674462Salfred#endif /* PORTMAP */ 57774462Salfred } else 57874462Salfred continue; 57974462Salfred xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE); 58074462Salfred if (xdr_replymsg(xdrs, &msg)) { 58174462Salfred if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && 58274462Salfred (msg.acpted_rply.ar_stat == SUCCESS)) { 58374462Salfred struct netbuf taddr, *np; 58474462Salfred struct sockaddr_in *sin; 58574462Salfred 58674462Salfred#ifdef PORTMAP 58774462Salfred if (pmap_flag && pmap_reply_flag) { 58874462Salfred sin = (struct sockaddr_in *) 58974462Salfred (void *)&fdlist[i].raddr; 59074462Salfred sin->sin_port = 59174462Salfred htons((u_short)port); 59274462Salfred taddr.len = taddr.maxlen = 59374462Salfred fdlist[i].raddr.ss_len; 59474462Salfred taddr.buf = &fdlist[i].raddr; 59574462Salfred done = (*eachresult)(resultsp, 59674462Salfred &taddr, fdlist[i].nconf); 59774462Salfred } else { 59874462Salfred#endif /* PORTMAP */ 59974462Salfred#ifdef RPC_DEBUG 60074462Salfred fprintf(stderr, "uaddr %s\n", 60174462Salfred uaddrp); 60274462Salfred#endif 60374462Salfred np = uaddr2taddr( 60474462Salfred fdlist[i].nconf, uaddrp); 60574462Salfred done = (*eachresult)(resultsp, 60674462Salfred np, fdlist[i].nconf); 60774462Salfred free(np); 60874462Salfred#ifdef PORTMAP 60974462Salfred } 61074462Salfred#endif /* PORTMAP */ 61174462Salfred } 61274462Salfred /* otherwise, we just ignore the errors ... */ 61374462Salfred } 61474462Salfred /* else some kind of deserialization problem ... */ 61574462Salfred 61674462Salfred xdrs->x_op = XDR_FREE; 61774462Salfred msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; 61874462Salfred (void) xdr_replymsg(xdrs, &msg); 61974462Salfred (void) (*xresults)(xdrs, resultsp); 62074462Salfred XDR_DESTROY(xdrs); 62174462Salfred if (done) { 62274462Salfred stat = RPC_SUCCESS; 62374462Salfred goto done_broad; 62474462Salfred } else { 62574462Salfred goto recv_again; 62674462Salfred } 62774462Salfred } /* The recv for loop */ 62874462Salfred } /* The giant for loop */ 62974462Salfred 63074462Salfreddone_broad: 63174462Salfred if (inbuf) 63274462Salfred (void) free(inbuf); 63374462Salfred if (outbuf) 63474462Salfred (void) free(outbuf); 63574462Salfred#ifdef PORTMAP 63674462Salfred if (outbuf_pmap) 63774462Salfred (void) free(outbuf_pmap); 63874462Salfred#endif /* PORTMAP */ 63974462Salfred for (i = 0; i < fdlistno; i++) { 64074462Salfred (void)_close(fdlist[i].fd); 64174462Salfred __rpc_freebroadifs(&fdlist[i].nal); 64274462Salfred } 64374462Salfred AUTH_DESTROY(sys_auth); 64474462Salfred (void) __rpc_endconf(handle); 64574462Salfred 64674462Salfred return (stat); 64774462Salfred} 64874462Salfred 64974462Salfred 65074462Salfredenum clnt_stat 65174462Salfredrpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, 65274462Salfred eachresult, nettype) 65374462Salfred rpcprog_t prog; /* program number */ 65474462Salfred rpcvers_t vers; /* version number */ 65574462Salfred rpcproc_t proc; /* procedure number */ 65674462Salfred xdrproc_t xargs; /* xdr routine for args */ 65774462Salfred caddr_t argsp; /* pointer to args */ 65874462Salfred xdrproc_t xresults; /* xdr routine for results */ 65974462Salfred caddr_t resultsp; /* pointer to results */ 66074462Salfred resultproc_t eachresult; /* call with each result obtained */ 66174462Salfred const char *nettype; /* transport type */ 66274462Salfred{ 66374462Salfred enum clnt_stat dummy; 66474462Salfred 66574462Salfred dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp, 66674462Salfred xresults, resultsp, eachresult, 66774462Salfred INITTIME, WAITTIME, nettype); 66874462Salfred return (dummy); 66974462Salfred} 670