aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jonas Gunz <himself@jonasgunz.de> 2019-12-02 01:37:15 +0100
committerGravatar Jonas Gunz <himself@jonasgunz.de> 2019-12-02 01:37:15 +0100
commit1cd2ee4a7776fb14ca76c63ab4ed181316327ef7 (patch)
tree3908248e231cab6b731554ff491fd34733404a55 /src
parentd2c641eb5b516783adfe2a236bc18412cd89af71 (diff)
downloaddns-1cd2ee4a7776fb14ca76c63ab4ed181316327ef7.tar.gz
Parser seems working for requests
Diffstat (limited to 'src')
-rw-r--r--src/dns.c64
-rw-r--r--src/dns.h41
-rw-r--r--src/main.c53
3 files changed, 123 insertions, 35 deletions
diff --git a/src/dns.c b/src/dns.c
index 2d3ac75..eaa032e 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -7,9 +7,9 @@ int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg )
if ( _bufflen < 12 )
return 1; //Too short to contain a DNS header
-
+
//TODO test
- _msg->header.id = *( (uint16_t*) _buffer );
+ _msg->header.id = *( (uint16_t*) _buffer );
_msg->header.QR = ( 0x80 & *( (uint8_t*) (_buffer + 2)) ) >> 7;
_msg->header.OPCODE = (0x78 & *( (uint8_t*) (_buffer + 2))) >> 3;
_msg->header.AA = (0x04 & *( (uint8_t*) (_buffer + 2))) >> 2;
@@ -18,17 +18,41 @@ int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg )
_msg->header.RA = (0x80 & *( (uint8_t*) (_buffer + 3))) >> 7;
_msg->header.Z = (0x70 & *( (uint8_t*) (_buffer + 3))) >> 4;
_msg->header.RCODE = (0x0F & *( (uint8_t*) (_buffer + 3)));
- _msg->header.question_count = (*((uint8_t*) (_buffer + 4)) << 8) | *((uint8_t*) (_buffer + 5));
- _msg->header.answer_count = (*((uint8_t*) (_buffer + 6)) << 8) | *((uint8_t*) (_buffer + 7));
- _msg->header.authorative_count = (*((uint8_t*) (_buffer + 8)) << 8) | *((uint8_t*) (_buffer + 9));
+ _msg->header.question_count = (*((uint8_t*) (_buffer + 4 )) << 8) | *((uint8_t*) (_buffer + 5 ));
+ _msg->header.answer_count = (*((uint8_t*) (_buffer + 6 )) << 8) | *((uint8_t*) (_buffer + 7 ));
+ _msg->header.authorative_count = (*((uint8_t*) (_buffer + 8 )) << 8) | *((uint8_t*) (_buffer + 9 ));
_msg->header.additional_count = (*((uint8_t*) (_buffer + 10)) << 8) | *((uint8_t*) (_buffer + 11));
-
+ //TODO remove
printf("ANSWER %i\n", _msg->header.answer_count);
printf("QUESTI %i\n", _msg->header.question_count);
printf("AUTHOR %i\n", _msg->header.authorative_count);
printf("ADDITI %i\n", _msg->header.additional_count);
-
- return 1;
+
+ //Allocate question array
+ //TODO Only implements question section.
+ size_t qsize = sizeof(typeof(*(_msg->question))) * _msg->question_count;
+ _msg->question_count = _msg->header.question_count;
+ _msg->question = malloc ( qsize );
+ memset( _msg->question, 0, qsize );
+
+ int ptr = 12; //byte counter
+ for (int i = 0; i < _msg->question_count; i++) {
+ int qname_len = qname_check ( (_buffer + ptr), _bufflen - ptr);
+
+ if (qname_len <= 0) //Check for faulty QNAME
+ return 1;
+
+ _msg->question[i].qname = _buffer + ptr;
+ ptr += qname_len;
+ _msg->question[i].qtype = (uint16_t*) (_buffer + ptr);
+ ptr += 2;
+ _msg->question[i].qclass = (uint16_t*) (_buffer + ptr);
+
+ if( ptr >= _bufflen ) //Out of bounds check
+ return 1;
+ }
+
+ return 0;
}
int fqdn_to_qname( char* _source, int _sourcelen, char* _sink ,int _sinklen )
@@ -60,7 +84,7 @@ int fqdn_to_qname( char* _source, int _sourcelen, char* _sink ,int _sinklen )
_sink[lastdot] = i - lastdot;
_sink[i + 1] = 0;
- return i+2;
+ return i+2;
}
@@ -85,8 +109,28 @@ int qname_to_fqdn( char* _source, int _sourcelen, char* _sink, int _sinklen )
} else {
_sink[i-1] = _source[i];
}
+ }
+ return i-1;
+}
+
+int qname_check( char* _source, int _sourcelen )
+{
+ if (!_sourcelen)
+ return -1;
+ int next_dot = 0;
+
+ for (int i = 0; i < _sourcelen; i++) {
+ if ( i == next_dot ) {
+ if (_source[i]) { //Not last dot
+ next_dot = _source[i] + i + 1;
+ } else { //last dot
+ return i+1;
+ }
+ } else if (!_source[i]) { //Invalid qname
+ return -1;
+ }
}
- return i-1;
+ return -1;
}
diff --git a/src/dns.h b/src/dns.h
index 8cba804..c2d6d18 100644
--- a/src/dns.h
+++ b/src/dns.h
@@ -1,18 +1,32 @@
#pragma once
#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
//TODO remove
#include <stdio.h>
+/**
+ * Data is COPIED
+ * */
struct dns_header;
+/**
+ * Data is REFERENCED
+ * */
struct dns_question;
+/**
+ * Data is REFERENCED
+ * */
struct dns_answer;
/**
* DNS Message struct
+ *
+ * A initialized instance is only valid as long as
+ * the buffer used to create it remains unchanged
* */
struct dns_message;
@@ -35,32 +49,33 @@ struct dns_header {
};
struct dns_question {
- char* qname;
- uint16_t qtype;
- uint16_t qclass;
+ const char* qname;
+ const uint16_t* qtype;
+ uint16_t* qclass;
};
struct dns_answer {
char* name; //in qname format
- uint16_t type;
- uint16_t class;
- uint32_t ttl;
- uint16_t rdlength;
+ uint16_t* type;
+ uint16_t* class;
+ uint32_t* ttl;
+ uint16_t* rdlength;
char* rdata;
};
struct dns_message {
struct dns_header header;
-
- int qcount;
+
+ int question_count;
struct dns_question* question;
- int acount;
+ int answer_count;
struct dns_answer* answer;
};
/**
* Parse the packet in _buffer and populate the dns_message struct
+ * Struct may still be written to on failure but contents are invalid
* returns: 0 on success, !=0 on failure
* */
int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg );
@@ -80,3 +95,9 @@ int fqdn_to_qname( char* _source, int _sourcelen, char* _sink, int _sinklen );
* _sink may still be altered in failed attempts, but not terminated.
* */
int qname_to_fqdn( char* _source, int _sourcelen, char* _sink, int _sinklen );
+
+/**
+ * Check a QNAME and get length
+ * returns: length of QNAME including NULL-byte at the end, < 0 on error
+ * */
+int qname_check( char* _source, int _sourcelen );
diff --git a/src/main.c b/src/main.c
index 92ca391..cb0432e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -34,10 +34,29 @@ void signal_term_child ( );
void signal_child ( );
-int test_main( int argc,
+int main1( int argc,
char* argv[] )
{
printf("TEST MODE. NOT FUNCTIONAL\n");
+
+ /*
+ //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];
@@ -48,6 +67,11 @@ int test_main( int argc,
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;
@@ -57,7 +81,7 @@ int test_main( int argc,
printf(" %x ", out[i]);
written = qname_to_fqdn (out,128,in,128);
-
+
if (written < 0) {
printf("invalid qname\n");
return 1;
@@ -72,9 +96,9 @@ int test_main( int argc,
int main( int argc,
char* argv[] )
{
- int ret;
- struct sockaddr_in sock_server_addr;
-
+ int ret;
+ struct sockaddr_in sock_server_addr;
+
char recv_buffer[ UDP_BUFFER_LEN ];
signal ( SIGTERM, signal_term );
@@ -112,7 +136,6 @@ int main( int argc,
{
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 );
@@ -130,7 +153,7 @@ int main( int argc,
LOGPRINTF(_LOG_DEBUG, "UDP Packet size %i", ret);
- if ( (pid = handle_connection (sock_server,
+ if ( (handle_connection (sock_server,
&sock_client_addr,
sock_client_addr_len,
recv_buffer,
@@ -155,12 +178,12 @@ int handle_connection ( int _socket,
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 );
@@ -169,25 +192,25 @@ int handle_connection ( int _socket,
//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 );
}
+ char out[128];
+ qname_to_fqdn( msg.question[0].qname, 100, out, 128);
+ printf("%s\n", out);
+
exit ( 0 );
}
void signal_term ( ) {
printf( "Recieved Signal. Terminating active connections and closing socket\n" );
-
+
//terminate all children >:)
kill ( 0, SIGTERM );