Crec que hauria de funcionar almenys el listen... però no va.
authorviric@llimona
Sun, 26 Mar 2006 20:44:16 +0200
changeset 3 9bcdce466e88
parent 2 c0db07a9d316
child 4 f74ca12a5a41
Crec que hauria de funcionar almenys el listen... però no va.
.hgignore
Makefile
syslog_in_udp.c
--- a/.hgignore	Sun Mar 26 16:57:18 2006 +0200
+++ b/.hgignore	Sun Mar 26 20:44:16 2006 +0200
@@ -1,2 +1,4 @@
 .*\.o
-syslog_npipe
+.*\.a
+syslog_in_npipe
+syslog_in_udp
--- a/Makefile	Sun Mar 26 16:57:18 2006 +0200
+++ b/Makefile	Sun Mar 26 20:44:16 2006 +0200
@@ -6,15 +6,19 @@
 #CC=tcc
 #CFLAGS=
 
-all: syslog_in_npipe
+all: syslog_in_npipe syslog_in_udp
 
 %.a: 
 	ar rc $@ $<
 
 rfc3164.o: rfc3164.h
 rfc3164.a: rfc3164.o
+
 syslog_in_npipe.o: rfc3164.h syslog_in_npipe.c
+syslog_in_udp.o: syslog_in_udp.c rfc3164.h
+
 syslog_in_npipe: syslog_in_npipe.o rfc3164.a
+syslog_in_udp: syslog_in_udp.o rfc3164.a
 
 clean:
 	rm -f *.o *.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/syslog_in_udp.c	Sun Mar 26 20:44:16 2006 +0200
@@ -0,0 +1,205 @@
+#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 <sys/types.h>  // Per crides de fitxer
+#include <sys/socket.h>  // Per les macros bool,true,false
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h> // Per protoent getprotobyname
+#include <assert.h> // Per assert()
+#include <sys/select.h> // Pel select()
+
+#include "rfc3164.h"
+
+const int const_listen_queue = 10;
+
+void show_help(const char * restrict program)
+{
+	printf("Usage: %s <udp_port>\n", program);
+}
+
+
+int udp_proto_number()
+{
+	struct protoent *protocol;
+
+	/* Get the protocol udp number */
+	protocol = getprotobyname("udp");
+	if (protocol == NULL)
+	{
+		printf("Cannot get the protocol number for udp.\n");
+		abort();
+	}
+	
+	return protocol->p_proto;
+}
+
+int listen_ipv6(int port)
+{
+	int socket_ipv6;
+	struct sockaddr_in6 source_ipv6;
+	int result;
+	int on=1;
+
+
+	socket_ipv6 = socket(PF_INET6, SOCK_DGRAM, udp_proto_number() );
+	if (socket_ipv6 == -1)
+	{
+		printf("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)
+	{
+		printf("IPv6 setsockopt() 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, const_listen_queue);
+	if (result != 0)
+	{
+		printf("Error in listen() ipv6: %s\n", strerror(errno));
+		abort();
+	}
+
+	return socket_ipv6;
+}
+
+int listen_ipv4(int port)
+{
+	int socket_ipv4;
+	struct sockaddr_in source_ipv4;
+	int result;
+	int on=1;
+
+
+	socket_ipv4 = socket(PF_INET, SOCK_DGRAM, udp_proto_number() );
+	if (socket_ipv4 == -1)
+	{
+		printf("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)
+	{
+		printf("IPv6 setsockopt() 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, const_listen_queue);
+	if (result != 0)
+	{
+		printf("Error in listen() ipv4: %s\n", strerror(errno));
+		abort();
+	}
+
+	return socket_ipv4;
+}
+
+
+int server_loop(int port)
+{
+	int socket_ipv6, socket_ipv4;
+	fd_set listen_sockets;
+	struct timeval wait_time;
+	int result;
+	int high_socket;
+
+
+	socket_ipv6 = listen_ipv6(port);
+	socket_ipv4 = listen_ipv4(port);
+
+	/* Establim els FDs que volem esperar al select() */
+	FD_ZERO(&listen_sockets);
+	FD_SET(socket_ipv6, &listen_sockets);
+	FD_SET(socket_ipv4, &listen_sockets);
+
+	/* Establim el temporitzador pel select() */
+	wait_time.tv_sec = 5;
+	wait_time.tv_usec = 0;
+
+	/* Mirem quin és el socket més alt pel select() */
+	high_socket = socket_ipv6;
+	if (high_socket < socket_ipv4)
+		high_socket = socket_ipv4;
+
+	high_socket += 1;
+	
+	result = 0;
+	while (result)
+	{
+		result = select(high_socket, &listen_sockets, NULL, NULL,
+			&wait_time);
+		if (result == 0)
+			continue;
+		else if (result == -1)
+		{
+			printf("Error in select(): %s\n", strerror(errno));
+			abort();
+		}
+
+		/* Algun FD té dades... */
+		if (FD_ISSET(socket_ipv4, &listen_sockets))
+		{
+			/* Dummy */
+			printf("Got data in IPv4\n");
+		}
+
+		if (FD_ISSET(socket_ipv6, &listen_sockets))
+		{
+			/* Dummy */
+			printf("Got data in IPv6\n");
+		}
+	}
+}
+
+
+int main(int argn, char **argv)
+{
+	int port;
+
+	/* Processem els paràmetres d'entrada */
+	if (argn != 2) {
+		show_help(argv[0]);
+		return 2;
+	}
+
+	port=atoi(argv[1]);
+	if (port < 0 || port >65535)
+	{
+		show_help(argv[0]);
+		return 2;
+	}
+
+	server_loop(port);
+
+	return 0;
+}