diff options
author | Jonas Gunz <himself@jonasgunz.de> | 2019-12-02 22:53:38 +0100 |
---|---|---|
committer | Jonas Gunz <himself@jonasgunz.de> | 2019-12-02 22:53:38 +0100 |
commit | d84a301a63c768afa3aafeede302e809af93f351 (patch) | |
tree | 8e7bf34b73c430fef4efff5f290858a371408aa1 /src/dns.c | |
parent | 1629c3621e02a8e176172f44a72d155030172d35 (diff) | |
download | dns-d84a301a63c768afa3aafeede302e809af93f351.tar.gz |
memory leak fixes, now answers
removed forking to improve performance
fixed memory leaks
added header construct function
now return MXDOMAIN to all valid DNS queries
Diffstat (limited to 'src/dns.c')
-rw-r--r-- | src/dns.c | 72 |
1 files changed, 65 insertions, 7 deletions
@@ -5,8 +5,52 @@ #include "dns.h" +int dns_construct_header ( struct dns_header* _header, char* _buffer, int _bufflen ) +{ + if ( !_buffer || !_header || _bufflen < 12 ) + return -1; + + *((uint16_t*)_buffer) = _header->id; //Since only copied, no flipping necessary + _buffer[2] = + ((_header->QR & 0x01) << 7) | + ((_header->OPCODE & 0x0F) << 3) | + ((_header->AA & 0x01) << 2) | + ((_header->TC & 0x01) << 1) | + ( _header->RD & 0x01); + _buffer[3] = + ((_header->RA & 0x01) << 7) | + ((_header->Z & 0x07) << 4) | + ( _header->RCODE & 0x0F); + *((uint16_t*)(_buffer + 4 )) = FLIP_BYTES(_header->question_count); + *((uint16_t*)(_buffer + 6 )) = FLIP_BYTES(_header->answer_count); + *((uint16_t*)(_buffer + 8 )) = FLIP_BYTES(_header->authorative_count); + *((uint16_t*)(_buffer + 10)) = FLIP_BYTES(_header->additional_count); + + return 12; +} + +int dns_destroy_struct ( struct dns_message* _msg ) +{ + if ( !_msg ) + return -1; + + if ( _msg->question_count > 0 && _msg->question) { + free ( _msg->question ); + _msg->question = NULL; + } + + if ( _msg->answer_count > 0 && _msg->answer) { + free ( _msg->answer ); + _msg->answer = NULL; + } + + return 0; +} + int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg ) { + //TODO refactor + if ( !_buffer || !_bufflen || !_msg ) return 1; //Invalid input @@ -23,16 +67,25 @@ 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->question_count = _msg->header.question_count = (*((uint8_t*) (_buffer + 4 )) << 8) | *((uint8_t*) (_buffer + 5 )); + _msg->answer_count = _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); + //Check for sensible QD, AN, NS and ARCOUNTS before massive memory allocation + if( _msg->header.question_count > 4 || + _msg->header.answer_count > 32 || + _msg->header.authorative_count > 32 || + _msg->header.additional_count > 32 ) { + return 1; + } + //Allocate question array //TODO Only implements question section. size_t qsize = sizeof(typeof(*(_msg->question))) * _msg->question_count; @@ -40,6 +93,9 @@ int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg ) _msg->question = malloc ( qsize ); memset( _msg->question, 0, qsize ); + if (!_msg->question) //malloc failed + return 1; + int ptr = 12; //byte counter for (int i = 0; i < _msg->question_count; i++) { int qname_len = qname_check ( (_buffer + ptr), _bufflen - ptr); @@ -49,12 +105,15 @@ int dns_parse_packet ( char* _buffer, int _bufflen, struct dns_message* _msg ) _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 + if( ptr >= (_bufflen - 4) ) //Out of bounds check return 1; + + _msg->question[i].qtype = ((uint8_t)*(_buffer + ptr) << 8) | ((uint8_t)*(_buffer + ptr + 1)); + ptr += 2; + _msg->question[i].qclass = ((uint8_t)*(_buffer + ptr) << 8) | ((uint8_t)*(_buffer + ptr + 1)); + ptr += 2; + } return 0; @@ -92,7 +151,6 @@ int fqdn_to_qname( char* _source, int _sourcelen, char* _sink ,int _sinklen ) return i+2; } - int qname_to_fqdn( char* _source, int _sourcelen, char* _sink, int _sinklen ) { if ( !_sourcelen || !_sinklen ) { |