diff options
Diffstat (limited to 'src/server.c')
-rw-r--r-- | src/server.c | 120 |
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 ); +} |