diff options
Diffstat (limited to 'meta')
| -rw-r--r-- | meta/recipes-extended/libtirpc/libtirpc/0001-Add-missing-rwlock_unlocks-in-xprt_register.patch | 62 | ||||
| -rw-r--r-- | meta/recipes-extended/libtirpc/libtirpc/Use-netbsd-queue.h.patch | 1579 | ||||
| -rw-r--r-- | meta/recipes-extended/libtirpc/libtirpc/remove-des-functionality.patch | 144 | ||||
| -rw-r--r-- | meta/recipes-extended/libtirpc/libtirpc/remove-des-uclibc.patch | 38 | ||||
| -rw-r--r-- | meta/recipes-extended/libtirpc/libtirpc_1.0.1.bb (renamed from meta/recipes-extended/libtirpc/libtirpc_0.2.5.bb) | 11 |
5 files changed, 1793 insertions, 41 deletions
diff --git a/meta/recipes-extended/libtirpc/libtirpc/0001-Add-missing-rwlock_unlocks-in-xprt_register.patch b/meta/recipes-extended/libtirpc/libtirpc/0001-Add-missing-rwlock_unlocks-in-xprt_register.patch new file mode 100644 index 0000000000..50613ba312 --- /dev/null +++ b/meta/recipes-extended/libtirpc/libtirpc/0001-Add-missing-rwlock_unlocks-in-xprt_register.patch @@ -0,0 +1,62 @@ +Subject: [PATCH] Add missing rwlock_unlocks in xprt_register + +It looks like in b2c9430f46c4ac848957fb8adaac176a3f6ac03f when svc_run +switched to poll, an early return was added, but the rwlock was not +unlocked. + +I observed that rpcbind built against libtirpc-1.0.1 would handle only +one request before hanging, and tracked it down to a missing +rwlock_unlock here. + +Fixes: b2c9430f46c4 ('Use poll() instead of select() in svc_run()') + +Upstream-Status: Backport + +Signed-off-by: Michael Forney <mforney@mforney.org> +Signed-off-by: Steve Dickson <steved@redhat.com> +Signed-off-by: Maxin B. John <maxin.john@intel.com> +--- + src/svc.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/svc.c b/src/svc.c +index 9c41445..b59467b 100644 +--- a/src/svc.c ++++ b/src/svc.c +@@ -99,7 +99,7 @@ xprt_register (xprt) + { + __svc_xports = (SVCXPRT **) calloc (_rpc_dtablesize(), sizeof (SVCXPRT *)); + if (__svc_xports == NULL) +- return; ++ goto unlock; + } + if (sock < _rpc_dtablesize()) + { +@@ -120,14 +120,14 @@ xprt_register (xprt) + svc_pollfd[i].fd = sock; + svc_pollfd[i].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); +- return; ++ goto unlock; + } + + new_svc_pollfd = (struct pollfd *) realloc (svc_pollfd, + sizeof (struct pollfd) + * (svc_max_pollfd + 1)); + if (new_svc_pollfd == NULL) /* Out of memory */ +- return; ++ goto unlock; + svc_pollfd = new_svc_pollfd; + ++svc_max_pollfd; + +@@ -135,6 +135,7 @@ xprt_register (xprt) + svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); + } ++unlock: + rwlock_unlock (&svc_fd_lock); + } + +-- +2.5.3 + diff --git a/meta/recipes-extended/libtirpc/libtirpc/Use-netbsd-queue.h.patch b/meta/recipes-extended/libtirpc/libtirpc/Use-netbsd-queue.h.patch new file mode 100644 index 0000000000..21c6c53a85 --- /dev/null +++ b/meta/recipes-extended/libtirpc/libtirpc/Use-netbsd-queue.h.patch @@ -0,0 +1,1579 @@ +musl does not provide sys/queue.h implementation. Borrow queue.h from +the NetBSD project +http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/queue.h?rev=1.68 + +Upstream-Status: Inappropriate [musl specific] + +Signed-off-by: Jörg Krause <joerg.krause@embedded.rocks> +Signed-off-by: Maxin B. John <maxin.john@intel.com> +--- +diff -Naur libtirpc-1.0.1-orig/src/clnt_bcast.c libtirpc-1.0.1/src/clnt_bcast.c +--- libtirpc-1.0.1-orig/src/clnt_bcast.c 2015-10-30 17:15:14.000000000 +0200 ++++ libtirpc-1.0.1/src/clnt_bcast.c 2015-12-21 17:03:52.066008311 +0200 +@@ -40,7 +40,6 @@ + */ + #include <sys/socket.h> + #include <sys/types.h> +-#include <sys/queue.h> + + #include <net/if.h> + #include <netinet/in.h> +@@ -62,6 +61,7 @@ + #include <err.h> + #include <string.h> + ++#include "queue.h" + #include "rpc_com.h" + #include "debug.h" + +diff -Naur libtirpc-1.0.1-orig/src/clnt_bcast.c.orig libtirpc-1.0.1/src/clnt_bcast.c.orig +--- libtirpc-1.0.1-orig/src/clnt_bcast.c.orig 1970-01-01 02:00:00.000000000 +0200 ++++ libtirpc-1.0.1/src/clnt_bcast.c.orig 2015-10-30 17:15:14.000000000 +0200 +@@ -0,0 +1,697 @@ ++/* ++ * Copyright (c) 2009, Sun Microsystems, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * - Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the following disclaimer. ++ * - Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * - Neither the name of Sun Microsystems, Inc. nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++/* ++ * Copyright (c) 1986-1991 by Sun Microsystems Inc. ++ */ ++ ++/* ++ * clnt_bcast.c ++ * Client interface to broadcast service. ++ * ++ * Copyright (C) 1988, Sun Microsystems, Inc. ++ * ++ * The following is kludged-up support for simple rpc broadcasts. ++ * Someday a large, complicated system will replace these routines. ++ */ ++#include <sys/socket.h> ++#include <sys/types.h> ++#include <sys/queue.h> ++ ++#include <net/if.h> ++#include <netinet/in.h> ++#include <ifaddrs.h> ++#include <poll.h> ++#include <rpc/rpc.h> ++#ifdef PORTMAP ++#include <rpc/pmap_prot.h> ++#include <rpc/pmap_clnt.h> ++#include <rpc/pmap_rmt.h> ++#endif /* PORTMAP */ ++#include <rpc/nettype.h> ++#include <arpa/inet.h> ++#include <stdio.h> ++#include <errno.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <netdb.h> ++#include <err.h> ++#include <string.h> ++ ++#include "rpc_com.h" ++#include "debug.h" ++ ++#define MAXBCAST 20 /* Max no of broadcasting transports */ ++#define INITTIME 4000 /* Time to wait initially */ ++#define WAITTIME 8000 /* Maximum time to wait */ ++ ++# define POLLRDNORM 0x040 /* Normal data may be read. */ ++# define POLLRDBAND 0x080 /* Priority data may be read. */ ++ ++ ++ ++/* ++ * If nettype is NULL, it broadcasts on all the available ++ * datagram_n transports. May potentially lead to broadacst storms ++ * and hence should be used with caution, care and courage. ++ * ++ * The current parameter xdr packet size is limited by the max tsdu ++ * size of the transport. If the max tsdu size of any transport is ++ * smaller than the parameter xdr packet, then broadcast is not ++ * sent on that transport. ++ * ++ * Also, the packet size should be less the packet size of ++ * the data link layer (for ethernet it is 1400 bytes). There is ++ * no easy way to find out the max size of the data link layer and ++ * we are assuming that the args would be smaller than that. ++ * ++ * The result size has to be smaller than the transport tsdu size. ++ * ++ * If PORTMAP has been defined, we send two packets for UDP, one for ++ * rpcbind and one for portmap. For those machines which support ++ * both rpcbind and portmap, it will cause them to reply twice, and ++ * also here it will get two responses ... inefficient and clumsy. ++ */ ++ ++#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) ++ ++#define TAILQ_FIRST(head) ((head)->tqh_first) ++ ++ ++struct broadif { ++ int index; ++ struct sockaddr_storage broadaddr; ++ TAILQ_ENTRY(broadif) link; ++}; ++ ++typedef TAILQ_HEAD(, broadif) broadlist_t; ++ ++int __rpc_getbroadifs(int, int, int, broadlist_t *); ++void __rpc_freebroadifs(broadlist_t *); ++int __rpc_broadenable(int, int, struct broadif *); ++ ++int __rpc_lowvers = 0; ++ ++int ++__rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list) ++{ ++ int count = 0; ++ struct broadif *bip; ++ struct ifaddrs *ifap, *ifp; ++#ifdef INET6 ++ struct sockaddr_in6 *sin6; ++#endif ++ struct sockaddr_in *sin; ++ struct addrinfo hints, *res; ++ ++ if (getifaddrs(&ifp) < 0) ++ return 0; ++ ++ memset(&hints, 0, sizeof hints); ++ ++ hints.ai_family = af; ++ hints.ai_protocol = proto; ++ hints.ai_socktype = socktype; ++ ++ if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0) ++ return 0; ++ ++ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { ++ if (ifap->ifa_addr == NULL || /* happens for eg tuntap devices */ ++ ifap->ifa_addr->sa_family != af || ++ !(ifap->ifa_flags & IFF_UP)) ++ continue; ++ bip = (struct broadif *)malloc(sizeof *bip); ++ if (bip == NULL) ++ break; ++ bip->index = if_nametoindex(ifap->ifa_name); ++ if ( ++#ifdef INET6 ++ af != AF_INET6 && ++#endif ++ (ifap->ifa_flags & IFF_BROADCAST) && ++ ifap->ifa_broadaddr) { ++ /* memcpy(&bip->broadaddr, ifap->ifa_broadaddr, ++ (size_t)ifap->ifa_broadaddr->sa_len);*/ ++ memcpy(&bip->broadaddr, ifap->ifa_broadaddr, ++ sizeof(bip->broadaddr)); ++ sin = (struct sockaddr_in *)(void *)&bip->broadaddr; ++ sin->sin_port = ++ ((struct sockaddr_in *) ++ (void *)res->ai_addr)->sin_port; ++ } else ++#ifdef INET6 ++ if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) { ++ sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr; ++ inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr); ++ sin6->sin6_family = af; ++ sin6->sin6_port = ++ ((struct sockaddr_in6 *) ++ (void *)res->ai_addr)->sin6_port; ++ sin6->sin6_scope_id = bip->index; ++ } else ++#endif ++ { ++ free(bip); ++ continue; ++ } ++ TAILQ_INSERT_TAIL(list, bip, link); ++ count++; ++ } ++ freeifaddrs(ifp); ++ freeaddrinfo(res); ++ ++ return count; ++} ++ ++void ++__rpc_freebroadifs(broadlist_t *list) ++{ ++ struct broadif *bip, *next; ++ ++ bip = TAILQ_FIRST(list); ++ ++ while (bip != NULL) { ++ next = TAILQ_NEXT(bip, link); ++ free(bip); ++ bip = next; ++ } ++} ++ ++int ++/*ARGSUSED*/ ++__rpc_broadenable(int af, int s, struct broadif *bip) ++{ ++ int o = 1; ++ ++#if 0 ++ if (af == AF_INET6) { ++ fprintf(stderr, "set v6 multicast if to %d\n", bip->index); ++ if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index, ++ sizeof bip->index) < 0) ++ return -1; ++ } else ++#endif ++ if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++/* ++ * Some rpcbind implementations use an IPv6 socket to serve both ++ * IPv4 and IPv6 messages, but neglect to check for the caller's ++ * address family when sending broadcast replies. These rpcbind ++ * implementations return an IPv6 address in reply to an IPv4 ++ * broadcast. We can either ignore them, or try to patch them up. ++ */ ++static struct netbuf * ++__ipv6v4_fixup(struct sockaddr_storage *ss, const char *uaddr) ++{ ++ struct sockaddr_in sin; ++ struct netbuf *np; ++ ++ /* ss is the remote rpcbind server's address */ ++ if (ss->ss_family != AF_INET) ++ return NULL; ++ memcpy(&sin, ss, sizeof(sin)); ++ ++ np = __rpc_uaddr2taddr_af(AF_INET6, uaddr); ++ if (np == NULL) ++ return NULL; ++ ++ /* Overwrite the port with that of the service we ++ * wanted to talk to. */ ++ sin.sin_port = ((struct sockaddr_in6 *) np)->sin6_port; ++ ++ /* We know netbuf holds a sockaddr_in6, so it can easily ++ * hold a sockaddr_in as well. */ ++ memcpy(np->buf, &sin, sizeof(sin)); ++ np->len = sizeof(sin); ++ ++ return np; ++} ++ ++enum clnt_stat ++rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, ++ eachresult, inittime, waittime, nettype) ++ rpcprog_t prog; /* program number */ ++ rpcvers_t vers; /* version number */ ++ rpcproc_t proc; /* procedure number */ ++ xdrproc_t xargs; /* xdr routine for args */ ++ caddr_t argsp; /* pointer to args */ ++ xdrproc_t xresults; /* xdr routine for results */ ++ caddr_t resultsp; /* pointer to results */ ++ resultproc_t eachresult; /* call with each result obtained */ ++ int inittime; /* how long to wait initially */ ++ int waittime; /* maximum time to wait */ ++ const char *nettype; /* transport type */ ++{ ++ enum clnt_stat stat = RPC_SUCCESS; /* Return status */ ++ XDR xdr_stream; /* XDR stream */ ++ XDR *xdrs = &xdr_stream; ++ struct rpc_msg msg; /* RPC message */ ++ struct timeval t; ++ char *outbuf = NULL; /* Broadcast msg buffer */ ++ char *inbuf = NULL; /* Reply buf */ ++ int inlen; ++ u_int maxbufsize = 0; ++ AUTH *sys_auth = authunix_create_default(); ++ int i; ++ void *handle; ++ char uaddress[1024]; /* A self imposed limit */ ++ char *uaddrp = uaddress; ++ int pmap_reply_flag; /* reply recvd from PORTMAP */ ++ /* An array of all the suitable broadcast transports */ ++ struct { ++ int fd; /* File descriptor */ ++ int af; ++ int proto; ++ struct netconfig *nconf; /* Netconfig structure */ ++ u_int asize; /* Size of the addr buf */ ++ u_int dsize; /* Size of the data buf */ ++ struct sockaddr_storage raddr; /* Remote address */ ++ broadlist_t nal; ++ } fdlist[MAXBCAST]; ++ struct pollfd pfd[MAXBCAST]; ++ size_t fdlistno = 0; ++ struct r_rpcb_rmtcallargs barg; /* Remote arguments */ ++ struct r_rpcb_rmtcallres bres; /* Remote results */ ++ size_t outlen; ++ struct netconfig *nconf; ++ int msec; ++ int pollretval; ++ int fds_found; ++ ++#ifdef PORTMAP ++ size_t outlen_pmap = 0; ++ u_long port; /* Remote port number */ ++ int pmap_flag = 0; /* UDP exists ? */ ++ char *outbuf_pmap = NULL; ++ struct rmtcallargs barg_pmap; /* Remote arguments */ ++ struct rmtcallres bres_pmap; /* Remote results */ ++ u_int udpbufsz = 0; ++#endif /* PORTMAP */ ++ ++ if (sys_auth == NULL) { ++ return (RPC_SYSTEMERROR); ++ } ++ /* ++ * initialization: create a fd, a broadcast address, and send the ++ * request on the broadcast transport. ++ * Listen on all of them and on replies, call the user supplied ++ * function. ++ */ ++ ++ if (nettype == NULL) ++ nettype = "datagram_n"; ++ if ((handle = __rpc_setconf(nettype)) == NULL) { ++ return (RPC_UNKNOWNPROTO); ++ } ++ while ((nconf = __rpc_getconf(handle)) != NULL) { ++ int fd; ++ struct __rpc_sockinfo si; ++ ++ if (nconf->nc_semantics != NC_TPI_CLTS) ++ continue; ++ if (fdlistno >= MAXBCAST) ++ break; /* No more slots available */ ++ if (!__rpc_nconf2sockinfo(nconf, &si)) ++ continue; ++ ++ TAILQ_INIT(&fdlist[fdlistno].nal); ++ if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype, ++ &fdlist[fdlistno].nal) == 0) ++ continue; ++ ++ fd = socket(si.si_af, si.si_socktype, si.si_proto); ++ if (fd < 0) { ++ stat = RPC_CANTSEND; ++ continue; ++ } ++ fdlist[fdlistno].af = si.si_af; ++ fdlist[fdlistno].proto = si.si_proto; ++ fdlist[fdlistno].fd = fd; ++ fdlist[fdlistno].nconf = nconf; ++ fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af); ++ pfd[fdlistno].events = POLLIN | POLLPRI | ++ POLLRDNORM | POLLRDBAND; ++ pfd[fdlistno].fd = fdlist[fdlistno].fd = fd; ++ fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto, ++ 0); ++ ++ if (maxbufsize <= fdlist[fdlistno].dsize) ++ maxbufsize = fdlist[fdlistno].dsize; ++ ++#ifdef PORTMAP ++ if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) { ++ udpbufsz = fdlist[fdlistno].dsize; ++ if ((outbuf_pmap = malloc(udpbufsz)) == NULL) { ++ close(fd); ++ stat = RPC_SYSTEMERROR; ++ goto done_broad; ++ } ++ pmap_flag = 1; ++ } ++#endif /* PORTMAP */ ++ fdlistno++; ++ } ++ ++ if (fdlistno == 0) { ++ if (stat == RPC_SUCCESS) ++ stat = RPC_UNKNOWNPROTO; ++ goto done_broad; ++ } ++ if (maxbufsize == 0) { ++ if (stat == RPC_SUCCESS) ++ stat = RPC_CANTSEND; ++ goto done_broad; ++ } ++ inbuf = malloc(maxbufsize); ++ outbuf = malloc(maxbufsize); ++ if ((inbuf == NULL) || (outbuf == NULL)) { ++ stat = RPC_SYSTEMERROR; ++ goto done_broad; ++ } ++ ++ /* Serialize all the arguments which have to be sent */ ++ (void) gettimeofday(&t, NULL); ++ msg.rm_xid = __RPC_GETXID(&t); ++ msg.rm_direction = CALL; ++ msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; ++ msg.rm_call.cb_prog = RPCBPROG; ++ msg.rm_call.cb_vers = RPCBVERS; ++ msg.rm_call.cb_proc = RPCBPROC_CALLIT; ++ barg.prog = prog; ++ barg.vers = vers; ++ barg.proc = proc; ++ barg.args.args_val = argsp; ++ barg.xdr_args = xargs; ++ bres.addr = uaddrp; ++ bres.results.results_val = resultsp; ++ bres.xdr_res = xresults; ++ msg.rm_call.cb_cred = sys_auth->ah_cred; ++ msg.rm_call.cb_verf = sys_auth->ah_verf; ++ xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE); ++ if ((!xdr_callmsg(xdrs, &msg)) || ++ (!xdr_rpcb_rmtcallargs(xdrs, ++ (struct rpcb_rmtcallargs *)(void *)&barg))) { ++ stat = RPC_CANTENCODEARGS; ++ goto done_broad; ++ } ++ outlen = xdr_getpos(xdrs); ++ xdr_destroy(xdrs); ++ ++#ifdef PORTMAP ++ /* Prepare the packet for version 2 PORTMAP */ ++ if (pmap_flag) { ++ msg.rm_xid++; /* One way to distinguish */ ++ msg.rm_call.cb_prog = PMAPPROG; ++ msg.rm_call.cb_vers = PMAPVERS; ++ msg.rm_call.cb_proc = PMAPPROC_CALLIT; ++ barg_pmap.prog = prog; ++ barg_pmap.vers = vers; ++ barg_pmap.proc = proc; ++ barg_pmap.args_ptr = argsp; ++ barg_pmap.xdr_args = xargs; ++ bres_pmap.port_ptr = &port; ++ bres_pmap.xdr_results = xresults; ++ bres_pmap.results_ptr = resultsp; ++ xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE); ++ if ((! xdr_callmsg(xdrs, &msg)) || ++ (! xdr_rmtcall_args(xdrs, &barg_pmap))) { ++ stat = RPC_CANTENCODEARGS; ++ goto done_broad; ++ } ++ outlen_pmap = xdr_getpos(xdrs); ++ xdr_destroy(xdrs); ++ } ++#endif /* PORTMAP */ ++ ++ /* ++ * Basic loop: broadcast the packets to transports which ++ * support data packets of size such that one can encode ++ * all the arguments. ++ * Wait a while for response(s). ++ * The response timeout grows larger per iteration. ++ */ ++ for (msec = inittime; msec <= waittime; msec += msec) { ++ struct broadif *bip; ++ ++ /* Broadcast all the packets now */ ++ for (i = 0; i < fdlistno; i++) { ++ if (fdlist[i].dsize < outlen) { ++ stat = RPC_CANTSEND; ++ continue; ++ } ++ for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL; ++ bip = TAILQ_NEXT(bip, link)) { ++ void *addr; ++ ++ addr = &bip->broadaddr; ++ ++ __rpc_broadenable(fdlist[i].af, fdlist[i].fd, ++ bip); ++ ++ /* ++ * Only use version 3 if lowvers is not set ++ */ ++ ++ if (!__rpc_lowvers) ++ if (sendto(fdlist[i].fd, outbuf, ++ outlen, 0, (struct sockaddr*)addr, ++ (size_t)fdlist[i].asize) != ++ outlen) { ++ LIBTIRPC_DEBUG(1, ++ ("rpc_broadcast_exp: sendto failed: errno %d", errno)); ++ warnx("rpc_broadcast_exp: cannot send broadcast packet"); ++ stat = RPC_CANTSEND; ++ continue; ++ }; ++ if (!__rpc_lowvers) ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: Broadcast packet sent for %s\n", ++ fdlist[i].nconf->nc_netid)); ++#ifdef PORTMAP ++ /* ++ * Send the version 2 packet also ++ * for UDP/IP ++ */ ++ if (pmap_flag && ++ fdlist[i].proto == IPPROTO_UDP) { ++ if (sendto(fdlist[i].fd, outbuf_pmap, ++ outlen_pmap, 0, addr, ++ (size_t)fdlist[i].asize) != ++ outlen_pmap) { ++ warnx("clnt_bcast: " ++ "Cannot send broadcast packet"); ++ stat = RPC_CANTSEND; ++ continue; ++ } ++ } ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: PMAP Broadcast packet sent for %s\n", ++ fdlist[i].nconf->nc_netid)); ++#endif /* PORTMAP */ ++ } ++ /* End for sending all packets on this transport */ ++ } /* End for sending on all transports */ ++ ++ if (eachresult == NULL) { ++ stat = RPC_SUCCESS; ++ goto done_broad; ++ } ++ ++ /* ++ * Get all the replies from these broadcast requests ++ */ ++ recv_again: ++ ++ switch (pollretval = poll(pfd, fdlistno, msec)) { ++ case 0: /* timed out */ ++ stat = RPC_TIMEDOUT; ++ continue; ++ case -1: /* some kind of error - we ignore it */ ++ goto recv_again; ++ } /* end of poll results switch */ ++ ++ for (i = fds_found = 0; ++ i < fdlistno && fds_found < pollretval; i++) { ++ bool_t done = FALSE; ++ ++ if (pfd[i].revents == 0) ++ continue; ++ else if (pfd[i].revents & POLLNVAL) { ++ /* ++ * Something bad has happened to this descri- ++ * ptor. We can cause _poll() to ignore ++ * it simply by using a negative fd. We do that ++ * rather than compacting the pfd[] and fdlist[] ++ * arrays. ++ */ ++ pfd[i].fd = -1; ++ fds_found++; ++ continue; ++ } else ++ fds_found++; ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: response for %s\n", ++ fdlist[i].nconf->nc_netid)); ++ try_again: ++ inlen = recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize, ++ 0, (struct sockaddr *)(void *)&fdlist[i].raddr, ++ &fdlist[i].asize); ++ if (inlen < 0) { ++ if (errno == EINTR) ++ goto try_again; ++ warnx("clnt_bcast: Cannot receive reply to " ++ "broadcast"); ++ stat = RPC_CANTRECV; ++ continue; ++ } ++ if (inlen < sizeof (u_int32_t)) ++ continue; /* Drop that and go ahead */ ++ /* ++ * see if reply transaction id matches sent id. ++ * If so, decode the results. If return id is xid + 1 ++ * it was a PORTMAP reply ++ */ ++ if (*((u_int32_t *)(void *)(inbuf)) == ++ *((u_int32_t *)(void *)(outbuf))) { ++ pmap_reply_flag = 0; ++ msg.acpted_rply.ar_verf = _null_auth; ++ msg.acpted_rply.ar_results.where = ++ (caddr_t)(void *)&bres; ++ msg.acpted_rply.ar_results.proc = ++ (xdrproc_t)xdr_rpcb_rmtcallres; ++#ifdef PORTMAP ++ } else if (pmap_flag && ++ *((u_int32_t *)(void *)(inbuf)) == ++ *((u_int32_t *)(void *)(outbuf_pmap))) { ++ pmap_reply_flag = 1; ++ msg.acpted_rply.ar_verf = _null_auth; ++ msg.acpted_rply.ar_results.where = ++ (caddr_t)(void *)&bres_pmap; ++ msg.acpted_rply.ar_results.proc = ++ (xdrproc_t)xdr_rmtcallres; ++#endif /* PORTMAP */ ++ } else ++ continue; ++ xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE); ++ if (xdr_replymsg(xdrs, &msg)) { ++ if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && ++ (msg.acpted_rply.ar_stat == SUCCESS)) { ++ struct netbuf *np; ++#ifdef PORTMAP ++ struct netbuf taddr; ++ struct sockaddr_in sin; ++ ++ if (pmap_flag && pmap_reply_flag) { ++ memcpy(&sin, &fdlist[i].raddr, sizeof(sin)); ++ sin.sin_port = htons((u_short)port); ++ memcpy(&fdlist[i].raddr, &sin, sizeof(sin)); ++ taddr.len = taddr.maxlen = ++ sizeof(fdlist[i].raddr); ++ taddr.buf = &fdlist[i].raddr; ++ done = (*eachresult)(resultsp, ++ &taddr, fdlist[i].nconf); ++ } else { ++#endif /* PORTMAP */ ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: uaddr %s\n", uaddrp)); ++ np = uaddr2taddr( ++ fdlist[i].nconf, uaddrp); ++ /* Some misguided rpcbind implemenations ++ * seem to return an IPv6 uaddr in IPv4 ++ * responses. */ ++ if (np == NULL) ++ np = __ipv6v4_fixup( ++ &fdlist[i].raddr, ++ uaddrp); ++ if (np != NULL) { ++ done = (*eachresult)(resultsp, ++ np, fdlist[i].nconf); ++ free(np); ++ } ++#ifdef PORTMAP ++ } ++#endif /* PORTMAP */ ++ } ++ /* otherwise, we just ignore the errors ... */ ++ } ++ /* else some kind of deserialization problem ... */ ++ ++ xdrs->x_op = XDR_FREE; ++ msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; ++ (void) xdr_replymsg(xdrs, &msg); ++ (void) (*xresults)(xdrs, resultsp); ++ XDR_DESTROY(xdrs); ++ if (done) { ++ stat = RPC_SUCCESS; ++ goto done_broad; ++ } else { ++ goto recv_again; ++ } ++ } /* The recv for loop */ ++ } /* The giant for loop */ ++ ++done_broad: ++ if (inbuf) ++ (void) free(inbuf); ++ if (outbuf) ++ (void) free(outbuf); ++#ifdef PORTMAP ++ if (outbuf_pmap) ++ (void) free(outbuf_pmap); ++#endif /* PORTMAP */ ++ for (i = 0; i < fdlistno; i++) { ++ (void)close(fdlist[i].fd); ++ __rpc_freebroadifs(&fdlist[i].nal); ++ } ++ AUTH_DESTROY(sys_auth); ++ (void) __rpc_endconf(handle); ++ ++ return (stat); ++} ++ ++ ++enum clnt_stat ++rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, ++ eachresult, nettype) ++ rpcprog_t prog; /* program number */ ++ rpcvers_t vers; /* version number */ ++ rpcproc_t proc; /* procedure number */ ++ xdrproc_t xargs; /* xdr routine for args */ ++ caddr_t argsp; /* pointer to args */ ++ xdrproc_t xresults; /* xdr routine for results */ ++ caddr_t resultsp; /* pointer to results */ ++ resultproc_t eachresult; /* call with each result obtained */ ++ const char *nettype; /* transport type */ ++{ ++ enum clnt_stat dummy; ++ ++ dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp, ++ xresults, resultsp, eachresult, ++ INITTIME, WAITTIME, nettype); ++ return (dummy); ++} +diff -Naur libtirpc-1.0.1-orig/tirpc/queue.h libtirpc-1.0.1/tirpc/queue.h +--- libtirpc-1.0.1-orig/tirpc/queue.h 1970-01-01 02:00:00.000000000 +0200 ++++ libtirpc-1.0.1/tirpc/queue.h 2015-12-21 17:02:44.427853905 +0200 +@@ -0,0 +1,846 @@ ++/* $NetBSD: queue.h,v 1.68 2014/11/19 08:10:01 uebayasi Exp $ */ ++ ++/* ++ * Copyright (c) 1991, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)queue.h 8.5 (Berkeley) 8/20/94 ++ */ ++ ++#ifndef _SYS_QUEUE_H_ ++#define _SYS_QUEUE_H_ ++ ++/* ++ * This file defines five types of data structures: singly-linked lists, ++ * lists, simple queues, tail queues, and circular queues. ++ * ++ * A singly-linked list is headed by a single forward pointer. The ++ * elements are singly linked for minimum space and pointer manipulation ++ * overhead at the expense of O(n) removal for arbitrary elements. New ++ * elements can be added to the list after an existing element or at the ++ * head of the list. Elements being removed from the head of the list ++ * should use the explicit macro for this purpose for optimum ++ * efficiency. A singly-linked list may only be traversed in the forward ++ * direction. Singly-linked lists are ideal for applications with large ++ * datasets and few or no removals or for implementing a LIFO queue. ++ * ++ * A list is headed by a single forward pointer (or an array of forward ++ * pointers for a hash table header). The elements are doubly linked ++ * so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before ++ * or after an existing element or at the head of the list. A list ++ * may only be traversed in the forward direction. ++ * ++ * A simple queue is headed by a pair of pointers, one the head of the ++ * list and the other to the tail of the list. The elements are singly ++ * linked to save space, so elements can only be removed from the ++ * head of the list. New elements can be added to the list after ++ * an existing element, at the head of the list, or at the end of the ++ * list. A simple queue may only be traversed in the forward direction. ++ * ++ * A tail queue is headed by a pair of pointers, one to the head of the ++ * list and the other to the tail of the list. The elements are doubly ++ * linked so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before or ++ * after an existing element, at the head of the list, or at the end of ++ * the list. A tail queue may be traversed in either direction. ++ * ++ * A circle queue is headed by a pair of pointers, one to the head of the ++ * list and the other to the tail of the list. The elements are doubly ++ * linked so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before or after ++ * an existing element, at the head of the list, or at the end of the list. ++ * A circle queue may be traversed in either direction, but has a more ++ * complex end of list detection. ++ * ++ * For details on the use of these macros, see the queue(3) manual page. ++ */ ++ ++/* ++ * Include the definition of NULL only on NetBSD because sys/null.h ++ * is not available elsewhere. This conditional makes the header ++ * portable and it can simply be dropped verbatim into any system. ++ * The caveat is that on other systems some other header ++ * must provide NULL before the macros can be used. ++ */ ++#ifdef __NetBSD__ ++#include <sys/null.h> ++#endif ++ ++#if defined(QUEUEDEBUG) ++# if defined(_KERNEL) ++# define QUEUEDEBUG_ABORT(...) panic(__VA_ARGS__) ++# else ++# include <err.h> ++# define QUEUEDEBUG_ABORT(...) err(1, __VA_ARGS__) ++# endif ++#endif ++ ++/* ++ * Singly-linked List definitions. ++ */ ++#define SLIST_HEAD(name, type) \ ++struct name { \ ++ struct type *slh_first; /* first element */ \ ++} ++ ++#define SLIST_HEAD_INITIALIZER(head) \ ++ { NULL } ++ ++#define SLIST_ENTRY(type) \ ++struct { \ ++ struct type *sle_next; /* next element */ \ ++} ++ ++/* ++ * Singly-linked List access methods. ++ */ ++#define SLIST_FIRST(head) ((head)->slh_first) ++#define SLIST_END(head) NULL ++#define SLIST_EMPTY(head) ((head)->slh_first == NULL) ++#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) ++ ++#define SLIST_FOREACH(var, head, field) \ ++ for((var) = (head)->slh_first; \ ++ (var) != SLIST_END(head); \ ++ (var) = (var)->field.sle_next) ++ ++#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ ++ for ((var) = SLIST_FIRST((head)); \ ++ (var) != SLIST_END(head) && \ ++ ((tvar) = SLIST_NEXT((var), field), 1); \ ++ (var) = (tvar)) ++ ++/* ++ * Singly-linked List functions. ++ */ ++#define SLIST_INIT(head) do { \ ++ (head)->slh_first = SLIST_END(head); \ ++} while (/*CONSTCOND*/0) ++ ++#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ ++ (elm)->field.sle_next = (slistelm)->field.sle_next; \ ++ (slistelm)->field.sle_next = (elm); \ ++} while (/*CONSTCOND*/0) ++ ++#define SLIST_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.sle_next = (head)->slh_first; \ ++ (head)->slh_first = (elm); \ ++} while (/*CONSTCOND*/0) ++ ++#define SLIST_REMOVE_AFTER(slistelm, field) do { \ ++ (slistelm)->field.sle_next = \ ++ SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \ ++} while (/*CONSTCOND*/0) ++ ++#define SLIST_REMOVE_HEAD(head, field) do { \ ++ (head)->slh_first = (head)->slh_first->field.sle_next; \ ++} while (/*CONSTCOND*/0) ++ ++#define SLIST_REMOVE(head, elm, type, field) do { \ ++ if ((head)->slh_first == (elm)) { \ ++ SLIST_REMOVE_HEAD((head), field); \ ++ } \ ++ else { \ ++ struct type *curelm = (head)->slh_first; \ ++ while(curelm->field.sle_next != (elm)) \ ++ curelm = curelm->field.sle_next; \ ++ curelm->field.sle_next = \ ++ curelm->field.sle_next->field.sle_next; \ ++ } \ ++} while (/*CONSTCOND*/0) ++ ++ ++/* ++ * List definitions. ++ */ ++#define LIST_HEAD(name, type) \ ++struct name { \ ++ struct type *lh_first; /* first element */ \ ++} ++ ++#define LIST_HEAD_INITIALIZER(head) \ ++ { NULL } ++ ++#define LIST_ENTRY(type) \ ++struct { \ ++ struct type *le_next; /* next element */ \ ++ struct type **le_prev; /* address of previous next element */ \ ++} ++ ++/* ++ * List access methods. ++ */ ++#define LIST_FIRST(head) ((head)->lh_first) ++#define LIST_END(head) NULL ++#define LIST_EMPTY(head) ((head)->lh_first == LIST_END(head)) ++#define LIST_NEXT(elm, field) ((elm)->field.le_next) ++ ++#define LIST_FOREACH(var, head, field) \ ++ for ((var) = ((head)->lh_first); \ ++ (var) != LIST_END(head); \ ++ (var) = ((var)->field.le_next)) ++ ++#define LIST_FOREACH_SAFE(var, head, field, tvar) \ ++ for ((var) = LIST_FIRST((head)); \ ++ (var) != LIST_END(head) && \ ++ ((tvar) = LIST_NEXT((var), field), 1); \ ++ (var) = (tvar)) ++ ++#define LIST_MOVE(head1, head2) do { \ ++ LIST_INIT((head2)); \ ++ if (!LIST_EMPTY((head1))) { \ ++ (head2)->lh_first = (head1)->lh_first; \ ++ LIST_INIT((head1)); \ ++ } \ ++} while (/*CONSTCOND*/0) ++ ++/* ++ * List functions. ++ */ ++#if defined(QUEUEDEBUG) ++#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ ++ if ((head)->lh_first && \ ++ (head)->lh_first->field.le_prev != &am |
