You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 0211-1301 USA */
#include <stdio.h>
#include <string.h>
# define __close(f) close ((f))
#endif
+int getservport(u_long number, const char *proto)
+{
+ char rpcdata[1024], servdata[1024];
+ struct rpcent rpcbuf, *rpcp;
+ struct servent servbuf, *servp = NULL;
+ int ret;
+
+ ret = getrpcbynumber_r(number, &rpcbuf, rpcdata, sizeof rpcdata,
+ &rpcp);
+ if (ret == 0 && rpcp != NULL) {
+ /* First try name. */
+ ret = getservbyname_r(rpcp->r_name, proto, &servbuf, servdata,
+ sizeof servdata, &servp);
+ if ((ret != 0 || servp == NULL) && rpcp->r_aliases) {
+ const char **a;
+
+ /* Then we try aliases. */
+ for (a = (const char **) rpcp->r_aliases; *a != NULL; a++) {
+ ret = getservbyname_r(*a, proto, &servbuf, servdata,
+ sizeof servdata, &servp);
+ if (ret == 0 && servp != NULL)
+ break;
+ }
+ }
+ }
+
+ if (ret == 0 && servp != NULL)
+ return ntohs(servp->s_port);
+
+ return 0;
+}
+
static int
svc_socket (u_long number, int type, int protocol, int reuse)
{
struct sockaddr_in addr;
socklen_t len = sizeof (struct sockaddr_in);
- char rpcdata [1024], servdata [1024];
- struct rpcent rpcbuf, *rpcp;
- 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;
+ addr.sin_port = htons(getservport(number, proto));
- ret = getrpcbynumber_r (number, &rpcbuf, rpcdata, sizeof rpcdata,
- &rpcp);
- if (ret == 0 && rpcp != NULL)
- {
- /* First try name. */
- ret = getservbyname_r (rpcp->r_name, proto, &servbuf, servdata,
- sizeof servdata, &servp);
- if ((ret != 0 || servp == NULL) && rpcp->r_aliases)
- {
- const char **a;
-
- /* Then we try aliases. */
- for (a = (const char **) rpcp->r_aliases; *a != NULL; a++)
- {
- ret = getservbyname_r (*a, proto, &servbuf, servdata,
- sizeof servdata, &servp);
- if (ret == 0 && servp != NULL)
- break;
- }
- }
- }
-
- if (ret == 0 && servp != NULL)
- {
- addr.sin_port = servp->s_port;
- if (bind (sock, (struct sockaddr *) &addr, len) < 0)
- {
- perror (_("svc_socket: bind problem"));
- (void) __close (sock);
- sock = -1;
- }
- }
- else
+ if (bind(sock, (struct sockaddr *) &addr, len) < 0)
{
- if (bindresvport (sock, &addr))
- {
- addr.sin_port = 0;
- if (bind (sock, (struct sockaddr *) &addr, len) < 0)
- {
- perror (_("svc_socket: bind problem"));
- (void) __close (sock);
- sock = -1;
- }
- }
+ perror (_("svc_socket: bind problem"));
+ (void) __close(sock);
+ sock = -1;
}
- if (sock >= 0 && protocol == IPPROTO_TCP)
+ if (sock >= 0)
{
- /* Make the TCP rendezvous socket non-block to avoid
- * problems with blocking in accept() after a spurious
- * wakeup from the kernel */
+ /* 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)
{
* Create and bind a UDP socket based on program number
*/
int
-svcudp_socket (u_long number, int reuse)
+svcudp_socket (u_long number)
{
- return svc_socket (number, SOCK_DGRAM, IPPROTO_UDP, reuse);
+ return svc_socket (number, SOCK_DGRAM, IPPROTO_UDP, FALSE);
}
#ifdef TEST
if (protocol == IPPROTO_TCP)
socket = svctcp_socket (number, reuse);
else
- socket = svcudp_socket (number, reuse);
+ socket = svcudp_socket (number);
if (socket < 0)
return 1;