aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jonas Gunz <himself@jonasgunz.de> 2020-04-04 02:25:21 +0200
committerGravatar Jonas Gunz <himself@jonasgunz.de> 2020-04-04 02:25:21 +0200
commita83aee989b06729078e6ba7c8448b30a3bab4e1d (patch)
tree0c39dee6cd7715ebb4d90e37efd774d1797c7151 /src
parentc36c7fedf969fa49e832c7d2739ea4d1ad1108f2 (diff)
downloaddns-a83aee989b06729078e6ba7c8448b30a3bab4e1d.tar.gz
Moved server to server.h/.c, added tests
- All server functions have been moved to server.h/.c - main call run_dns_server() or run_test() depending on makefile target - Makefile target test is now available - test.h/.c provide unit tests
Diffstat (limited to 'src')
-rw-r--r--src/main.c218
-rw-r--r--src/server.c120
-rw-r--r--src/server.h37
-rw-r--r--src/test.c109
-rw-r--r--src/test.h29
5 files changed, 302 insertions, 211 deletions
diff --git a/src/main.c b/src/main.c
index ff07c48..f193f44 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,222 +5,18 @@
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/ip.h>
-#include <arpa/inet.h>
-
-#include <unistd.h>
-
-#include <signal.h>
-
-#include "dns.h"
#include "log.h"
-#include "zonefile.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 main1( int argc,
- char* argv[] )
-{
- printf("TEST MODE. NOT FUNCTIONAL\n");
-
- printf ("%i\n", string_compare (argv[1], argv[2]));
-
- return 0;
- /*
- //Fuzztest the QNAME checker
- FILE* urand = fopen ("/dev/urandom", "r");
- char rand[128];
- char out[129];
- out[128] = 0;
-
- if (!urand)
- return 1;
-
- for (;;) {
- if (fread (rand, 128, 1, urand) > 0) {
- if ( qname_check(rand, 128) > 0 ) {
- qname_to_fqdn ( rand, 128, out, 128);
- printf("Valid %s\n", out);
- }
- }
- }*/
-
- 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 ( qname_check(out,128) < 0)
- printf("Wrong\n");
- else
- printf("qname ok\n");
-
- 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 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;
-
- 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);
-
- handle_connection ( sock_server,
- &sock_client_addr,
- sock_client_addr_len,
- recv_buffer,
- ret );
- }
-
- close( sock_server );
-
- return 0;
-}
-
-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);
+ //CMD line arg parsing goes in here
+#ifdef _TEST
+ run_test();
+#else
+ run_dns_server();
+#endif
- 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 );
-}
-
-void signal_term_child ( ) {
- close ( sock_server );
- printf ( "%i: Active connection terminated\n", getpid() );
- exit( 0 );
-}
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 );
+}
diff --git a/src/server.h b/src/server.h
new file mode 100644
index 0000000..388dbae
--- /dev/null
+++ b/src/server.h
@@ -0,0 +1,37 @@
+/* server.h
+ * (c) Jonas Gunz, 2020
+ * License: MIT
+ * */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+
+#include <unistd.h>
+
+#include <signal.h>
+
+#include "dns.h"
+#include "log.h"
+
+#define UDP_BUFFER_LEN 512
+
+static int sock_server;
+
+void run_dns_server ( void );
+
+int handle_connection ( int _socket,
+ struct sockaddr_in *sockaddr_client,
+ socklen_t sockaddr_client_len,
+ char* _buffer,
+ int _bufflen );
+
+void signal_term ( );
diff --git a/src/test.c b/src/test.c
new file mode 100644
index 0000000..d635515
--- /dev/null
+++ b/src/test.c
@@ -0,0 +1,109 @@
+/* test.c
+ * (c) Jonas Gunz, 2020
+ * License: MIT
+ * */
+
+#include "test.h"
+
+#ifdef _TEST
+
+void run_test ()
+{
+ //Space for temporary tests
+
+ //tree_balanced_insert(NULL, NULL, NULL, 15 );
+ //Normal tests
+ test_tree();
+ test_dns_parsing();
+ test_dns_parsing_fuzz();
+}
+
+int test_tree ()
+{
+ printf("\ntest_tree()\n");
+
+ struct tree_node* root = NULL;
+
+ tree_insert ( &root, "eins", "Test eins" );
+ tree_insert ( &root, "zwei", "Test zwei" );
+
+ printf("After Insert\n");
+
+ printf("%s\n", tree_get(&root, "zwei"));
+
+ printf("After Get\n");
+
+ tree_destroy (&root,0);
+
+ printf("After destroy\n");
+
+ return 0;
+}
+
+int test_dns_parsing ()
+{
+ printf("test_dns_parsing()\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 ( qname_check(out,128) < 0)
+ printf("Wrong\n");
+ else
+ printf("qname ok\n");
+
+ 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 test_dns_parsing_fuzz()
+{
+ printf("\n-> test_parsing_fuzz()\n======\n\n");
+ FILE* urand = fopen ("/dev/urandom", "r");
+ char rand[128];
+ char out[129];
+ out[128] = 0;
+
+ if (!urand)
+ return 1;
+
+ unsigned long int limit = 10000000;
+ unsigned long int valid_cnt = 0;
+ for (unsigned long int i = 0; i < limit; i++) {
+ if (fread (rand, 128, 1, urand) > 0) {
+ if ( qname_check(rand, 128) > 0 ) {
+ qname_to_fqdn ( rand, 128, out, 128);
+ //printf("Valid %s\n", out);
+ valid_cnt++;
+ }
+ }
+ }
+
+ float valid_percent = (float)valid_cnt / (float)limit * 100;
+ printf("# of valid qnames in random data: %i / %i = %f%%\n", valid_cnt, limit, valid_percent);
+
+ return 0;
+}
+#endif
diff --git a/src/test.h b/src/test.h
new file mode 100644
index 0000000..885e304
--- /dev/null
+++ b/src/test.h
@@ -0,0 +1,29 @@
+/* test.h
+ * (c) Jonas Gunz, 2020
+ * License: MIT
+ * */
+
+#pragma once
+
+#include <stdio.h>
+#include "tree.h"
+#include "dns.h"
+
+/*
+ * TODO
+ * * fuzz dns_parse_packet()
+ * * test dns_parse_packet() with random valid data
+ * * test qname_check() with random valid data
+ */
+
+#ifdef _TEST
+
+void run_test ();
+
+int test_tree ();
+
+int test_dns_parsing ();
+
+int test_dns_parsing_fuzz();
+
+#endif