#include #include #include #include #include #include #include #include #include #include #include "dns.h" #include "log.h" #define PRINT_ERRNO() {printf("%s:%i %i:%s\n", __FILE__, __LINE__, errno, strerror(errno));} #define UDP_BUFFER_LEN 512 //main server socket int sock_server; int handle_connection ( int _socket, struct sockaddr_in *sockaddr_client, socklen_t sockaddr_client_len, char* _buffer, int _bufflen ); void signal_term ( ); void signal_term_child ( ); void signal_child ( ); int test_main( int argc, char* argv[] ) { printf("TEST MODE. NOT FUNCTIONAL\n"); char in[128]; char out[128]; strncpy ( in, "sub.domain.example.com\0", 127); printf("%s\n", in); int written = fqdn_to_qname (in,128,out,128); if (written < 0) { printf("invallid fqdn\n"); return 1; } for(int i = 0; i < written; i++) printf(" %x ", out[i]); written = qname_to_fqdn (out,128,in,128); if (written < 0) { printf("invalid qname\n"); return 1; } printf("%s\n", in); printf("\n\n"); return 0; } int main( int argc, char* argv[] ) { 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 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"); return 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" ); return 1; } ret = bind ( sock_server, (struct sockaddr*) &sock_server_addr, sizeof(struct sockaddr_in) ); if ( ret == -1 ) { LOGPRINTF(_LOG_ERROR, "bind() failed"); return errno; } while( 1 ) { struct sockaddr_in sock_client_addr; socklen_t sock_client_addr_len; pid_t pid; 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()"); return errno; } LOGPRINTF(_LOG_DEBUG, "UDP Packet size %i", ret); if ( (pid = handle_connection (sock_server, &sock_client_addr, sock_client_addr_len, recv_buffer, ret ) ) ) { LOGPRINTF(_LOG_ERROR, "handle_connection() failed"); return errno; } else { LOGPRINTF ( _LOG_DEBUG, "forked " ); } } close( sock_server ); return 0; } int handle_connection ( int _socket, struct sockaddr_in *sockaddr_client, socklen_t sockaddr_client_len, char* _buffer, int _bufflen ) { pid_t pid = fork(); if ( pid > 0) return 0; else if ( pid < 0 ) return errno; //Change signal handler. signal_term shuts down entire socket on TERM signal ( SIGTERM, signal_term_child ); //echo request sendto (_socket, _buffer, _bufflen, 0, (struct sockaddr*) sockaddr_client, sockaddr_client_len); //Testing recieved question //TODO remove char out[128]; qname_to_fqdn((_buffer+12), _bufflen-12, out, 128); printf("%s\n", out); struct dns_message msg; if (dns_parse_packet (_buffer, _bufflen, &msg) ) { LOGPRINTF (_LOG_DEBUG, "Malformed packet recieved. parsing failed"); close ( _socket ); exit( 1 ); } exit ( 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 ); } void signal_term_child ( ) { close ( sock_server ); printf ( "%i: Active connection terminated\n", getpid() ); exit( 0 ); }