From 233f169f507e31472b23a64269878557d6f0f9fe Mon Sep 17 00:00:00 2001 From: Jonas Gunz Date: Sun, 28 Feb 2021 23:23:54 +0100 Subject: construct answer/question --- src/dns.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/dns.h | 34 ++++++++++++++++++++++++---- src/main.c | 6 ++++- src/server.c | 24 ++++++++++++++------ src/server.h | 8 ++++++- 5 files changed, 130 insertions(+), 16 deletions(-) diff --git a/src/dns.c b/src/dns.c index 2bf6add..01fe7fa 100644 --- a/src/dns.c +++ b/src/dns.c @@ -5,7 +5,7 @@ #include "dns.h" -int dns_construct_header ( struct dns_header* _header, char* _buffer, int _bufflen ) +int dns_construct_header ( char* _buffer, int _bufflen, struct dns_header* _header ) { if ( !_buffer || !_header || _bufflen < 12 ) return -1; @@ -29,6 +29,72 @@ int dns_construct_header ( struct dns_header* _header, char* _buffer, int _buffl return 12; } +int dns_construct_answer ( + char* _buffer, + int _bufflen, + struct dns_answer* _answer + ) { + int ret = 0; + + if ( !_buffer || _bufflen <= 0 || !_answer ) + return -1; + + // Check buffer size + if ( _answer->qname_len + _answer->rdlength + 10 > _bufflen ) + return -1; + + memcpy( _buffer, _answer->qname, _answer->qname_len ); + ret += _answer->qname_len; + + *((uint16_t*)(_buffer + ret + 0 )) = FLIP_BYTES(_answer->type); + *((uint16_t*)(_buffer + ret + 2 )) = FLIP_BYTES(_answer->class); + *((uint16_t*)(_buffer + ret + 4 )) = FLIP_BYTES((uint16_t)((_answer->ttl << 16) & 0xffff)); + *((uint16_t*)(_buffer + ret + 6 )) = FLIP_BYTES((uint16_t)(_answer->ttl & 0xffff)); + *((uint16_t*)(_buffer + ret + 8 )) = FLIP_BYTES(_answer->rdlength); + ret += 10; + + memcpy( _buffer + ret, _answer->rdata, _answer->rdlength ); + ret += _answer->rdlength; + + return ret; +} + +int dns_construct_questoin ( + char* _buffer, + int _bufflen, + struct dns_question* _question + ) { + //TODO Test + int ret = 0; + + if ( !_buffer || _bufflen <= 0 || !_question ) + return -1; + + // Check buffer size + if ( _question->qname_len + 4 > _bufflen ) + return -1; + + memcpy( _buffer, _question->qname, _question->qname_len ); + ret += _question->qname_len; + + *((uint16_t*)(_buffer + ret + 0 )) = FLIP_BYTES(_question->qtype); + *((uint16_t*)(_buffer + ret + 2 )) = FLIP_BYTES(_question->qclass); + ret += 4; + + return ret; +} + + +// Question and answer count come from header +int dns_construct_packet ( + char* _buffer, + int _bufflen, + struct dns_message* _message + ) { + return -1; +} + + int dns_destroy_struct ( struct dns_message* _msg ) { if ( !_msg ) @@ -77,7 +143,8 @@ int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg ) printf("QUESTI %i\n", _msg->header.question_count); printf("AUTHOR %i\n", _msg->header.authorative_count); printf("ADDITI %i\n", _msg->header.additional_count); -*/ + */ + //Check for sensible QD, AN, NS and ARCOUNTS before massive memory allocation if( _msg->header.question_count > 4 || _msg->header.answer_count > 32 || @@ -97,6 +164,8 @@ int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg ) return 1; int ptr = 12; //byte counter + + // TODO refactor for (int i = 0; i < _msg->question_count; i++) { int qname_len = qname_check ( (_buffer + ptr), _bufflen - ptr); @@ -104,6 +173,7 @@ int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg ) return 1; _msg->question[i].qname = _buffer + ptr; + _msg->question[i].qname_len = qname_len; ptr += qname_len; if( ptr >= (_bufflen - 4) ) //Out of bounds check diff --git a/src/dns.h b/src/dns.h index 73cf9c3..c44fb29 100644 --- a/src/dns.h +++ b/src/dns.h @@ -91,8 +91,9 @@ struct dns_answer; /** * DNS Message struct * - * A initialized instance is only valid as long as - * the buffer used to create it remains unchanged + * An initialized instance is only valid as long as + * the buffer used to create it remains unchanged as + * some values are referenced, not copied. * */ struct dns_message; @@ -116,12 +117,16 @@ struct dns_header { struct dns_question { const char* qname; + int qname_len; + uint16_t qtype; uint16_t qclass; }; struct dns_answer { - char* name; //in qname format + char* qname; //in qname format + int qname_len; + uint16_t type; uint16_t class; uint32_t ttl; @@ -140,9 +145,28 @@ struct dns_message { }; int dns_construct_header ( - struct dns_header* _header, char* _buffer, - int _bufflen + int _bufflen, + struct dns_header* _header + ); + +int dns_construct_answer ( + char* _buffer, + int _bufflen, + struct dns_answer* _answer + ); + +int dns_construct_questoin ( + char* _buffer, + int _bufflen, + struct dns_question* _question + ); + +// Question and answer count come from header +int dns_construct_packet ( + char* _buffer, + int _bufflen, + struct dns_message* _message ); /** diff --git a/src/main.c b/src/main.c index 848f04e..36a37c6 100644 --- a/src/main.c +++ b/src/main.c @@ -20,7 +20,11 @@ int main(int argc, char* argv[]) #ifdef _TEST run_test(); #else - run_dns_server(); + server_config_t config; + config.bind_ip = "0.0.0.0"; + config.bind_port = 53; + + run_dns_server( &config ); #endif } diff --git a/src/server.c b/src/server.c index 1b28b14..3ec6603 100644 --- a/src/server.c +++ b/src/server.c @@ -5,7 +5,7 @@ #include "server.h" -void run_dns_server ( void ) +void run_dns_server ( server_config_t* _config ) { int ret; struct sockaddr_in sock_server_addr; @@ -21,6 +21,8 @@ void run_dns_server ( void ) log_init_stdout ( _LOG_DEBUG ); + LOGPRINTF(_LOG_NOTE, "Initializing DNS Server on %s:%i", _config->bind_ip, _config->bind_port); + sock_server = socket ( AF_INET, SOCK_DGRAM, 0 ); if ( sock_server == -1 ) { LOGPRINTF(_LOG_ERROR, "socket() failed"); @@ -29,8 +31,8 @@ void run_dns_server ( void ) 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 ); + sock_server_addr.sin_port = htons( _config->bind_port ); + ret = inet_aton ( _config->bind_ip, & sock_server_addr.sin_addr ); if( ret == 0 ) { //Error on 0, no errno! LOGPRINTF(_LOG_NOTE, "inet_aton(): Invalid bind IP\n" ); exit ( 1 ); @@ -44,6 +46,8 @@ void run_dns_server ( void ) exit ( errno ); } + LOGPRINTF(_LOG_NOTE, "Done!"); + while( 1 ) { struct sockaddr_in sock_client_addr; @@ -95,10 +99,16 @@ int handle_connection ( int _socket, } //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); + + struct dns_question quest = & msg.question[0]; + + struct dns_header head = {msg.header.id,1,OP_Q,0,0,0,0,0,dns_responsecode.NOERR,0,0,0,0}; + struct dns_answer answ = {quest->qname, quest->qname_len, } + + char ret[512]; + int hlen = dns_construct_header ( ret, 512, &head ); + int alen = dns_construct_answer ( ret + hlen, 512-hlen, &answer ); + sendto (_socket, ret, hlen + alen, 0, (struct sockaddr*) sockaddr_client, sockaddr_client_len); dns_destroy_struct ( &msg ); diff --git a/src/server.h b/src/server.h index 388dbae..d59eba6 100644 --- a/src/server.h +++ b/src/server.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -24,9 +25,14 @@ #define UDP_BUFFER_LEN 512 +typedef struct server_config { + char* bind_ip; + uint16_t bind_port; +} server_config_t; + static int sock_server; -void run_dns_server ( void ); +void run_dns_server ( server_config_t* _config ); int handle_connection ( int _socket, struct sockaddr_in *sockaddr_client, -- cgit v1.2.3