X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fnfs%2Fsvc_socket.c;h=f44217a404821dcd059e8374531d3ac32c12d1fa;hp=ca323e6b9aa57c3251e854f5e98bf04b2c84d82a;hb=9bb85c5e8d2285f82367c75df5530a71a9a5a5f2;hpb=c5a48eb6e49e4c0203f7adf137ffeab29a5798e3 diff --git a/support/nfs/svc_socket.c b/support/nfs/svc_socket.c index ca323e6..f44217a 100644 --- a/support/nfs/svc_socket.c +++ b/support/nfs/svc_socket.c @@ -22,12 +22,12 @@ #include #include #include +#include #include #ifdef _LIBC # include #else -# include "config.h" # ifndef _ # define _(s) (s) # endif @@ -35,7 +35,6 @@ # define __close(f) close ((f)) #endif -#if !defined HAVE_SVCTCP_SOCKET || !defined HAVE_SVCUDP_SOCKET static int svc_socket (u_long number, int type, int protocol, int reuse) { @@ -43,7 +42,7 @@ svc_socket (u_long number, int type, int protocol, int reuse) 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"; @@ -65,7 +64,7 @@ svc_socket (u_long number, int type, int protocol, int reuse) } } - __bzero ((char *) &addr, sizeof (addr)); + memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; ret = getrpcbynumber_r (number, &rpcbuf, rpcdata, sizeof rpcdata, @@ -102,8 +101,6 @@ svc_socket (u_long number, int type, int protocol, int reuse) } else { - if (bindresvport (sock, &addr)) - { addr.sin_port = 0; if (bind (sock, (struct sockaddr *) &addr, len) < 0) { @@ -111,14 +108,42 @@ svc_socket (u_long number, int type, int protocol, int reuse) (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; } -#endif -#ifndef HAVE_SVCTCP_SOCKET /* * Create and bind a TCP socket based on program number */ @@ -127,18 +152,15 @@ svctcp_socket (u_long number, int reuse) { return svc_socket (number, SOCK_STREAM, IPPROTO_TCP, reuse); } -#endif -#ifndef HAVE_SVCUDP_SOCKET /* * Create and bind a UDP socket based on program number */ 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); } -#endif #ifdef TEST static int