Updates to TCP server to close the lock file handle, use a non-blocking socket, and detect when the parent fwknop dies so it can exit as well.

git-svn-id: file:///home/mbr/svn/fwknop/trunk@228 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Damien Stuart 2010-07-01 03:12:32 +00:00
parent b217c6a1fa
commit 14e844f3f2
3 changed files with 83 additions and 7 deletions

View File

@ -597,6 +597,11 @@ write_pid_file(fko_srv_options_t *opts)
*/
fsync(op_fd);
/* Put the lock file discriptor in out options struct so any
* child processes we my spawn can close and release it.
*/
opts->lock_fd = op_fd;
return 0;
}

View File

@ -435,6 +435,7 @@ typedef struct fko_srv_options
int data_link_offset;
int tcp_server_pid;
int lock_fd;
spa_pkt_info_t spa_pkt; /* The current SPA packet */

View File

@ -33,9 +33,10 @@
#include <sys/socket.h>
#endif
#include <netdb.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/select.h>
static int c_sock;
//static int c_sock;
/* Fork off and run a "dummy" TCP server. The return value is the PID of
* the child process or -1 if there is a fork error.
@ -43,9 +44,12 @@ static int c_sock;
int
run_tcp_server(fko_srv_options_t *opts)
{
pid_t pid;
int s_sock, clen;
pid_t pid, ppid;
int s_sock, c_sock, sfd_flags, clen, selval;
int reuse_addr = 1;
fd_set sfd_set;
struct sockaddr_in saddr, caddr;
struct timeval tv;
char sipbuf[MAX_IP_STR_LEN];
unsigned short port = atoi(opts->config[CONF_TCPSERV_PORT]);
@ -65,8 +69,19 @@ run_tcp_server(fko_srv_options_t *opts)
return(pid);
}
/* We are the child, so let's make a TCP server */
/* Get our parent PID so we can periodically check for it. We want to
* know when it goes away so we can to.
*/
ppid = getppid();
/* We are the child. The first thing to do is close our copy of the
* parent PID file so we don't end up holding the lock if the parent
* suffers a sudden death that doesn't take us out too.
*/
close(opts->lock_fd);
/* Now, let's make a TCP server
*/
if ((s_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
log_msg(LOG_ERR, "run_tcp_server: socket() failed: %s",
@ -74,6 +89,29 @@ run_tcp_server(fko_srv_options_t *opts)
exit(EXIT_FAILURE);
}
/* So that we can re-bind to it without TIME_WAIT problems
*/
setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
/* Make our main socket non-blocking so we don't have to be stuck on
* listening for incoming connections.
*/
if((sfd_flags = fcntl(s_sock, F_GETFL, 0)) < 0)
{
log_msg(LOG_ERR, "run_tcp_server: fcntl F_GETFL error: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
sfd_flags |= O_NONBLOCK;
if(fcntl(s_sock, F_SETFL, sfd_flags) < 0)
{
log_msg(LOG_ERR, "run_tcp_server: fcntl F_SETFL error setting )_NONBLOCK: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
/* Construct local address structure */
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET; /* Internet address family */
@ -105,6 +143,38 @@ run_tcp_server(fko_srv_options_t *opts)
*/
while(1)
{
/* Initialize and setup the socket for select.
*/
FD_ZERO(&sfd_set);
FD_SET(s_sock, &sfd_set);
/* Set our select timeout to 200 ms.
*/
tv.tv_sec = 0;
tv.tv_usec = 200000;
selval = select(s_sock+1, &sfd_set, NULL, NULL, &tv);
if(selval == -1)
{
/* Select error - so kill the child and bail.
*/
log_msg(LOG_ERR, "run_tcp_server: select error socket: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
if(selval == 0)
{
/* Timeout - So we check to make sure our parent is still there by simply
* using kill(ppid, 0) and checking the return value.
*/
if(kill(ppid, 0) != 0 && errno == ESRCH)
exit(EXIT_FAILURE);
continue;
}
/* Wait for a client to connect
*/
if((c_sock = accept(s_sock, (struct sockaddr *) &caddr, &clen)) < 0)
@ -118,7 +188,7 @@ run_tcp_server(fko_srv_options_t *opts)
{
memset(sipbuf, 0x0, MAX_IP_STR_LEN);
inet_ntop(AF_INET, &(caddr.sin_addr.s_addr), sipbuf, MAX_IP_STR_LEN);
log_msg(LOG_INFO, "tcp_server: Got TCP connection from %s.", sipbuf);
log_msg(LOG_INFO|LOG_STDERR, "tcp_server: Got TCP connection from %s.", sipbuf);
}
/* Though hacky and clunky, we just sleep for a second then
@ -128,7 +198,7 @@ run_tcp_server(fko_srv_options_t *opts)
* after that time.
*/
usleep(1000000);
shutdown(c_sock, SHUT_RDWR);
close(c_sock);
}
}