aboutsummaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.c')
-rw-r--r--src/server.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..4ca1985
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,120 @@
+/* main.c
+ * (c) Jonas Gunz, 2020
+ * License: MIT
+ * */
+
+#include "server.h"
+
+void run_dns_server ( void )
+{
+ int ret;
+ struct sockaddr_in sock_server_addr;
+
+ char recv_buffer[ UDP_BUFFER_LEN ];
+
+ signal ( SIGTERM, signal_term );
+ signal ( SIGINT, signal_term );
+
+ //Avoid zombie processes
+ //TODO currently useless, since no forking is done.
+ signal (SIGCHLD, SIG_IGN);
+
+ log_init_stdout ( _LOG_DEBUG );
+
+ sock_server = socket ( AF_INET, SOCK_DGRAM, 0 );
+ if ( sock_server == -1 ) {
+ LOGPRINTF(_LOG_ERROR, "socket() failed");
+ exit ( errno );
+ }
+
+ memset( &sock_server_addr, '\0', sizeof(struct sockaddr_in) );
+ sock_server_addr.sin_family = AF_INET;
+ sock_server_addr.sin_port = htons( 53 );
+ ret = inet_aton ( "0.0.0.0", & sock_server_addr.sin_addr );
+ if( ret == 0 ) { //Error on 0, no errno!
+ LOGPRINTF(_LOG_NOTE, "inet_aton(): Invalid bind IP\n" );
+ exit ( 1 );
+ }
+
+ ret = bind ( sock_server,
+ (struct sockaddr*) &sock_server_addr,
+ sizeof(struct sockaddr_in) );
+ if ( ret == -1 ) {
+ LOGPRINTF(_LOG_ERROR, "bind() failed");
+ exit ( errno );
+ }
+
+ while( 1 )
+ {
+ struct sockaddr_in sock_client_addr;
+ socklen_t sock_client_addr_len;
+
+ sock_client_addr_len = sizeof ( struct sockaddr_in );
+ memset ( &sock_client_addr, '\0', sock_client_addr_len );
+
+ ret = recvfrom (sock_server,
+ recv_buffer,
+ UDP_BUFFER_LEN,
+ 0,
+ (struct sockaddr*) &sock_client_addr,
+ &sock_client_addr_len );
+ if ( ret == -1 ) {
+ LOGPRINTF( _LOG_ERROR, "recvfrom()");
+ exit ( errno );
+ }
+
+ LOGPRINTF(_LOG_DEBUG, "UDP Packet size %i", ret);
+
+ handle_connection ( sock_server,
+ &sock_client_addr,
+ sock_client_addr_len,
+ recv_buffer,
+ ret );
+ }
+
+ close( sock_server );
+}
+
+int handle_connection ( int _socket,
+ struct sockaddr_in *sockaddr_client,
+ socklen_t sockaddr_client_len,
+ char* _buffer,
+ int _bufflen )
+{
+ struct dns_message msg;
+
+ if (dns_parse_packet (_buffer, _bufflen, &msg) ) {
+ LOGPRINTF (_LOG_DEBUG, "Malformed packet recieved. parsing failed");
+ return 1;
+ }
+
+ if(msg.question_count > 0) {
+ char out[128];
+ qname_to_fqdn( (char*) msg.question[0].qname, 100, out, 128);
+ printf("%s %i\n", out, msg.question[0].qtype);
+ }
+
+ dns_destroy_struct ( &msg );
+
+ //Always return NXDOMAIN
+ struct dns_header head = {msg.header.id,1,OP_Q,0,0,0,0,0,NAMEERR,0,0,0,0};
+ char ret[20];
+ int retlen = dns_construct_header ( &head, ret, 20 );
+ sendto (_socket, ret, retlen, 0, (struct sockaddr*) sockaddr_client, sockaddr_client_len);
+
+ return 0;
+}
+
+void signal_term ( ) {
+ printf( "Recieved Signal. Terminating active connections and closing socket\n" );
+
+ //terminate all children >:)
+ kill ( 0, SIGTERM );
+
+ shutdown ( sock_server, SHUT_RDWR );
+ close ( sock_server );
+
+ printf( "done\n" );
+
+ exit( 0 );
+}