#include <netdb.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
+#include <sys/fcntl.h>
#include <errno.h>
#ifdef _LIBC
socklen_t len = sizeof (struct sockaddr_in);
char rpcdata [1024], servdata [1024];
struct rpcent rpcbuf, *rpcp;
- struct servent servbuf, *servp;
+ struct servent servbuf, *servp = NULL;
int sock, ret;
const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp";
}
}
- __bzero ((char *) &addr, sizeof (addr));
+ memset (&addr, 0, sizeof (addr));
addr.sin_family = AF_INET;
ret = getrpcbynumber_r (number, &rpcbuf, rpcdata, sizeof rpcdata,
}
else
{
- if (bindresvport (sock, &addr))
- {
addr.sin_port = 0;
if (bind (sock, (struct sockaddr *) &addr, len) < 0)
{
(void) __close (sock);
sock = -1;
}
- }
+ }
+
+ if (sock >= 0)
+ {
+ /* This socket might be shared among multiple processes
+ * if mountd is run multi-threaded. So it is safest to
+ * make it non-blocking, else all threads might wake
+ * one will get the data, and the others will block
+ * indefinitely.
+ * In all cases, transaction on this socket are atomic
+ * (accept for TCP, packet-read and packet-write for UDP)
+ * so O_NONBLOCK will not confuse unprepared code causing
+ * it to corrupt messages.
+ * It generally safest to have O_NONBLOCK when doing an accept
+ * as if we get a RST after the SYN and before accept runs,
+ * we can block despite being told there was an acceptable
+ * connection.
+ */
+ int flags;
+ if ((flags = fcntl(sock, F_GETFL)) < 0)
+ {
+ perror (_("svc_socket: can't get socket flags"));
+ (void) __close (sock);
+ sock = -1;
+ }
+ else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
+ {
+ perror (_("svc_socket: can't set socket flags"));
+ (void) __close (sock);
+ sock = -1;
+ }
}
return sock;
int
svcudp_socket (u_long number, int reuse)
{
- return svc_socket (number, SOCK_DGRAM, IPPROTO_UDP, reuse);
+ return svc_socket (number, SOCK_DGRAM, IPPROTO_UDP, 0);
}
#ifdef TEST