The tcp server listen() started working. By now the connections are closed at once.
A bug was corrected in syslog_kernel, about EOF from read().
Added debug to term_childs().
--- a/Makefile.common Tue May 30 00:04:18 2006 +0200
+++ b/Makefile.common Tue May 30 00:32:32 2006 +0200
@@ -20,6 +20,7 @@
out_file.o: out_file.c syslog.h
signals.o: signals.c syslog.h
unix_writer.o: unix_writer.c rfc3164.h
+tcp_server.o: tcp_server.c rfc3164.h
childs.o: childs.c syslog.h
syslog_in_npipe: syslog_in_npipe.o rfc3164.a signals.o
@@ -27,7 +28,7 @@
syslog_in_unix: syslog_in_unix.o rfc3164.a signals.o
unix_writer: unix_writer.o
syslog_kernel: syslog_kernel.o config.o rfc3164.a signals.o out_udp.o \
- out_file.o childs.o
+ out_file.o childs.o tcp_server.o
clean:
rm -f *.o *.a
--- a/childs.c Tue May 30 00:04:18 2006 +0200
+++ b/childs.c Tue May 30 00:32:32 2006 +0200
@@ -35,6 +35,7 @@
for(i=0;i<childs_alive;i++)
{
res = kill(child[i], SIGTERM);
+ fprintf(stderr, "Sent SIGTERM to %i\n", child[i]);
/* Accepting the res == -1 && errno == ESRCH saves us
* from the race condition possible kill error */
if (res == -1)
--- a/syslog.conf Tue May 30 00:04:18 2006 +0200
+++ b/syslog.conf Tue May 30 00:32:32 2006 +0200
@@ -1,4 +1,5 @@
from_unix=patata
to_udp_host=localhost
to_udp_port=8000
+tcp_manager=3000
log_file=prova.log
--- a/syslog.h Tue May 30 00:04:18 2006 +0200
+++ b/syslog.h Tue May 30 00:32:32 2006 +0200
@@ -1,5 +1,6 @@
enum {
MAX_STRING=255,
+ TCP_LISTEN_QUEUE=10,
MAX_CHILDS=15
};
@@ -42,6 +43,9 @@
int write_out_file(const char * restrict buf, const int len);
int close_out_file();
+/* tcp_server.c */
+int init_tcp_server();
+
/* childs.c */
void term_childs();
void wait_childs_die();
--- a/syslog_kernel.c Tue May 30 00:04:18 2006 +0200
+++ b/syslog_kernel.c Tue May 30 00:32:32 2006 +0200
@@ -148,6 +148,9 @@
fprintf(stderr, "Received: %s\n",missatge);
output_message(missatge, res);
+ } else if (res == 0) /* EOF */
+ {
+ break;
}
}
@@ -207,6 +210,8 @@
else if (res == -1)
fprintf(stderr, "error setting up the File output.\n");
+ init_tcp_server();
+
kernel_loop();
if (reconfig == true)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp_server.c Tue May 30 00:32:32 2006 +0200
@@ -0,0 +1,246 @@
+#include <unistd.h> // Per les crides a fitxer
+#include <stdio.h> // Per l'I/O de stdin/stdout
+#include <errno.h> // Pels errors de les crides a fitxer
+#include <string.h> // Per strerror()
+#include <stdlib.h> // Per abort()
+#include <fcntl.h> // Per fcntl()
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdbool.h>
+#include <assert.h> // Per assert()
+#include <sys/select.h> // Pel select()
+
+#include "syslog.h"
+
+/* Prototypes */
+static void listen_tcp(const int port, const bool ipv6enabled);
+static int listen_tcp_ipv6(int port);
+static int listen_tcp_ipv4(int port);
+static int accept_connection(int socket);
+
+/* Returns 0 on success. Returns -1 on error. */
+int init_tcp_server()
+{
+ int pid;
+ int port;
+ char service[MAX_STRING];
+ enum {
+ SUCCESS=0,
+ ERROR=-1,
+ DISABLED=-2
+ } ret;
+
+
+ /* Get the configuration */
+ get_config(TCP_MANAGER, service, MAX_STRING);
+ if (strncmp(service, "disabled", MAX_STRING) == 0)
+ return DISABLED;
+
+ /* Check the configuration */
+ port = atoi(service);
+ if (port < -65535 || port > 65535)
+ return ERROR;
+
+ /* Create the server process */
+ pid = child_fork();
+
+ if (pid == 0)
+ {
+ /* Child */
+ close(0);
+ close(1);
+ //close(2);
+ if(port < 0)
+ {
+ listen_tcp(-port, true);
+ } else
+ {
+ listen_tcp(port, false);
+ }
+ /* Should be Not reachable */
+ exit(0);
+ } else if (pid > 0)
+ {
+ /* Parent */
+ fprintf(stderr, "Child forked (tcp server on port %i): %i\n",
+ port, pid);
+ ret = SUCCESS;
+ } else
+ {
+ ret = ERROR;
+ }
+
+ return ret;
+}
+
+
+static void listen_tcp(const int port, const bool ipv6enabled)
+{
+ int socket_ipv6, socket_ipv4;
+ fd_set listen_sockets;
+ int result;
+ int high_socket;
+
+ socket_ipv4 = listen_tcp_ipv4(port);
+
+ if (ipv6enabled)
+ socket_ipv6 = listen_tcp_ipv6(port);
+
+ /* Mirem quin és el socket més alt pel select() */
+ high_socket = socket_ipv4;
+ if (ipv6enabled && (high_socket < socket_ipv6) )
+ high_socket = socket_ipv6;
+
+ high_socket += 1;
+
+ result = 0;
+ while (result >= 0)
+ {
+ /* Establim els FDs que volem esperar al select() */
+ FD_ZERO(&listen_sockets);
+ if (ipv6enabled)
+ FD_SET(socket_ipv6, &listen_sockets);
+ FD_SET(socket_ipv4, &listen_sockets);
+
+ result = select(high_socket, &listen_sockets, NULL, NULL,
+ NULL);
+ if (result == 0)
+ {
+ /* Això no hauria de passar, no tenim timeout fixat. */
+ continue;
+ }
+ else if (result == -1 && errno != EINTR)
+ {
+ fprintf(stderr, "Error in select(): %s\n",
+ strerror(errno));
+ abort();
+ }
+
+ /* Algun FD té dades... */
+ if (FD_ISSET(socket_ipv4, &listen_sockets))
+ {
+ accept_connection(socket_ipv4);
+ }
+
+ if (ipv6enabled && FD_ISSET(socket_ipv6, &listen_sockets))
+ {
+ accept_connection(socket_ipv6);
+ }
+ }
+}
+
+
+static int listen_tcp_ipv6(int port)
+{
+ int socket_ipv6;
+ struct sockaddr_in6 source_ipv6;
+ int result;
+ int on=1;
+
+
+ socket_ipv6 = socket(PF_INET6, SOCK_STREAM, 0);
+ if (socket_ipv6 == -1)
+ {
+ fprintf(stderr, "IPv6 socket failed.\n");
+ abort();
+ }
+
+ /* Fem que poguem reutilitzar l'adreça encara que no s'hagi acabat
+ el timeout després de tancar-se la connexió */
+ if (setsockopt(socket_ipv6, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&on,sizeof(on)) < 0)
+ {
+ fprintf(stderr, "IPv6 setsockopt() failed: %s.\n",
+ strerror(errno));
+ abort();
+ }
+
+ /* No volem que aquest socket bloquegi. */
+ if (fcntl(socket_ipv6, F_SETFL, O_NONBLOCK) == -1)
+ {
+ fprintf(stderr, "IPv6 fcntl() failed: %s.\n",
+ strerror(errno));
+ abort();
+ }
+
+ /* IPv6 listen address */
+ memset(&source_ipv6, 0, sizeof(source_ipv6));
+ source_ipv6.sin6_family = AF_INET6;
+ source_ipv6.sin6_flowinfo = 0;
+ source_ipv6.sin6_port = htons(port);
+ source_ipv6.sin6_addr = in6addr_any;
+ result = bind(socket_ipv6, (struct sockaddr *) &source_ipv6,
+ sizeof(source_ipv6));
+ assert(result == 0);
+
+ result = listen(socket_ipv6, TCP_LISTEN_QUEUE);
+ if (result != 0)
+ {
+ fprintf(stderr,"Error in listen() ipv6: %s\n", strerror(errno));
+ abort();
+ }
+
+ return socket_ipv6;
+}
+
+static int listen_tcp_ipv4(int port)
+{
+ int socket_ipv4;
+ struct sockaddr_in source_ipv4;
+ int result;
+ int on=1;
+
+
+ socket_ipv4 = socket(PF_INET, SOCK_STREAM, 0);
+ if (socket_ipv4 == -1)
+ {
+ fprintf(stderr, "IPv4 socket not supported.\n");
+ abort();
+ }
+
+ /* Fem que poguem reutilitzar l'adreça encara que no s'hagi acabat
+ el timeout després de tancar-se la connexió */
+ if (setsockopt(socket_ipv4, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&on,sizeof(on)) < 0)
+ {
+ fprintf(stderr, "IPv4 setsockopt() failed: %s.\n",
+ strerror(errno));
+ abort();
+ }
+
+ /* No volem que aquest socket bloquegi. */
+ if (fcntl(socket_ipv4, F_SETFL, O_NONBLOCK) == -1)
+ {
+ fprintf(stderr, "IPv6 fcntl() failed: %s.\n",
+ strerror(errno));
+ abort();
+ }
+
+ /* IPv4 listen address */
+ memset(&source_ipv4, 0, sizeof(source_ipv4));
+ source_ipv4.sin_family = AF_INET;
+ source_ipv4.sin_port = htons(port);
+ source_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
+ result = bind(socket_ipv4, (struct sockaddr *) &source_ipv4,
+ sizeof(source_ipv4));
+ assert(result == 0);
+
+ result = listen(socket_ipv4, TCP_LISTEN_QUEUE);
+ if (result != 0)
+ {
+ fprintf(stderr,"Error in listen() ipv4: %s\n", strerror(errno));
+ abort();
+ }
+
+ return socket_ipv4;
+}
+
+
+static int accept_connection(int socket)
+{
+ int res;
+
+ res = accept(socket, NULL, NULL);
+ close(res);
+ return res;
+}