Commit bbc98d9b authored by Mike Hibler's avatar Mike Hibler

Set the RCV and SND timeout values on accepted TCP sockets.

Should help prevent our TCP tmcd from "wedging".
parent d146ec1e
/* /*
* EMULAB-COPYRIGHT * EMULAB-COPYRIGHT
* Copyright (c) 2000-2004 University of Utah and the Flux Group. * Copyright (c) 2000-2004, 2006 University of Utah and the Flux Group.
* All rights reserved. * All rights reserved.
*/ */
...@@ -220,9 +220,9 @@ tmcd_client_sslinit(void) ...@@ -220,9 +220,9 @@ tmcd_client_sslinit(void)
* is static and local to the process. * is static and local to the process.
*/ */
int int
tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen) tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen, int ms)
{ {
int newsock, cc; int newsock, cc, err;
if ((newsock = accept(sock, addr, addrlen)) < 0) if ((newsock = accept(sock, addr, addrlen)) < 0)
return -1; return -1;
...@@ -233,6 +233,21 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen) ...@@ -233,6 +233,21 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen)
if (nousessl) if (nousessl)
return newsock; return newsock;
/*
* Set timeout values to keep us from hanging due to a
* malfunctioning or malicious client.
*/
if (ms > 0) {
struct timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * 1000;
if (setsockopt(newsock, SOL_SOCKET, SO_RCVTIMEO,
&tv, sizeof(tv)) < 0) {
errorc("setting SO_RCVTIMEO");
}
}
/* /*
* Read the first bit. It indicates whether we need to SSL * Read the first bit. It indicates whether we need to SSL
* handshake or not. Clear the buffer to avoid confusing * handshake or not. Clear the buffer to avoid confusing
...@@ -241,9 +256,14 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen) ...@@ -241,9 +256,14 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen)
bzero(nosslbuf, strlen(SPEAKSSL)); bzero(nosslbuf, strlen(SPEAKSSL));
if ((cc = read(newsock, nosslbuf, strlen(SPEAKSSL))) <= 0) { if ((cc = read(newsock, nosslbuf, strlen(SPEAKSSL))) <= 0) {
error("sslaccept: reading request"); if (cc < 0) {
if (cc == 0) err = errno;
errno = EIO; if (err == EWOULDBLOCK)
error("sslaccept: timeout reading request");
else
error("sslaccept: error reading request");
} else if (cc == 0)
err = EIO;
goto badauth; goto badauth;
} }
...@@ -262,17 +282,17 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen) ...@@ -262,17 +282,17 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen)
if (! (ssl = SSL_new(ctx))) { if (! (ssl = SSL_new(ctx))) {
tmcd_sslerror(); tmcd_sslerror();
errno = EIO; err = EIO;
goto badauth; goto badauth;
} }
if (! SSL_set_fd(ssl, newsock)) { if (! SSL_set_fd(ssl, newsock)) {
tmcd_sslerror(); tmcd_sslerror();
errno = EIO; err = EIO;
goto badauth; goto badauth;
} }
if (SSL_accept(ssl) <= 0) { if (SSL_accept(ssl) <= 0) {
tmcd_sslerror(); tmcd_sslerror();
errno = EAUTH; err = EAUTH;
goto badauth; goto badauth;
} }
...@@ -281,6 +301,7 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen) ...@@ -281,6 +301,7 @@ tmcd_sslaccept(int sock, struct sockaddr *addr, socklen_t *addrlen)
error("sslaccept: error speaking to %s\n", error("sslaccept: error speaking to %s\n",
inet_ntoa(((struct sockaddr_in *)addr)->sin_addr)); inet_ntoa(((struct sockaddr_in *)addr)->sin_addr));
tmcd_sslclose(newsock); tmcd_sslclose(newsock);
errno = err;
return -1; return -1;
} }
......
/* /*
* EMULAB-COPYRIGHT * EMULAB-COPYRIGHT
* Copyright (c) 2000-2002, 2004 University of Utah and the Flux Group. * Copyright (c) 2000-2002, 2004, 2006 University of Utah and the Flux Group.
* All rights reserved. * All rights reserved.
*/ */
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
int tmcd_server_sslinit(void); int tmcd_server_sslinit(void);
int tmcd_client_sslinit(void); int tmcd_client_sslinit(void);
int tmcd_sslaccept(int sock, struct sockaddr *, socklen_t *); int tmcd_sslaccept(int sock, struct sockaddr *, socklen_t *, int);
int tmcd_sslconnect(int sock, const struct sockaddr *, socklen_t); int tmcd_sslconnect(int sock, const struct sockaddr *, socklen_t);
int tmcd_sslwrite(int sock, const void *buf, size_t nbytes); int tmcd_sslwrite(int sock, const void *buf, size_t nbytes);
int tmcd_sslread(int sock, void *buf, size_t nbytes); int tmcd_sslread(int sock, void *buf, size_t nbytes);
...@@ -44,13 +44,13 @@ inline int win_recv(SOCKET s, char FAR* buf, int len) ...@@ -44,13 +44,13 @@ inline int win_recv(SOCKET s, char FAR* buf, int len)
{ {
return recv(s,buf,len,0); return recv(s,buf,len,0);
} }
#define ACCEPT accept #define ACCEPT tmcd_accept
#define CONNECT connect #define CONNECT connect
#define WRITE win_send #define WRITE win_send
#define READ win_recv #define READ win_recv
#define CLOSE close #define CLOSE close
#else #else
#define ACCEPT accept #define ACCEPT tmcd_accept
#define CONNECT connect #define CONNECT connect
#define WRITE write #define WRITE write
#define READ read #define READ read
......
...@@ -61,6 +61,10 @@ ...@@ -61,6 +61,10 @@
#define RUNASGROUP "nobody" #define RUNASGROUP "nobody"
#define NTPSERVER "ntp1" #define NTPSERVER "ntp1"
/* socket read/write timeouts in ms */
#define READTIMO 3000
#define WRITETIMO 3000
#define TESTMODE #define TESTMODE
#define DEFAULTNETMASK "255.255.255.0" #define DEFAULTNETMASK "255.255.255.0"
/* This can be tossed once all the changes are in place */ /* This can be tossed once all the changes are in place */
...@@ -109,6 +113,10 @@ MYSQL_RES * mydb_query(char *query, int ncols, ...); ...@@ -109,6 +113,10 @@ MYSQL_RES * mydb_query(char *query, int ncols, ...);
int mydb_update(char *query, ...); int mydb_update(char *query, ...);
static int safesymlink(char *name1, char *name2); static int safesymlink(char *name1, char *name2);
/* socket timeouts */
static int readtimo = READTIMO;
static int writetimo = WRITETIMO;
/* thread support */ /* thread support */
#define MAXCHILDREN 20 #define MAXCHILDREN 20
#define MINCHILDREN 8 #define MINCHILDREN 8
...@@ -790,6 +798,32 @@ udpserver(int sock, int portnum) ...@@ -790,6 +798,32 @@ udpserver(int sock, int portnum)
exit(1); exit(1);
} }
int
tmcd_accept(int sock, struct sockaddr *addr, socklen_t *addrlen, int ms)
{
int newsock;
if ((newsock = accept(sock, addr, addrlen)) < 0)
return -1;
/*
* Set timeout value to keep us from hanging due to a
* malfunctioning or malicious client.
*/
if (ms > 0) {
struct timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * 1000;
if (setsockopt(newsock, SOL_SOCKET, SO_RCVTIMEO,
&tv, sizeof(tv)) < 0) {
errorc("setting SO_RCVTIMEO");
}
}
return newsock;
}
/* /*
* Listen for TCP requests. * Listen for TCP requests.
*/ */
...@@ -800,6 +834,7 @@ tcpserver(int sock, int portnum) ...@@ -800,6 +834,7 @@ tcpserver(int sock, int portnum)
struct sockaddr_in client; struct sockaddr_in client;
int length, cc, newsock; int length, cc, newsock;
unsigned int nreq = 0; unsigned int nreq = 0;
struct timeval tv;
info("tcpserver starting: pid=%d sock=%d portnum=%d\n", info("tcpserver starting: pid=%d sock=%d portnum=%d\n",
mypid, sock, portnum); mypid, sock, portnum);
...@@ -810,18 +845,37 @@ tcpserver(int sock, int portnum) ...@@ -810,18 +845,37 @@ tcpserver(int sock, int portnum)
while (1) { while (1) {
setproctitle("TCP %d: %u done", portnum, nreq); setproctitle("TCP %d: %u done", portnum, nreq);
length = sizeof(client); length = sizeof(client);
newsock = ACCEPT(sock, (struct sockaddr *)&client, &length); newsock = ACCEPT(sock, (struct sockaddr *)&client, &length,
readtimo);
if (newsock < 0) { if (newsock < 0) {
errorc("accepting TCP connection"); errorc("accepting TCP connection");
continue; continue;
} }
/*
* Set write timeout value to keep us from hanging due to a
* malfunctioning or malicious client.
* NOTE: ACCEPT function sets read timeout.
*/
tv.tv_sec = writetimo / 1000;
tv.tv_usec = (writetimo % 1000) * 1000;
if (setsockopt(newsock, SOL_SOCKET, SO_SNDTIMEO,
&tv, sizeof(tv)) < 0) {
errorc("setting SO_SNDTIMEO");
CLOSE(newsock);
continue;
}
/* /*
* Read in the command request. * Read in the command request.
*/ */
if ((cc = READ(newsock, buf, sizeof(buf) - 1)) <= 0) { if ((cc = READ(newsock, buf, sizeof(buf) - 1)) <= 0) {
if (cc < 0) if (cc < 0) {
errorc("Reading TCP request"); if (errno == EWOULDBLOCK)
errorc("Timeout reading TCP request");
else
errorc("Error reading TCP request");
}
error("TCP connection aborted\n"); error("TCP connection aborted\n");
CLOSE(newsock); CLOSE(newsock);
continue; continue;
...@@ -5084,7 +5138,7 @@ COMMAND_PROTOTYPE(dorusage) ...@@ -5084,7 +5138,7 @@ COMMAND_PROTOTYPE(dorusage)
/* We're going to store plab up/down data in a file for a while. */ /* We're going to store plab up/down data in a file for a while. */
if (reqp->isplabsvc) { if (reqp->isplabsvc) {
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
tmnow = localtime(&now.tv_sec); tmnow = localtime((time_t *)&now.tv_sec);
strftime(timebuf, sizeof(timebuf), "%Y%m%d", tmnow); strftime(timebuf, sizeof(timebuf), "%Y%m%d", tmnow);
snprintf(pllogfname, sizeof(pllogfname), snprintf(pllogfname, sizeof(pllogfname),
"%s/%s-isalive-%s", "%s/%s-isalive-%s",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment