diff --git a/modules/pico_dns_client.c b/modules/pico_dns_client.c index 77e7afcb..4a72575a 100644 --- a/modules/pico_dns_client.c +++ b/modules/pico_dns_client.c @@ -1,12 +1,12 @@ /********************************************************************* - * PicoTCP-NG + * PicoTCP-NG * Copyright (c) 2020 Daniele Lacamera * * This file also includes code from: * PicoTCP * Copyright (c) 2012-2017 Altran Intelligent Systems * Authors: Kristof Roelants - * + * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only * * PicoTCP-NG is free software; you can redistribute it and/or modify @@ -596,9 +596,6 @@ static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s) } header = (struct pico_dns_header *)dns_response; - domain = (char *)header + sizeof(struct pico_dns_header); - qsuffix = (struct pico_dns_question_suffix *)pico_dns_client_seek(domain); - /* valid asuffix is determined dynamically later on */ if (pico_dns_client_check_header(header) < 0) return; @@ -607,6 +604,11 @@ static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s) if (!q) return; + // FIX: what if the query is not a PTR query? + domain = (char *)header + sizeof(struct pico_dns_header); + qsuffix = (struct pico_dns_question_suffix *)pico_dns_client_seek(domain); + /* valid asuffix is determined dynamically later on */ + if (pico_dns_client_check_qsuffix(qsuffix, q) < 0) return; @@ -873,4 +875,3 @@ int pico_dns_client_init(struct pico_stack *S) #endif /* PICO_SUPPORT_DNS_CLIENT */ - diff --git a/modules/pico_dns_common.c b/modules/pico_dns_common.c index 15fb8ee2..4836398e 100644 --- a/modules/pico_dns_common.c +++ b/modules/pico_dns_common.c @@ -1,12 +1,12 @@ /********************************************************************* - * PicoTCP-NG + * PicoTCP-NG * Copyright (c) 2020 Daniele Lacamera * * This file also includes code from: * PicoTCP * Copyright (c) 2012-2017 Altran Intelligent Systems * Authors: Toon Stegen, Jelle De Vleeschouwer - * + * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only * * PicoTCP-NG is free software; you can redistribute it and/or modify @@ -25,19 +25,21 @@ * * *********************************************************************/ -#include "pico_config.h" -#include "pico_protocol.h" -#include "pico_stack.h" +#include "pico_dns_common.h" #include "pico_addressing.h" +#include "pico_config.h" #include "pico_ipv4.h" #include "pico_ipv6.h" -#include "pico_dns_common.h" +#include "pico_protocol.h" +#include "pico_stack.h" #include "pico_tree.h" #ifdef DEBUG_DNS - #define dns_dbg dbg +#define dns_dbg dbg #else - #define dns_dbg(...) do {} while(0) +#define dns_dbg(...) \ + do { \ + } while (0) #endif /* MARK: v NAME & IP FUNCTIONS */ @@ -48,10 +50,13 @@ * - arriving to null terminator * - exceeding maxlen * ****************************************************************************/ -#define dns_name_foreach_label_safe(label, name, next, maxlen) \ - for ((label) = (name), (next) = (char *)((name) + *(unsigned char*)(name) + 1); \ - (*(label) != '\0') && ((uint16_t)((label) - (name)) < (maxlen)) && (((*label) & 0xC0) != 0xC0) && (*label <= 63); \ - (label) = (next), (next) = (char *)((next) + *(unsigned char*)(next) + 1)) +#define dns_name_foreach_label_safe(label, name, next, maxlen) \ + for ((label) = (name), \ + (next) = (char *)((name) + *(unsigned char *)(name) + 1); \ + (*(label) != '\0') && ((uint16_t)((label) - (name)) < (maxlen)) && \ + (((*label) & 0xC0) != 0xC0) && (*label <= 63); \ + (label) = (next), \ + (next) = (char *)((next) + *(unsigned char *)(next) + 1)) /* **************************************************************************** * Checks if the DNS name doesn't exceed 256 bytes including zero-byte. @@ -59,10 +64,8 @@ * @param namelen Length of the DNS name-string including zero-byte * @return 0 when the length is correct * ****************************************************************************/ -int -pico_dns_check_namelen( uint16_t namelen ) -{ - return ((namelen > 2u) && (namelen < PICO_DNS_NAMEBUF_SIZE)) ? (0) : (-1); +int pico_dns_check_namelen(uint16_t namelen) { + return ((namelen > 2u) && (namelen < PICO_DNS_NAMEBUF_SIZE)) ? (0) : (-1); } /* **************************************************************************** @@ -71,35 +74,32 @@ pico_dns_check_namelen( uint16_t namelen ) * * @param name Compressed name you want the calculate the strlen from * @return Returns strlen of a compressed name, takes the first byte of compr- - * ession pointer into account but not the second byte, which acts - * like a trailing zero-byte + * ession pointer into account but not the second byte, + *which acts like a trailing zero-byte * ****************************************************************************/ -uint16_t -pico_dns_namelen_comp( char *name ) -{ - uint16_t len = 0; - char *label = NULL, *next = NULL; - - /* Check params */ - if (!name) { - pico_err = PICO_ERR_EINVAL; - return 0; - } +uint16_t pico_dns_namelen_comp(char *name) { + uint16_t len = 0; + char *label = NULL, *next = NULL; - /* Just count until the zero-byte or a pointer */ - dns_name_foreach_label_safe(label, name, next, PICO_DNS_NAMEBUF_SIZE) { - if ((0xC0 & *label)) - break; - } + /* Check params */ + if (!name) { + pico_err = PICO_ERR_EINVAL; + return 0; + } - /* Calculate the length */ - len = (uint16_t)(label - name); - if(*label != '\0') - len++; + /* Just count until the zero-byte or a pointer */ + dns_name_foreach_label_safe(label, name, next, PICO_DNS_NAMEBUF_SIZE) { + if ((0xC0 & *label)) + break; + } - return len; -} + /* Calculate the length */ + len = (uint16_t)(label - name); + if (*label != '\0') + len++; + return len; +} /* **************************************************************************** * Returns the uncompressed name in DNS name format when DNS name compression @@ -109,66 +109,79 @@ pico_dns_namelen_comp( char *name ) * @param packet Packet that contains the compressed name * @return Returns the decompressed name, NULL on failure. * ****************************************************************************/ -char * -pico_dns_decompress_name( char *name, pico_dns_packet *packet ) -{ - char decompressed_name[PICO_DNS_NAMEBUF_SIZE] = { - 0 - }; - char *return_name = NULL; - uint16_t ptr = 0, nslen = 0; - uint16_t decompressed_index = 0; - char *label = NULL, *next = NULL; - - /* Reading labels until reaching to pointer or NULL terminator. - * Only one pointer is allowed in DNS compression, the pointer is always the last according to the RFC */ - dns_name_foreach_label_safe(label, name, next, PICO_DNS_NAMEBUF_SIZE) { - - uint8_t label_size = (uint8_t)(*label+1); - if (decompressed_index + label_size >= PICO_DNS_NAMEBUF_SIZE) { - return NULL; - } - memcpy(&decompressed_name[decompressed_index], label, label_size); - decompressed_index = (uint16_t)(decompressed_index+label_size); - } +char *pico_dns_decompress_name(char *name, pico_dns_packet *packet) { + uint16_t packet_len = sizeof(pico_dns_packet); + char decompressed_name[PICO_DNS_NAMEBUF_SIZE] = {0}; + char *return_name = NULL; + uint16_t ptr = 0, nslen = 0; + uint16_t decompressed_index = 0; + char *label = NULL, *next = NULL; + + if (!name || !packet) { + pico_err = PICO_ERR_EINVAL; + return NULL; + } - if (decompressed_index >= PICO_DNS_NAMEBUF_SIZE) { - return NULL; + /* Reading labels until reaching to pointer or NULL terminator. + * Only one pointer is allowed in DNS compression, the pointer is always the + * last according to the RFC */ + dns_name_foreach_label_safe(label, name, next, PICO_DNS_NAMEBUF_SIZE) { + if (!label || (*label & 0xFF) >= PICO_DNS_NAMEBUF_SIZE) { + return NULL; } - if (*label & 0xC0) { - /* Found compression bits */ - ptr = (uint16_t)((((uint16_t) *label) & 0x003F) << 8); - ptr = (uint16_t)(ptr | (uint16_t) *(label + 1)); - label = (char *)((uint8_t *)packet + ptr); - - dns_name_foreach_label_safe(label, label, next, PICO_DNS_NAMEBUF_SIZE-decompressed_index) { - uint8_t label_size = (uint8_t)(*label + 1); - if (decompressed_index + label_size >= PICO_DNS_NAMEBUF_SIZE) { - return NULL; - } - memcpy(&decompressed_name[decompressed_index], label, label_size); - decompressed_index = (uint16_t) (decompressed_index + label_size); - } + uint8_t label_size = (uint8_t)(*label + 1); + if (decompressed_index + label_size >= PICO_DNS_NAMEBUF_SIZE) { + return NULL; } + memcpy(&decompressed_name[decompressed_index], label, label_size); + decompressed_index = (uint16_t)(decompressed_index + label_size); + } - if (decompressed_index >= PICO_DNS_NAMEBUF_SIZE) { - return NULL; + if (decompressed_index >= PICO_DNS_NAMEBUF_SIZE) { + return NULL; + } + + if (*label & 0xC0) { + /* Found compression bits */ + ptr = (uint16_t)((((uint16_t)*label) & 0x003F) << 8); + ptr = (uint16_t)(ptr | (uint16_t)*(label + 1)); + + /* Check if the pointer is within the packet */ + if (ptr >= packet_len) { + return NULL; } - /* Append final zero-byte */ - decompressed_name[decompressed_index] = (uint8_t) '\0'; + label = (char *)((uint8_t *)packet + ptr); - /* Provide storage for the name to return */ - nslen = (uint16_t)(pico_dns_strlen(decompressed_name) + 1); - if(!(return_name = PICO_ZALLOC((size_t)nslen))) { - pico_err = PICO_ERR_ENOMEM; + dns_name_foreach_label_safe(label, label, next, + PICO_DNS_NAMEBUF_SIZE - decompressed_index) { + uint8_t label_size = (uint8_t)(*label + 1); + if (decompressed_index + label_size >= PICO_DNS_NAMEBUF_SIZE) { return NULL; + } + memcpy(&decompressed_name[decompressed_index], label, label_size); + decompressed_index = (uint16_t)(decompressed_index + label_size); } + } - memcpy((void *)return_name, (void *)decompressed_name, (size_t)nslen); + if (decompressed_index >= PICO_DNS_NAMEBUF_SIZE) { + return NULL; + } + + /* Append final zero-byte */ + decompressed_name[decompressed_index] = (uint8_t)'\0'; + + /* Provide storage for the name to return */ + nslen = (uint16_t)(pico_dns_strlen(decompressed_name) + 1); + if (!(return_name = PICO_ZALLOC((size_t)nslen))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } + + memcpy((void *)return_name, (void *)decompressed_name, (size_t)nslen); - return return_name; + return return_name; } /* **************************************************************************** @@ -182,31 +195,27 @@ pico_dns_decompress_name( char *name, pico_dns_packet *packet ) * 'PICO_PROTO_IPV4' or 'PICO_PROTO_IPV6' * @return Returns the length of the reverse name * ****************************************************************************/ -static uint16_t -pico_dns_url_get_reverse_len( const char *url, - uint16_t *arpalen, - uint16_t proto ) -{ - uint16_t slen = (uint16_t)(pico_dns_strlen(url) + 2u); - - /* Check if pointers given are not NULL */ - if (pico_dns_check_namelen(slen) && !arpalen) { - pico_err = PICO_ERR_EINVAL; - return 0; - } +static uint16_t pico_dns_url_get_reverse_len(const char *url, uint16_t *arpalen, + uint16_t proto) { + uint16_t slen = (uint16_t)(pico_dns_strlen(url) + 2u); - /* Get the length of arpa-suffix if needed */ - if (proto == PICO_PROTO_IPV4) - *arpalen = (uint16_t) pico_dns_strlen(PICO_ARPA_IPV4_SUFFIX); + /* Check if pointers given are not NULL */ + if (pico_dns_check_namelen(slen) && !arpalen) { + pico_err = PICO_ERR_EINVAL; + return 0; + } + + /* Get the length of arpa-suffix if needed */ + if (proto == PICO_PROTO_IPV4) + *arpalen = (uint16_t)pico_dns_strlen(PICO_ARPA_IPV4_SUFFIX); #ifdef PICO_SUPPORT_IPV6 - else if (proto == PICO_PROTO_IPV6) - { - *arpalen = (uint16_t) pico_dns_strlen(PICO_ARPA_IPV6_SUFFIX); - slen = STRLEN_PTR_IP6 + 2u; - } + else if (proto == PICO_PROTO_IPV6) { + *arpalen = (uint16_t)pico_dns_strlen(PICO_ARPA_IPV6_SUFFIX); + slen = STRLEN_PTR_IP6 + 2u; + } #endif - return slen; + return slen; } /* **************************************************************************** @@ -218,47 +227,44 @@ pico_dns_url_get_reverse_len( const char *url, * @param proto Depending on the protocol given the ARPA-suffix will be added. * @return Returns a pointer to a string-buffer with the reverse DNS name. * ****************************************************************************/ -static char * -pico_dns_url_to_reverse_qname( const char *url, uint8_t proto ) -{ - char *reverse_qname = NULL; - uint16_t arpalen = 0; - uint16_t slen = pico_dns_url_get_reverse_len(url, &arpalen, proto); - - /* Check namelen */ - if (pico_dns_check_namelen(slen)) { - pico_err = PICO_ERR_EINVAL; - return NULL; - } +static char *pico_dns_url_to_reverse_qname(const char *url, uint8_t proto) { + char *reverse_qname = NULL; + uint16_t arpalen = 0; + uint16_t slen = pico_dns_url_get_reverse_len(url, &arpalen, proto); + + /* Check namelen */ + if (pico_dns_check_namelen(slen)) { + pico_err = PICO_ERR_EINVAL; + return NULL; + } - /* Provide space for the reverse name */ - if (!(reverse_qname = PICO_ZALLOC((size_t)(slen + arpalen)))) { - pico_err = PICO_ERR_ENOMEM; - return NULL; - } + /* Provide space for the reverse name */ + if (!(reverse_qname = PICO_ZALLOC((size_t)(slen + arpalen)))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } - /* If reverse IPv4 address resolving, convert to IPv4 arpa-format */ - if (PICO_PROTO_IPV4 == proto) { - memcpy(reverse_qname + 1u, url, slen - 1u); - pico_dns_mirror_addr(reverse_qname + 1u); - memcpy(reverse_qname + slen - 1, PICO_ARPA_IPV4_SUFFIX, arpalen); - } + /* If reverse IPv4 address resolving, convert to IPv4 arpa-format */ + if (PICO_PROTO_IPV4 == proto) { + memcpy(reverse_qname + 1u, url, slen - 1u); + pico_dns_mirror_addr(reverse_qname + 1u); + memcpy(reverse_qname + slen - 1, PICO_ARPA_IPV4_SUFFIX, arpalen); + } - /* If reverse IPv6 address resolving, convert to IPv6 arpa-format */ + /* If reverse IPv6 address resolving, convert to IPv6 arpa-format */ #ifdef PICO_SUPPORT_IPV6 - else if (proto == PICO_PROTO_IPV6) { - pico_dns_ipv6_set_ptr(url, reverse_qname + 1u); - memcpy(reverse_qname + 1u + STRLEN_PTR_IP6, - PICO_ARPA_IPV6_SUFFIX, arpalen); - } + else if (proto == PICO_PROTO_IPV6) { + pico_dns_ipv6_set_ptr(url, reverse_qname + 1u); + memcpy(reverse_qname + 1u + STRLEN_PTR_IP6, PICO_ARPA_IPV6_SUFFIX, arpalen); + } #endif - else { /* This shouldn't happen */ - PICO_FREE(reverse_qname); - return NULL; - } + else { /* This shouldn't happen */ + PICO_FREE(reverse_qname); + return NULL; + } - pico_dns_name_to_dns_notation(reverse_qname, (uint16_t)(slen + arpalen)); - return reverse_qname; + pico_dns_name_to_dns_notation(reverse_qname, (uint16_t)(slen + arpalen)); + return reverse_qname; } /* **************************************************************************** @@ -269,33 +275,29 @@ pico_dns_url_to_reverse_qname( const char *url, uint8_t proto ) * @param qname DNS name in DNS name format to convert * @return Returns a pointer to a string-buffer with the URL name on success. * ****************************************************************************/ -char * -pico_dns_qname_to_url( const char *qname ) -{ - char *url = NULL; - char temp[PICO_DNS_NAMEBUF_SIZE] = { - 0 - }; - uint16_t namelen = pico_dns_strlen(qname); - - /* Check if qname is not a NULL-pointer and if the length is OK */ - if (pico_dns_check_namelen(namelen)) { - pico_err = PICO_ERR_EINVAL; - return NULL; - } +char *pico_dns_qname_to_url(const char *qname) { + char *url = NULL; + char temp[PICO_DNS_NAMEBUF_SIZE] = {0}; + uint16_t namelen = pico_dns_strlen(qname); + + /* Check if qname is not a NULL-pointer and if the length is OK */ + if (pico_dns_check_namelen(namelen)) { + pico_err = PICO_ERR_EINVAL; + return NULL; + } - /* Provide space for the URL */ - if (!(url = PICO_ZALLOC(namelen))) { - pico_err = PICO_ERR_ENOMEM; - return NULL; - } + /* Provide space for the URL */ + if (!(url = PICO_ZALLOC(namelen))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } - /* Convert qname to an URL */ - memcpy(temp, qname, namelen); - pico_dns_notation_to_name(temp, namelen); - memcpy((void *)url, (void *)(temp + 1), (size_t)(namelen - 1)); + /* Convert qname to an URL */ + memcpy(temp, qname, namelen); + pico_dns_notation_to_name(temp, namelen); + memcpy((void *)url, (void *)(temp + 1), (size_t)(namelen - 1)); - return url; + return url; } /* **************************************************************************** @@ -306,41 +308,37 @@ pico_dns_qname_to_url( const char *qname ) * @param url DNS name in URL format to convert * @return Returns a pointer to a string-buffer with the DNS name on success. * ****************************************************************************/ -char * -pico_dns_url_to_qname( const char *url ) -{ - char *qname = NULL; - uint16_t namelen = (uint16_t)(pico_dns_strlen(url) + 2u); - - /* Check if url or qname_addr is not a NULL-pointer */ - if (pico_dns_check_namelen(namelen)) { - pico_err = PICO_ERR_EINVAL; - return NULL; - } +char *pico_dns_url_to_qname(const char *url) { + char *qname = NULL; + uint16_t namelen = (uint16_t)(pico_dns_strlen(url) + 2u); - /* Provide space for the qname */ - if (!(qname = PICO_ZALLOC(namelen))) { - pico_err = PICO_ERR_ENOMEM; - return NULL; - } + /* Check if url or qname_addr is not a NULL-pointer */ + if (pico_dns_check_namelen(namelen)) { + pico_err = PICO_ERR_EINVAL; + return NULL; + } + + /* Provide space for the qname */ + if (!(qname = PICO_ZALLOC(namelen))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } - /* Copy in the URL (+1 to leave space for leading '.') */ - memcpy(qname + 1, url, (size_t)(namelen - 1)); - pico_dns_name_to_dns_notation(qname, namelen); - return qname; + /* Copy in the URL (+1 to leave space for leading '.') */ + memcpy(qname + 1, url, (size_t)(namelen - 1)); + pico_dns_name_to_dns_notation(qname, namelen); + return qname; } /* **************************************************************************** * @param url String-buffer * @return Length of string-buffer in an uint16_t * ****************************************************************************/ -uint16_t -pico_dns_strlen( const char *url ) -{ - if (!url) - return 0; +uint16_t pico_dns_strlen(const char *url) { + if (!url) + return 0; - return (uint16_t) strlen(url); + return (uint16_t)strlen(url); } /* **************************************************************************** @@ -354,29 +352,29 @@ pico_dns_strlen( const char *url ) * @param maxlen Maximum length of buffer so it doesn't cause a buffer overflow * @return 0 on success, something else on failure. * ****************************************************************************/ -int pico_dns_name_to_dns_notation( char *url, uint16_t maxlen ) -{ - char c = '\0'; - char *lbl = url, *i = url; - - /* Check params */ - if (!url || pico_dns_check_namelen(maxlen)) { - pico_err = PICO_ERR_EINVAL; - return -1; - } +int pico_dns_name_to_dns_notation(char *url, uint16_t maxlen) { + char c = '\0'; + char *lbl = url, *i = url; - /* Iterate over url */ - while ((c = *++i) != '\0') { - if ('.' == c) { - *lbl = (char)(i - lbl - 1); - lbl = i; - } + /* Check params */ + if (!url || pico_dns_check_namelen(maxlen)) { + pico_err = PICO_ERR_EINVAL; + return -1; + } - if ((uint16_t)(i - url) > (uint16_t)maxlen) break; + /* Iterate over url */ + while ((c = *++i) != '\0') { + if ('.' == c) { + *lbl = (char)(i - lbl - 1); + lbl = i; } - *lbl = (char)(i - lbl - 1); - return 0; + if ((uint16_t)(i - url) > (uint16_t)maxlen) + break; + } + *lbl = (char)(i - lbl - 1); + + return 0; } /* **************************************************************************** @@ -388,16 +386,13 @@ int pico_dns_name_to_dns_notation( char *url, uint16_t maxlen ) * @param maxlen Maximum length of buffer so it doesn't cause a buffer overflow * @return 0 on success, something else on failure. * ****************************************************************************/ -int pico_dns_notation_to_name( char *ptr, uint16_t maxlen ) -{ - char *label = NULL, *next = NULL; +int pico_dns_notation_to_name(char *ptr, uint16_t maxlen) { + char *label = NULL, *next = NULL; - /* Iterate safely over the labels and update each label */ - dns_name_foreach_label_safe(label, ptr, next, maxlen) { - *label = '.'; - } + /* Iterate safely over the labels and update each label */ + dns_name_foreach_label_safe(label, ptr, next, maxlen) { *label = '.'; } - return 0; + return 0; } /* **************************************************************************** @@ -406,22 +401,21 @@ int pico_dns_notation_to_name( char *ptr, uint16_t maxlen ) * @param url DNS name in URL-format * @return Length of the first label of DNS name in URL-format * ****************************************************************************/ -uint16_t -pico_dns_first_label_length( const char *url ) -{ - const char *i = NULL; - uint16_t len = 0; - - /* Check params */ - if (!url) return 0; - - /* Count */ - i = url; - while (*i != '.' && *i != '\0') { - ++i; - ++len; - } - return len; +uint16_t pico_dns_first_label_length(const char *url) { + const char *i = NULL; + uint16_t len = 0; + + /* Check params */ + if (!url) + return 0; + + /* Count */ + i = url; + while (*i != '.' && *i != '\0') { + ++i; + ++len; + } + return len; } /* **************************************************************************** @@ -431,22 +425,20 @@ pico_dns_first_label_length( const char *url ) * @param ptr * @return 0 on success, something else on failure. * ****************************************************************************/ -int -pico_dns_mirror_addr( char *ip ) -{ - uint32_t addr = 0; - - /* Convert IPv4-string to network-order 32-bit number */ - if (pico_string_to_ipv4(ip, &addr) < 0) - return -1; - - /* Mirror the 32-bit number */ - addr = (uint32_t)((uint32_t)((addr & (uint32_t)0xFF000000u) >> 24) | - (uint32_t)((addr & (uint32_t)0xFF0000u) >> 8) | - (uint32_t)((addr & (uint32_t)0xFF00u) << 8) | - (uint32_t)((addr & (uint32_t)0xFFu) << 24)); - - return pico_ipv4_to_string(ip, addr); +int pico_dns_mirror_addr(char *ip) { + uint32_t addr = 0; + + /* Convert IPv4-string to network-order 32-bit number */ + if (pico_string_to_ipv4(ip, &addr) < 0) + return -1; + + /* Mirror the 32-bit number */ + addr = (uint32_t)((uint32_t)((addr & (uint32_t)0xFF000000u) >> 24) | + (uint32_t)((addr & (uint32_t)0xFF0000u) >> 8) | + (uint32_t)((addr & (uint32_t)0xFF00u) << 8) | + (uint32_t)((addr & (uint32_t)0xFFu) << 24)); + + return pico_ipv4_to_string(ip, addr); } #ifdef PICO_SUPPORT_IPV6 @@ -456,14 +448,12 @@ pico_dns_mirror_addr( char *ip ) * @param byte Byte you want to extract the MSN from. * @return The ASCII value of the Most Significant Nibble of the byte * ****************************************************************************/ -static inline char -dns_ptr_ip6_nibble_lo( uint8_t byte ) -{ - uint8_t nibble = byte & 0x0f; - if (nibble < 10) - return (char)(nibble + '0'); - else - return (char)(nibble - 0xa + 'a'); +static inline char dns_ptr_ip6_nibble_lo(uint8_t byte) { + uint8_t nibble = byte & 0x0f; + if (nibble < 10) + return (char)(nibble + '0'); + else + return (char)(nibble - 0xa + 'a'); } /* **************************************************************************** @@ -472,14 +462,12 @@ dns_ptr_ip6_nibble_lo( uint8_t byte ) * @param byte Byte you want to extract the LSN from. * @return The ASCII value of the Least Significant Nibble of the byte * ****************************************************************************/ -static inline char -dns_ptr_ip6_nibble_hi( uint8_t byte ) -{ - uint8_t nibble = (byte & 0xf0u) >> 4u; - if (nibble < 10u) - return (char)(nibble + '0'); - else - return (char)(nibble - 0xa + 'a'); +static inline char dns_ptr_ip6_nibble_hi(uint8_t byte) { + uint8_t nibble = (byte & 0xf0u) >> 4u; + if (nibble < 10u) + return (char)(nibble + '0'); + else + return (char)(nibble - 0xa + 'a'); } /* **************************************************************************** @@ -489,21 +477,20 @@ dns_ptr_ip6_nibble_hi( uint8_t byte ) * @param ip IPv6-address stored as a string * @param dst Destination to store IPv6-address in nibble-format * ****************************************************************************/ -void -pico_dns_ipv6_set_ptr( const char *ip, char *dst ) -{ - int i = 0, j = 0; - struct pico_ip6 ip6; - memset(&ip6, 0, sizeof(struct pico_ip6)); - pico_string_to_ipv6(ip, ip6.addr); - for (i = 15; i >= 0; i--) { - if ((j + 3) > 64) return; /* Don't want j to go out of bounds */ - - dst[j++] = dns_ptr_ip6_nibble_lo(ip6.addr[i]); - dst[j++] = '.'; - dst[j++] = dns_ptr_ip6_nibble_hi(ip6.addr[i]); - dst[j++] = '.'; - } +void pico_dns_ipv6_set_ptr(const char *ip, char *dst) { + int i = 0, j = 0; + struct pico_ip6 ip6; + memset(&ip6, 0, sizeof(struct pico_ip6)); + pico_string_to_ipv6(ip, ip6.addr); + for (i = 15; i >= 0; i--) { + if ((j + 3) > 64) + return; /* Don't want j to go out of bounds */ + + dst[j++] = dns_ptr_ip6_nibble_lo(ip6.addr[i]); + dst[j++] = '.'; + dst[j++] = dns_ptr_ip6_nibble_hi(ip6.addr[i]); + dst[j++] = '.'; + } } #endif @@ -517,16 +504,15 @@ pico_dns_ipv6_set_ptr( const char *ip, char *dst ) * @param question Void-point to DNS Question * @return Size in bytes of single DNS Question if it was copied flat. * ****************************************************************************/ -static uint16_t pico_dns_question_size( void *question ) -{ - uint16_t size = 0; - struct pico_dns_question *q = (struct pico_dns_question *)question; - if (!q) - return 0; - - size = q->qname_length; - size = (uint16_t)(size + sizeof(struct pico_dns_question_suffix)); - return size; +static uint16_t pico_dns_question_size(void *question) { + uint16_t size = 0; + struct pico_dns_question *q = (struct pico_dns_question *)question; + if (!q) + return 0; + + size = q->qname_length; + size = (uint16_t)(size + sizeof(struct pico_dns_question_suffix)); + return size; } /* **************************************************************************** @@ -536,27 +522,25 @@ static uint16_t pico_dns_question_size( void *question ) * destroy. * @return Returns 0 on success, something else on failure. * ****************************************************************************/ -int -pico_dns_question_delete( void **question ) -{ - struct pico_dns_question **q = (struct pico_dns_question **)question; - - /* Check params */ - if ((!q) || !(*q)) { - pico_err = PICO_ERR_EINVAL; - return -1; - } +int pico_dns_question_delete(void **question) { + struct pico_dns_question **q = (struct pico_dns_question **)question; - if ((*q)->qname) - PICO_FREE(((*q)->qname)); + /* Check params */ + if ((!q) || !(*q)) { + pico_err = PICO_ERR_EINVAL; + return -1; + } - if ((*q)->qsuffix) - PICO_FREE((*q)->qsuffix); + if ((*q)->qname) + PICO_FREE(((*q)->qname)); - PICO_FREE((*q)); - *question = NULL; + if ((*q)->qsuffix) + PICO_FREE((*q)->qsuffix); - return 0; + PICO_FREE((*q)); + *question = NULL; + + return 0; } /* **************************************************************************** @@ -570,17 +554,14 @@ pico_dns_question_delete( void **question ) * @param qclass DNS class of the DNS question to be. * @return Returns 0 on success, something else on failure. * ****************************************************************************/ -int -pico_dns_question_fill_suffix( struct pico_dns_question_suffix *suf, - uint16_t qtype, - uint16_t qclass ) -{ - if (!suf) - return -1; - - suf->qtype = short_be(qtype); - suf->qclass = short_be(qclass); - return 0; +int pico_dns_question_fill_suffix(struct pico_dns_question_suffix *suf, + uint16_t qtype, uint16_t qclass) { + if (!suf) + return -1; + + suf->qtype = short_be(qtype); + suf->qclass = short_be(qclass); + return 0; } /* **************************************************************************** @@ -588,40 +569,37 @@ pico_dns_question_fill_suffix( struct pico_dns_question_suffix *suf, * * @param qname Pointer-pointer to the name-member of the DNS-question * @param url Name in URL format you want to convert to a name in DNS name - * format. When reverse resolving, only the IP, either IPV4 or - * IPV6, should be given in string format. - * f.e. => for IPv4: "192.168.2.1" - * => for IPv6: "2001:0db8:85a3:0042:1000:8a2e:0370:7334" + * format. When reverse resolving, only the IP, + *either IPV4 or IPV6, should be given in string format. f.e. => for IPv4: + *"192.168.2.1" + * => for IPv6: + *"2001:0db8:85a3:0042:1000:8a2e:0370:7334" * @param qtype DNS type type of the DNS question to be. * @param proto When reverse is true the reverse resolution name will be - * generated depending on the protocol. Can be either - * PICO_PROTO_IPV4 or PICO_PROTO_IPV6. + * generated depending on the protocol. Can be + *either PICO_PROTO_IPV4 or PICO_PROTO_IPV6. * @param reverse When this is true a reverse resolution name will be generated * from the URL. * @return The eventual length of the generated name, 0 on failure. * ****************************************************************************/ -static uint16_t -pico_dns_question_fill_name( char **qname, - const char *url, - uint16_t qtype, - uint8_t proto, - uint8_t reverse ) -{ - uint16_t slen = 0; - - /* Try to convert the URL to an FQDN */ - if (reverse && qtype == PICO_DNS_TYPE_PTR) - *qname = pico_dns_url_to_reverse_qname(url, proto); - else { - (*qname) = pico_dns_url_to_qname(url); - } - - if (!(*qname)) { - return 0; - } +static uint16_t pico_dns_question_fill_name(char **qname, const char *url, + uint16_t qtype, uint8_t proto, + uint8_t reverse) { + uint16_t slen = 0; + + /* Try to convert the URL to an FQDN */ + if (reverse && qtype == PICO_DNS_TYPE_PTR) + *qname = pico_dns_url_to_reverse_qname(url, proto); + else { + (*qname) = pico_dns_url_to_qname(url); + } + + if (!(*qname)) { + return 0; + } - slen = (uint16_t)(pico_dns_strlen(*qname) + 1u); - return (pico_dns_check_namelen(slen)) ? ((uint16_t)0) : (slen); + slen = (uint16_t)(pico_dns_strlen(*qname) + 1u); + return (pico_dns_check_namelen(slen)) ? ((uint16_t)0) : (slen); } /* **************************************************************************** @@ -640,47 +618,42 @@ pico_dns_question_fill_name( char **qname, * failure. * ****************************************************************************/ struct pico_dns_question * -pico_dns_question_create( const char *url, - uint16_t *len, - uint8_t proto, - uint16_t qtype, - uint16_t qclass, - uint8_t reverse ) -{ - struct pico_dns_question *question = NULL; - uint16_t slen = 0; - int ret = 0; - - /* Check if valid arguments are provided */ - if (!url || !len) { - pico_err = PICO_ERR_EINVAL; - return NULL; - } - - /* Allocate space for the question and the subfields */ - if (!(question = PICO_ZALLOC(sizeof(struct pico_dns_question)))) { - pico_err = PICO_ERR_ENOMEM; - return NULL; - } +pico_dns_question_create(const char *url, uint16_t *len, uint8_t proto, + uint16_t qtype, uint16_t qclass, uint8_t reverse) { + struct pico_dns_question *question = NULL; + uint16_t slen = 0; + int ret = 0; + + /* Check if valid arguments are provided */ + if (!url || !len) { + pico_err = PICO_ERR_EINVAL; + return NULL; + } - /* Fill name field */ - slen = pico_dns_question_fill_name(&(question->qname), url, - qtype, proto, reverse); - question->qname_length = (uint8_t)(slen); - question->proto = proto; - - /* Provide space for the question suffix & try to fill in */ - question->qsuffix = PICO_ZALLOC(sizeof(struct pico_dns_question_suffix)); - ret = pico_dns_question_fill_suffix(question->qsuffix, qtype, qclass); - if (ret || pico_dns_check_namelen(slen)) { - pico_dns_question_delete((void **)&question); - return NULL; - } + /* Allocate space for the question and the subfields */ + if (!(question = PICO_ZALLOC(sizeof(struct pico_dns_question)))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } + + /* Fill name field */ + slen = pico_dns_question_fill_name(&(question->qname), url, qtype, proto, + reverse); + question->qname_length = (uint8_t)(slen); + question->proto = proto; + + /* Provide space for the question suffix & try to fill in */ + question->qsuffix = PICO_ZALLOC(sizeof(struct pico_dns_question_suffix)); + ret = pico_dns_question_fill_suffix(question->qsuffix, qtype, qclass); + if (ret || pico_dns_check_namelen(slen)) { + pico_dns_question_delete((void **)&question); + return NULL; + } - /* Determine the entire length of the question */ - *len = (uint16_t)(slen + (uint16_t)sizeof(struct pico_dns_question_suffix)); + /* Determine the entire length of the question */ + *len = (uint16_t)(slen + (uint16_t)sizeof(struct pico_dns_question_suffix)); - return question; + return question; } /* **************************************************************************** @@ -690,19 +663,16 @@ pico_dns_question_create( const char *url, * @param packet Packet in which the DNS question is contained. * @return Pointer to original name of the DNS question before decompressing. * ****************************************************************************/ -char * -pico_dns_question_decompress( struct pico_dns_question *question, - pico_dns_packet *packet ) -{ - char *qname_original = question->qname; +char *pico_dns_question_decompress(struct pico_dns_question *question, + pico_dns_packet *packet) { + char *qname_original = question->qname; - /* Try to decompress the question name */ - question->qname = pico_dns_decompress_name(question->qname, packet); + /* Try to decompress the question name */ + question->qname = pico_dns_decompress_name(question->qname, packet); - return qname_original; + return qname_original; } - /* MARK: ^ QUESTION FUNCTIONS */ /* MARK: v RESOURCE RECORD FUNCTIONS */ @@ -711,47 +681,44 @@ pico_dns_question_decompress( struct pico_dns_question *question, * * @param record Pointer to DNS record you want to copy flat. * @param destination Pointer-pointer to flat memory buffer to copy DNS record - * to. When function returns, this will point to location - * right after the flat copied DNS Resource Record. + * to. When function returns, this will + *point to location right after the flat copied DNS Resource Record. * @return Returns 0 on success, something else on failure. * ****************************************************************************/ -static int -pico_dns_record_copy_flat( struct pico_dns_record *record, - uint8_t **destination ) -{ - char *dest_rname = NULL; /* rname destination location */ - struct pico_dns_record_suffix *dest_rsuffix = NULL; /* rsuffix destin. */ - uint8_t *dest_rdata = NULL; /* rdata destination location */ - - /* Check if there are no NULL-pointers given */ - if (!record || !destination || !(*destination)) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* Initialise the destination pointers to the right locations */ - dest_rname = (char *) *destination; - dest_rsuffix = (struct pico_dns_record_suffix *) - (dest_rname + record->rname_length); - dest_rdata = ((uint8_t *)dest_rsuffix + - sizeof(struct pico_dns_record_suffix)); - - /* Copy the rname of the resource record into the flat location */ - strcpy(dest_rname, record->rname); - - /* Copy the question suffix fields */ - dest_rsuffix->rtype = record->rsuffix->rtype; - dest_rsuffix->rclass = record->rsuffix->rclass; - dest_rsuffix->rttl = record->rsuffix->rttl; - dest_rsuffix->rdlength = record->rsuffix->rdlength; - - /* Copy the rdata of the resource */ - memcpy(dest_rdata, record->rdata, short_be(dest_rsuffix->rdlength)); - - /* Point to location right after flat resource record */ - *destination = (uint8_t *)(dest_rdata + - short_be(record->rsuffix->rdlength)); - return 0; +static int pico_dns_record_copy_flat(struct pico_dns_record *record, + uint8_t **destination) { + char *dest_rname = NULL; /* rname destination location */ + struct pico_dns_record_suffix *dest_rsuffix = NULL; /* rsuffix destin. */ + uint8_t *dest_rdata = NULL; /* rdata destination location */ + + /* Check if there are no NULL-pointers given */ + if (!record || !destination || !(*destination)) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* Initialise the destination pointers to the right locations */ + dest_rname = (char *)*destination; + dest_rsuffix = + (struct pico_dns_record_suffix *)(dest_rname + record->rname_length); + dest_rdata = + ((uint8_t *)dest_rsuffix + sizeof(struct pico_dns_record_suffix)); + + /* Copy the rname of the resource record into the flat location */ + strcpy(dest_rname, record->rname); + + /* Copy the question suffix fields */ + dest_rsuffix->rtype = record->rsuffix->rtype; + dest_rsuffix->rclass = record->rsuffix->rclass; + dest_rsuffix->rttl = record->rsuffix->rttl; + dest_rsuffix->rdlength = record->rsuffix->rdlength; + + /* Copy the rdata of the resource */ + memcpy(dest_rdata, record->rdata, short_be(dest_rsuffix->rdlength)); + + /* Point to location right after flat resource record */ + *destination = (uint8_t *)(dest_rdata + short_be(record->rsuffix->rdlength)); + return 0; } /* **************************************************************************** @@ -761,19 +728,17 @@ pico_dns_record_copy_flat( struct pico_dns_record *record, * @param record void-pointer to DNS record you want to know the size of. * @return Size of single DNS record if it was copied flat. * ****************************************************************************/ -static uint16_t -pico_dns_record_size( void *record ) -{ - uint16_t size = 0; - struct pico_dns_record *rr = (struct pico_dns_record *)record; - - if (!rr || !(rr->rsuffix)) - return 0; - - size = rr->rname_length; - size = (uint16_t)(size + sizeof(struct pico_dns_record_suffix)); - size = (uint16_t)(size + short_be(rr->rsuffix->rdlength)); - return size; +static uint16_t pico_dns_record_size(void *record) { + uint16_t size = 0; + struct pico_dns_record *rr = (struct pico_dns_record *)record; + + if (!rr || !(rr->rsuffix)) + return 0; + + size = rr->rname_length; + size = (uint16_t)(size + sizeof(struct pico_dns_record_suffix)); + size = (uint16_t)(size + short_be(rr->rsuffix->rdlength)); + return size; } /* **************************************************************************** @@ -783,27 +748,25 @@ pico_dns_record_size( void *record ) * @param record void-pointer-pointer to DNS record you want to delete. * @return Returns 0 on success, something else on failure. * ****************************************************************************/ -int -pico_dns_record_delete( void **record ) -{ - struct pico_dns_record **rr = (struct pico_dns_record **)record; +int pico_dns_record_delete(void **record) { + struct pico_dns_record **rr = (struct pico_dns_record **)record; - if ((!rr) || !(*rr)) - return 0; + if ((!rr) || !(*rr)) + return 0; - if ((*rr)->rname) - PICO_FREE((*rr)->rname); + if ((*rr)->rname) + PICO_FREE((*rr)->rname); - if ((*rr)->rsuffix) - PICO_FREE((*rr)->rsuffix); + if ((*rr)->rsuffix) + PICO_FREE((*rr)->rsuffix); - if ((*rr)->rdata) - PICO_FREE((*rr)->rdata); + if ((*rr)->rdata) + PICO_FREE((*rr)->rdata); - PICO_FREE((*rr)); - *record = NULL; + PICO_FREE((*rr)); + *record = NULL; - return 0; + return 0; } /* **************************************************************************** @@ -812,48 +775,46 @@ pico_dns_record_delete( void **record ) * @param record DNS record you want to copy * @return Pointer to copy of DNS record. * ****************************************************************************/ -struct pico_dns_record * -pico_dns_record_copy( struct pico_dns_record *record ) -{ - struct pico_dns_record *copy = NULL; - - /* Check params */ - if (!record || !(record->rname) || !(record->rdata) || !(record->rsuffix)) { - pico_err = PICO_ERR_EINVAL; - return NULL; - } +struct pico_dns_record *pico_dns_record_copy(struct pico_dns_record *record) { + struct pico_dns_record *copy = NULL; - /* Provide space for the copy */ - if (!(copy = PICO_ZALLOC(sizeof(struct pico_dns_record)))) { - pico_err = PICO_ERR_ENOMEM; - return NULL; - } + /* Check params */ + if (!record || !(record->rname) || !(record->rdata) || !(record->rsuffix)) { + pico_err = PICO_ERR_EINVAL; + return NULL; + } - /* Provide space for the subfields */ - copy->rname = PICO_ZALLOC((size_t)record->rname_length); - copy->rsuffix = PICO_ZALLOC(sizeof(struct pico_dns_record_suffix)); - copy->rdata = PICO_ZALLOC((size_t)short_be(record->rsuffix->rdlength)); - if (!(copy->rname) || !(copy->rsuffix) || !(copy->rdata)) { - pico_dns_record_delete((void **)©); - pico_err = PICO_ERR_ENOMEM; - return NULL; - } + /* Provide space for the copy */ + if (!(copy = PICO_ZALLOC(sizeof(struct pico_dns_record)))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } + + /* Provide space for the subfields */ + copy->rname = PICO_ZALLOC((size_t)record->rname_length); + copy->rsuffix = PICO_ZALLOC(sizeof(struct pico_dns_record_suffix)); + copy->rdata = PICO_ZALLOC((size_t)short_be(record->rsuffix->rdlength)); + if (!(copy->rname) || !(copy->rsuffix) || !(copy->rdata)) { + pico_dns_record_delete((void **)©); + pico_err = PICO_ERR_ENOMEM; + return NULL; + } - /* Fill in the rname field */ - memcpy((void *)(copy->rname), (void *)(record->rname), - (size_t)(record->rname_length)); - copy->rname_length = record->rname_length; + /* Fill in the rname field */ + memcpy((void *)(copy->rname), (void *)(record->rname), + (size_t)(record->rname_length)); + copy->rname_length = record->rname_length; - /* Fill in the rsuffix fields */ - copy->rsuffix->rtype = record->rsuffix->rtype; - copy->rsuffix->rclass = record->rsuffix->rclass; - copy->rsuffix->rttl = record->rsuffix->rttl; - copy->rsuffix->rdlength = record->rsuffix->rdlength; + /* Fill in the rsuffix fields */ + copy->rsuffix->rtype = record->rsuffix->rtype; + copy->rsuffix->rclass = record->rsuffix->rclass; + copy->rsuffix->rttl = record->rsuffix->rttl; + copy->rsuffix->rdlength = record->rsuffix->rdlength; - /* Fill in the rdata field */ - memcpy(copy->rdata, record->rdata, short_be(record->rsuffix->rdlength)); + /* Fill in the rdata field */ + memcpy(copy->rdata, record->rdata, short_be(record->rsuffix->rdlength)); - return copy; + return copy; } /* **************************************************************************** @@ -866,26 +827,22 @@ pico_dns_record_copy( struct pico_dns_record *record ) * @param rdlength DNS rdlength of the resource record to be. * @return Returns 0 on success, something else on failure. * ****************************************************************************/ -static int -pico_dns_record_fill_suffix( struct pico_dns_record_suffix **suf, - uint16_t rtype, - uint16_t rclass, - uint32_t rttl, - uint16_t rdlength ) -{ - /* Try to provide space for the rsuffix */ - if (!(*suf = PICO_ZALLOC(sizeof(struct pico_dns_record_suffix)))) { - pico_err = PICO_ERR_ENOMEM; - return -1; - } - - /* Fill in the fields */ - (*suf)->rtype = short_be(rtype); - (*suf)->rclass = short_be(rclass); - (*suf)->rttl = long_be(rttl); - (*suf)->rdlength = short_be(rdlength); - - return 0; +static int pico_dns_record_fill_suffix(struct pico_dns_record_suffix **suf, + uint16_t rtype, uint16_t rclass, + uint32_t rttl, uint16_t rdlength) { + /* Try to provide space for the rsuffix */ + if (!(*suf = PICO_ZALLOC(sizeof(struct pico_dns_record_suffix)))) { + pico_err = PICO_ERR_ENOMEM; + return -1; + } + + /* Fill in the fields */ + (*suf)->rtype = short_be(rtype); + (*suf)->rclass = short_be(rclass); + (*suf)->rttl = long_be(rttl); + (*suf)->rdlength = short_be(rdlength); + + return 0; } /* **************************************************************************** @@ -893,46 +850,43 @@ pico_dns_record_fill_suffix( struct pico_dns_record_suffix **suf, * * @param rdata Pointer-pointer to rdata-member of struct pico_dns_record. * @param _rdata Memory buffer with data to insert in the resource record. If - * data should contain a DNS name, the name in the databuffer - * needs to be in URL-format. + * data should contain a DNS name, the name in + *the databuffer needs to be in URL-format. * @param datalen The exact length in bytes of the _rdata-buffer. If data of - * record should contain a DNS name, datalen needs to be - * pico_dns_strlen(_rdata). + * record should contain a DNS name, datalen + *needs to be pico_dns_strlen(_rdata). * @param rtype DNS type of the resource record to be * @return Returns 0 on failure, length of filled in rdata-member on success. - * Can differ from datalen-param because of URL to DNS Name conversion. + * Can differ from datalen-param because of URL to DNS Name + *conversion. * ****************************************************************************/ -static uint16_t -pico_dns_record_fill_rdata( uint8_t **rdata, - void *_rdata, - uint16_t datalen, - uint16_t rtype ) -{ - uint16_t _datalen = 0; - - /* If type is PTR, rdata will be a DNS name in URL format */ - if (rtype == PICO_DNS_TYPE_PTR) { - _datalen = (uint16_t)(datalen + 2u); - if (!(*rdata = (uint8_t *)pico_dns_url_to_qname(_rdata))) { - pico_err = PICO_ERR_ENOMEM; - return 0; - } - } else { - /* Otherwise just copy in the databuffer */ - if (datalen == 0) { - return datalen; - } - - _datalen = datalen; - if (!(*rdata = (uint8_t *)PICO_ZALLOC((size_t)datalen))) { - pico_err = PICO_ERR_ENOMEM; - return 0; - } - - memcpy((void *)*rdata, (void *)_rdata, datalen); +static uint16_t pico_dns_record_fill_rdata(uint8_t **rdata, void *_rdata, + uint16_t datalen, uint16_t rtype) { + uint16_t _datalen = 0; + + /* If type is PTR, rdata will be a DNS name in URL format */ + if (rtype == PICO_DNS_TYPE_PTR) { + _datalen = (uint16_t)(datalen + 2u); + if (!(*rdata = (uint8_t *)pico_dns_url_to_qname(_rdata))) { + pico_err = PICO_ERR_ENOMEM; + return 0; + } + } else { + /* Otherwise just copy in the databuffer */ + if (datalen == 0) { + return datalen; } - return _datalen; + _datalen = datalen; + if (!(*rdata = (uint8_t *)PICO_ZALLOC((size_t)datalen))) { + pico_err = PICO_ERR_ENOMEM; + return 0; + } + + memcpy((void *)*rdata, (void *)_rdata, datalen); + } + + return _datalen; } /* **************************************************************************** @@ -941,65 +895,60 @@ pico_dns_record_fill_rdata( uint8_t **rdata, * @param url DNS rrecord name in URL format. Will be converted to DNS * name notation format. * @param _rdata Memory buffer with data to insert in the resource record. If - * data should contain a DNS name, the name in the databuffer - * needs to be in URL-format. + * data should contain a DNS name, the name in + *the databuffer needs to be in URL-format. * @param datalen The exact length in bytes of the _rdata-buffer. If data of - * record should contain a DNS name, datalen needs to be - * pico_dns_strlen(_rdata). + * record should contain a DNS name, datalen + *needs to be pico_dns_strlen(_rdata). * @param len Will be filled with the total length of the DNS rrecord. * @param rtype DNS type of the resource record to be. * @param rclass DNS class of the resource record to be. * @param rttl DNS ttl of the resource record to be. * @return Returns pointer to the created DNS Resource Record * ****************************************************************************/ -struct pico_dns_record * -pico_dns_record_create( struct pico_stack *S, - const char *url, - void *_rdata, - uint16_t datalen, - uint16_t *len, - uint16_t rtype, - uint16_t rclass, - uint32_t rttl ) -{ - struct pico_dns_record *record = NULL; - uint16_t slen = (uint16_t)(pico_dns_strlen(url) + 2u); - int ret = 0; - (void)S; - - /* Check params */ - if (pico_dns_check_namelen(slen) || !_rdata || !len) { - pico_err = PICO_ERR_EINVAL; - return NULL; - } +struct pico_dns_record *pico_dns_record_create(struct pico_stack *S, + const char *url, void *_rdata, + uint16_t datalen, uint16_t *len, + uint16_t rtype, uint16_t rclass, + uint32_t rttl) { + struct pico_dns_record *record = NULL; + uint16_t slen = (uint16_t)(pico_dns_strlen(url) + 2u); + int ret = 0; + (void)S; + + /* Check params */ + if (pico_dns_check_namelen(slen) || !_rdata || !len) { + pico_err = PICO_ERR_EINVAL; + return NULL; + } - /* Allocate space for the record and subfields */ - if (!(record = PICO_ZALLOC(sizeof(struct pico_dns_record)))) { - pico_err = PICO_ERR_ENOMEM; - return NULL; - } + /* Allocate space for the record and subfields */ + if (!(record = PICO_ZALLOC(sizeof(struct pico_dns_record)))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } - /* Provide space and convert the URL to a DNS name */ - record->rname = pico_dns_url_to_qname(url); - record->rname_length = slen; + /* Provide space and convert the URL to a DNS name */ + record->rname = pico_dns_url_to_qname(url); + record->rname_length = slen; - /* Provide space & fill in the rdata field */ - datalen = pico_dns_record_fill_rdata(&(record->rdata), _rdata, - datalen, rtype); + /* Provide space & fill in the rdata field */ + datalen = + pico_dns_record_fill_rdata(&(record->rdata), _rdata, datalen, rtype); - /* Provide space & fill in the rsuffix */ - ret = pico_dns_record_fill_suffix(&(record->rsuffix), rtype, rclass, rttl, - datalen); + /* Provide space & fill in the rsuffix */ + ret = pico_dns_record_fill_suffix(&(record->rsuffix), rtype, rclass, rttl, + datalen); - /* Check if everything succeeded */ - if (!(record->rname) || ret) { - pico_dns_record_delete((void **)&record); - return NULL; - } + /* Check if everything succeeded */ + if (!(record->rname) || ret) { + pico_dns_record_delete((void **)&record); + return NULL; + } - /* Determine the complete length of resource record */ - *len = (uint16_t)(slen + sizeof(struct pico_dns_record_suffix) + datalen); - return record; + /* Determine the complete length of resource record */ + *len = (uint16_t)(slen + sizeof(struct pico_dns_record_suffix) + datalen); + return record; } /* **************************************************************************** @@ -1009,24 +958,21 @@ pico_dns_record_create( struct pico_stack *S, * @param packet Packet in which is DNS record is present * @return Pointer to original name of the DNS record before decompressing. * ****************************************************************************/ -char * -pico_dns_record_decompress( struct pico_dns_record *record, - pico_dns_packet *packet ) -{ - char *rname_original = record->rname; +char *pico_dns_record_decompress(struct pico_dns_record *record, + pico_dns_packet *packet) { + char *rname_original = record->rname; - /* Try to decompress the record name */ - record->rname = pico_dns_decompress_name(record->rname, packet); + /* Try to decompress the record name */ + record->rname = pico_dns_decompress_name(record->rname, packet); - return rname_original; + return rname_original; } -static int pico_tolower(int c) -{ - if ((c >= 'A') && (c <= 'Z')) - c += 'a' - 'A'; +static int pico_tolower(int c) { + if ((c >= 'A') && (c <= 'Z')) + c += 'a' - 'A'; - return c; + return c; } /* MARK: ^ RESOURCE RECORD FUNCTIONS */ @@ -1044,45 +990,43 @@ static int pico_tolower(int c) * PICO_DNS_CASE_SENSITIVE or PICO_DNS_CASE_INSENSITIVE * @return 0 when the buffers are equal, returns difference when they're not. * ****************************************************************************/ -int -pico_dns_rdata_cmp( uint8_t *a, uint8_t *b, - uint16_t rdlength_a, uint16_t rdlength_b, uint8_t caseinsensitive ) -{ - uint16_t i = 0; - uint16_t slen = 0; - int dif = 0; - - /* Check params */ - if (!a || !b) { - if (!a && !b) - return 0; - - pico_err = PICO_ERR_EINVAL; - return -1; +int pico_dns_rdata_cmp(uint8_t *a, uint8_t *b, uint16_t rdlength_a, + uint16_t rdlength_b, uint8_t caseinsensitive) { + uint16_t i = 0; + uint16_t slen = 0; + int dif = 0; + + /* Check params */ + if (!a || !b) { + if (!a && !b) + return 0; + + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* Determine the smallest length */ + slen = rdlength_a; + if (rdlength_b < slen) + slen = rdlength_b; + + /* loop over slen */ + if (caseinsensitive) { + for (i = 0; i < slen; i++) { + if ((dif = pico_tolower((int)a[i]) - pico_tolower((int)b[i]))) { + return dif; + } } - - /* Determine the smallest length */ - slen = rdlength_a; - if (rdlength_b < slen) - slen = rdlength_b; - - /* loop over slen */ - if(caseinsensitive) { - for (i = 0; i < slen; i++) { - if ((dif = pico_tolower((int)a[i]) - pico_tolower((int)b[i]))) { - return dif; - } - } - }else{ - for (i = 0; i < slen; i++) { - if ((dif = (int)a[i] - (int)b[i])) { - return dif; - } - } + } else { + for (i = 0; i < slen; i++) { + if ((dif = (int)a[i] - (int)b[i])) { + return dif; + } } + } - /* Return difference of buffer lengths */ - return (int)((int)rdlength_a - (int)rdlength_b); + /* Return difference of buffer lengths */ + return (int)((int)rdlength_a - (int)rdlength_b); } /* **************************************************************************** @@ -1092,31 +1036,28 @@ pico_dns_rdata_cmp( uint8_t *a, uint8_t *b, * @param qb DNS question A as a void-pointer (for pico_tree) * @return 0 when questions are equal, returns difference when they're not. * ****************************************************************************/ -int -pico_dns_question_cmp( void *qa, - void *qb ) -{ - int dif = 0; - uint16_t at = 0, bt = 0; - struct pico_dns_question *a = (struct pico_dns_question *)qa; - struct pico_dns_question *b = (struct pico_dns_question *)qb; - - /* Check params */ - if (!a || !b) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* First, compare the qtypes */ - at = short_be(a->qsuffix->qtype); - bt = short_be(b->qsuffix->qtype); - if ((dif = (int)((int)at - (int)bt))) - return dif; - - /* Then compare qnames */ - return pico_dns_rdata_cmp((uint8_t *)a->qname, (uint8_t *)b->qname, - pico_dns_strlen(a->qname), - pico_dns_strlen(b->qname), PICO_DNS_CASE_INSENSITIVE); +int pico_dns_question_cmp(void *qa, void *qb) { + int dif = 0; + uint16_t at = 0, bt = 0; + struct pico_dns_question *a = (struct pico_dns_question *)qa; + struct pico_dns_question *b = (struct pico_dns_question *)qb; + + /* Check params */ + if (!a || !b) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* First, compare the qtypes */ + at = short_be(a->qsuffix->qtype); + bt = short_be(b->qsuffix->qtype); + if ((dif = (int)((int)at - (int)bt))) + return dif; + + /* Then compare qnames */ + return pico_dns_rdata_cmp( + (uint8_t *)a->qname, (uint8_t *)b->qname, pico_dns_strlen(a->qname), + pico_dns_strlen(b->qname), PICO_DNS_CASE_INSENSITIVE); } /* **************************************************************************** @@ -1127,31 +1068,28 @@ pico_dns_question_cmp( void *qa, * @return 0 when name and type of records are equal, returns difference when * they're not. * ****************************************************************************/ -int -pico_dns_record_cmp_name_type( void *ra, - void *rb ) -{ - int dif; - uint16_t at = 0, bt = 0; - struct pico_dns_record *a = (struct pico_dns_record *)ra; - struct pico_dns_record *b = (struct pico_dns_record *)rb; - - /* Check params */ - if (!a || !b) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* First, compare the rrtypes */ - at = short_be(a->rsuffix->rtype); - bt = short_be(b->rsuffix->rtype); - if ((dif = (int)((int)at - (int)bt))) - return dif; - - /* Then compare names */ - return pico_dns_rdata_cmp((uint8_t *)(a->rname), (uint8_t *)(b->rname), - (uint16_t)strlen(a->rname), - (uint16_t)strlen(b->rname), PICO_DNS_CASE_INSENSITIVE); +int pico_dns_record_cmp_name_type(void *ra, void *rb) { + int dif; + uint16_t at = 0, bt = 0; + struct pico_dns_record *a = (struct pico_dns_record *)ra; + struct pico_dns_record *b = (struct pico_dns_record *)rb; + + /* Check params */ + if (!a || !b) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* First, compare the rrtypes */ + at = short_be(a->rsuffix->rtype); + bt = short_be(b->rsuffix->rtype); + if ((dif = (int)((int)at - (int)bt))) + return dif; + + /* Then compare names */ + return pico_dns_rdata_cmp( + (uint8_t *)(a->rname), (uint8_t *)(b->rname), (uint16_t)strlen(a->rname), + (uint16_t)strlen(b->rname), PICO_DNS_CASE_INSENSITIVE); } /* **************************************************************************** @@ -1161,28 +1099,25 @@ pico_dns_record_cmp_name_type( void *ra, * @param rb DNS record B as a void-pointer (for pico_tree) * @return 0 when records are equal, returns difference when they're not * ****************************************************************************/ -int -pico_dns_record_cmp( void *ra, - void *rb ) -{ - int dif = 0; - struct pico_dns_record *a = (struct pico_dns_record *)ra; - struct pico_dns_record *b = (struct pico_dns_record *)rb; - - /* Check params */ - if (!a || !b) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* Compare type and name */ - if ((dif = pico_dns_record_cmp_name_type(a, b))) - return dif; - - /* Then compare rdata */ - return pico_dns_rdata_cmp(a->rdata, b->rdata, - short_be(a->rsuffix->rdlength), - short_be(b->rsuffix->rdlength), PICO_DNS_CASE_SENSITIVE); +int pico_dns_record_cmp(void *ra, void *rb) { + int dif = 0; + struct pico_dns_record *a = (struct pico_dns_record *)ra; + struct pico_dns_record *b = (struct pico_dns_record *)rb; + + /* Check params */ + if (!a || !b) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* Compare type and name */ + if ((dif = pico_dns_record_cmp_name_type(a, b))) + return dif; + + /* Then compare rdata */ + return pico_dns_rdata_cmp(a->rdata, b->rdata, short_be(a->rsuffix->rdlength), + short_be(b->rsuffix->rdlength), + PICO_DNS_CASE_SENSITIVE); } /* MARK: ^ COMPARING */ @@ -1195,27 +1130,25 @@ pico_dns_record_cmp( void *ra, * @param node_delete Helper-function for type-specific deleting. * @return Returns 0 on success, something else on failure. * ****************************************************************************/ -int -pico_tree_destroy( struct pico_tree *tree, int (*node_delete)(void **)) -{ - struct pico_tree_node *node = NULL, *next = NULL; - void *item = NULL; - - /* Check params */ - if (!tree) { - pico_err = PICO_ERR_EINVAL; - return -1; - } +int pico_tree_destroy(struct pico_tree *tree, int (*node_delete)(void **)) { + struct pico_tree_node *node = NULL, *next = NULL; + void *item = NULL; + + /* Check params */ + if (!tree) { + pico_err = PICO_ERR_EINVAL; + return -1; + } - pico_tree_foreach_safe(node, tree, next) { - item = node->keyValue; - pico_tree_delete(tree, node->keyValue); - if (item && node_delete) { - node_delete((void **)&item); - } + pico_tree_foreach_safe(node, tree, next) { + item = node->keyValue; + pico_tree_delete(tree, node->keyValue); + if (item && node_delete) { + node_delete((void **)&item); } + } - return 0; + return 0; } /* **************************************************************************** @@ -1224,36 +1157,33 @@ pico_tree_destroy( struct pico_tree *tree, int (*node_delete)(void **)) * * @param tree Pointer to pico_tree-instance * @param size Will get filled with the size of all the nodes summed up. - * Make sure you clear out (set to 0) this param before you - * call this function because it doesn't happen inside and - * each size will be added to the initial value. + * Make sure you clear out (set to 0) this + *param before you call this function because it doesn't happen inside and each + *size will be added to the initial value. * @param node_size Helper-function for type-specific size-determination * @return Amount of items in the tree. * ****************************************************************************/ -static uint16_t -pico_tree_size( struct pico_tree *tree, - uint16_t *size, - uint16_t (*node_size)(void *)) -{ - struct pico_tree_node *node = NULL; - void *node_item = NULL; - uint16_t count = 0; - - /* Check params */ - if (!tree || !size) { - pico_err = PICO_ERR_EINVAL; - return 0; - } +static uint16_t pico_tree_size(struct pico_tree *tree, uint16_t *size, + uint16_t (*node_size)(void *)) { + struct pico_tree_node *node = NULL; + void *node_item = NULL; + uint16_t count = 0; + + /* Check params */ + if (!tree || !size) { + pico_err = PICO_ERR_EINVAL; + return 0; + } - /* Add up the node sizes */ - pico_tree_foreach(node, tree) { - if ((node_item = node->keyValue)) { - *size = (uint16_t)((*size) + node_size(node_item)); - count++; - } + /* Add up the node sizes */ + pico_tree_foreach(node, tree) { + if ((node_item = node->keyValue)) { + *size = (uint16_t)((*size) + node_size(node_item)); + count++; } + } - return count; + return count; } /* **************************************************************************** @@ -1262,18 +1192,16 @@ pico_tree_size( struct pico_tree *tree, * @param tree Pointer to pico_tree-instance * @return Amount of items in the tree. * ****************************************************************************/ -uint16_t -pico_tree_count( struct pico_tree *tree ) -{ - struct pico_tree_node *node = NULL; - uint16_t count = 0; - - pico_tree_foreach(node, tree) { - if (node->keyValue) - count++; - } +uint16_t pico_tree_count(struct pico_tree *tree) { + struct pico_tree_node *node = NULL; + uint16_t count = 0; + + pico_tree_foreach(node, tree) { + if (node->keyValue) + count++; + } - return count; + return count; } /* **************************************************************************** @@ -1283,29 +1211,26 @@ pico_tree_count( struct pico_tree *tree ) * @param name Name of the questions you want to delete * @return Returns 0 on success, something else on failure. * ****************************************************************************/ -int -pico_dns_qtree_del_name( struct pico_tree *qtree, - const char *name ) -{ - struct pico_tree_node *node = NULL, *next = NULL; - struct pico_dns_question *question = NULL; - - /* Check params */ - if (!qtree || !name) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* Iterate over tree and delete every node with given name */ - pico_tree_foreach_safe(node, qtree, next) { - question = (struct pico_dns_question *)node->keyValue; - if ((question) && (strcasecmp(question->qname, name) == 0)) { - question = pico_tree_delete(qtree, (void *)question); - pico_dns_question_delete((void **)&question); - } - } - - return 0; +int pico_dns_qtree_del_name(struct pico_tree *qtree, const char *name) { + struct pico_tree_node *node = NULL, *next = NULL; + struct pico_dns_question *question = NULL; + + /* Check params */ + if (!qtree || !name) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* Iterate over tree and delete every node with given name */ + pico_tree_foreach_safe(node, qtree, next) { + question = (struct pico_dns_question *)node->keyValue; + if ((question) && (strcasecmp(question->qname, name) == 0)) { + question = pico_tree_delete(qtree, (void *)question); + pico_dns_question_delete((void **)&question); + } + } + + return 0; } /* **************************************************************************** @@ -1315,27 +1240,24 @@ pico_dns_qtree_del_name( struct pico_tree *qtree, * @param name Name you want to check for * @return 1 when the name is present in the qtree, 0 when it's not. * ****************************************************************************/ -int -pico_dns_qtree_find_name( struct pico_tree *qtree, - const char *name ) -{ - struct pico_tree_node *node = NULL; - struct pico_dns_question *question = NULL; - - /* Check params */ - if (!qtree || !name) { - pico_err = PICO_ERR_EINVAL; - return 0; - } - - /* Iterate over tree and compare names */ - pico_tree_foreach(node, qtree) { - question = (struct pico_dns_question *)node->keyValue; - if ((question) && (strcasecmp(question->qname, name) == 0)) - return 1; - } +int pico_dns_qtree_find_name(struct pico_tree *qtree, const char *name) { + struct pico_tree_node *node = NULL; + struct pico_dns_question *question = NULL; + /* Check params */ + if (!qtree || !name) { + pico_err = PICO_ERR_EINVAL; return 0; + } + + /* Iterate over tree and compare names */ + pico_tree_foreach(node, qtree) { + question = (struct pico_dns_question *)node->keyValue; + if ((question) && (strcasecmp(question->qname, name) == 0)) + return 1; + } + + return 0; } /* MARK: ^ PICO_TREE */ @@ -1351,34 +1273,30 @@ pico_dns_qtree_find_name( struct pico_tree *qtree, * @param nscount Amount of authority records added to the packet * @param arcount Amount of additional records added to the packet * ****************************************************************************/ -void -pico_dns_fill_packet_header( struct pico_dns_header *hdr, - uint16_t qdcount, - uint16_t ancount, - uint16_t nscount, - uint16_t arcount ) -{ - /* ID should be filled by caller */ - - if(qdcount > 0) { /* Questions present? Make it a query */ - hdr->qr = PICO_DNS_QR_QUERY; - hdr->aa = PICO_DNS_AA_NO_AUTHORITY; - } else { /* No questions present? Make it an answer*/ - hdr->qr = PICO_DNS_QR_RESPONSE; - hdr->aa = PICO_DNS_AA_IS_AUTHORITY; - } - - /* Fill in the flags and the fields */ - hdr->opcode = PICO_DNS_OPCODE_QUERY; - hdr->tc = PICO_DNS_TC_NO_TRUNCATION; - hdr->rd = PICO_DNS_RD_IS_DESIRED; - hdr->ra = PICO_DNS_RA_NO_SUPPORT; - hdr->z = 0; /* Z, AD, CD are 0 */ - hdr->rcode = PICO_DNS_RCODE_NO_ERROR; - hdr->qdcount = short_be(qdcount); - hdr->ancount = short_be(ancount); - hdr->nscount = short_be(nscount); - hdr->arcount = short_be(arcount); +void pico_dns_fill_packet_header(struct pico_dns_header *hdr, uint16_t qdcount, + uint16_t ancount, uint16_t nscount, + uint16_t arcount) { + /* ID should be filled by caller */ + + if (qdcount > 0) { /* Questions present? Make it a query */ + hdr->qr = PICO_DNS_QR_QUERY; + hdr->aa = PICO_DNS_AA_NO_AUTHORITY; + } else { /* No questions present? Make it an answer*/ + hdr->qr = PICO_DNS_QR_RESPONSE; + hdr->aa = PICO_DNS_AA_IS_AUTHORITY; + } + + /* Fill in the flags and the fields */ + hdr->opcode = PICO_DNS_OPCODE_QUERY; + hdr->tc = PICO_DNS_TC_NO_TRUNCATION; + hdr->rd = PICO_DNS_RD_IS_DESIRED; + hdr->ra = PICO_DNS_RA_NO_SUPPORT; + hdr->z = 0; /* Z, AD, CD are 0 */ + hdr->rcode = PICO_DNS_RCODE_NO_ERROR; + hdr->qdcount = short_be(qdcount); + hdr->ancount = short_be(ancount); + hdr->nscount = short_be(nscount); + hdr->arcount = short_be(arcount); } /* **************************************************************************** @@ -1386,24 +1304,23 @@ pico_dns_fill_packet_header( struct pico_dns_header *hdr, * * @param rtree Tree that contains the DNS resource records. * @param dest Pointer-pointer to location where you want to insert records. - * Will point to location after current section on return. + * Will point to location after current section on + *return. * @return 0 on success, something else on failure. * ****************************************************************************/ -static int -pico_dns_fill_packet_rr_section( struct pico_tree *rtree, - uint8_t **dest ) -{ - struct pico_tree_node *node = NULL; - struct pico_dns_record *record = NULL; - - pico_tree_foreach(node, rtree) { - record = node->keyValue; - if ((record) && pico_dns_record_copy_flat(record, dest)) { - dns_dbg("Could not copy record into Answer Section!\n"); - return -1; - } - } - return 0; +static int pico_dns_fill_packet_rr_section(struct pico_tree *rtree, + uint8_t **dest) { + struct pico_tree_node *node = NULL; + struct pico_dns_record *record = NULL; + + pico_tree_foreach(node, rtree) { + record = node->keyValue; + if ((record) && pico_dns_record_copy_flat(record, dest)) { + dns_dbg("Could not copy record into Answer Section!\n"); + return -1; + } + } + return 0; } /* **************************************************************************** @@ -1417,41 +1334,39 @@ pico_dns_fill_packet_rr_section( struct pico_tree *rtree, * @param artree DNS records to put in Additional section * @return 0 on success, something else on failure. * ****************************************************************************/ -static int -pico_dns_fill_packet_rr_sections( pico_dns_packet *packet, - struct pico_tree *qtree, - struct pico_tree *antree, - struct pico_tree *nstree, - struct pico_tree *artree ) -{ - int anret = 0, nsret = 0, arret = 0; - uint16_t temp = 0; - uint8_t *destination = NULL; - - /* Check params */ - if (!packet || !qtree || !antree || !nstree || !artree) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* Initialise the destination pointers before iterating */ - destination = (uint8_t *)packet + sizeof(struct pico_dns_header); - pico_tree_size(qtree, &temp, &pico_dns_question_size); - destination = destination + temp; - - /* Iterate over ANSWERS */ - anret = pico_dns_fill_packet_rr_section(antree, &destination); - - /* Iterate over AUTHORITIES */ - nsret = pico_dns_fill_packet_rr_section(nstree, &destination); - - /* Iterate over ADDITIONALS */ - arret = pico_dns_fill_packet_rr_section(artree, &destination); - - if (anret || nsret || arret) - return -1; - - return 0; +static int pico_dns_fill_packet_rr_sections(pico_dns_packet *packet, + struct pico_tree *qtree, + struct pico_tree *antree, + struct pico_tree *nstree, + struct pico_tree *artree) { + int anret = 0, nsret = 0, arret = 0; + uint16_t temp = 0; + uint8_t *destination = NULL; + + /* Check params */ + if (!packet || !qtree || !antree || !nstree || !artree) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* Initialise the destination pointers before iterating */ + destination = (uint8_t *)packet + sizeof(struct pico_dns_header); + pico_tree_size(qtree, &temp, &pico_dns_question_size); + destination = destination + temp; + + /* Iterate over ANSWERS */ + anret = pico_dns_fill_packet_rr_section(antree, &destination); + + /* Iterate over AUTHORITIES */ + nsret = pico_dns_fill_packet_rr_section(nstree, &destination); + + /* Iterate over ADDITIONALS */ + arret = pico_dns_fill_packet_rr_section(artree, &destination); + + if (anret || nsret || arret) + return -1; + + return 0; } /* **************************************************************************** @@ -1462,222 +1377,211 @@ pico_dns_fill_packet_rr_sections( pico_dns_packet *packet, * @param qtree Question tree with question you want to insert * @return 0 on success, something else on failure. * ****************************************************************************/ -static int -pico_dns_fill_packet_question_section( pico_dns_packet *packet, - struct pico_tree *qtree ) -{ - struct pico_tree_node *node = NULL; - struct pico_dns_question *question = NULL; - struct pico_dns_question_suffix *dest_qsuffix = NULL; - char *dest_qname = NULL; - - /* Check params */ - if (!packet || !qtree) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* Initialise pointer */ - dest_qname = (char *)((char *)packet + sizeof(struct pico_dns_header)); - - pico_tree_foreach(node, qtree) { - question = node->keyValue; - if (question) { - /* Copy the name */ - memcpy(dest_qname, question->qname, question->qname_length); - - /* Copy the suffix */ - dest_qsuffix = (struct pico_dns_question_suffix *) - (dest_qname + question->qname_length); - dest_qsuffix->qtype = question->qsuffix->qtype; - dest_qsuffix->qclass = question->qsuffix->qclass; - - /* Move to next question */ - dest_qname = (char *)((char *)dest_qsuffix + - sizeof(struct pico_dns_question_suffix)); - } - } - return 0; +static int pico_dns_fill_packet_question_section(pico_dns_packet *packet, + struct pico_tree *qtree) { + struct pico_tree_node *node = NULL; + struct pico_dns_question *question = NULL; + struct pico_dns_question_suffix *dest_qsuffix = NULL; + char *dest_qname = NULL; + + /* Check params */ + if (!packet || !qtree) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* Initialise pointer */ + dest_qname = (char *)((char *)packet + sizeof(struct pico_dns_header)); + + pico_tree_foreach(node, qtree) { + question = node->keyValue; + if (question) { + /* Copy the name */ + memcpy(dest_qname, question->qname, question->qname_length); + + /* Copy the suffix */ + dest_qsuffix = + (struct pico_dns_question_suffix *)(dest_qname + + question->qname_length); + dest_qsuffix->qtype = question->qsuffix->qtype; + dest_qsuffix->qclass = question->qsuffix->qclass; + + /* Move to next question */ + dest_qname = (char *)((char *)dest_qsuffix + + sizeof(struct pico_dns_question_suffix)); + } + } + return 0; } /* **************************************************************************** * Looks for a name somewhere else in packet, more specifically between the * beginning of the data buffer and the name itself. * ****************************************************************************/ -static uint8_t * -pico_dns_packet_compress_find_ptr( uint8_t *name, - uint8_t *data, - uint16_t len ) -{ - uint8_t *iterator = NULL; - - /* Check params */ - if (!name || !data || !len) - return NULL; - - if ((name < data) || (name > (data + len))) - return NULL; +static uint8_t *pico_dns_packet_compress_find_ptr(uint8_t *name, uint8_t *data, + uint16_t len) { + uint8_t *iterator = NULL; - iterator = data; + /* Check params */ + if (!name || !data || !len) + return NULL; - /* Iterate from the beginning of data up until the name-ptr */ - while (iterator < name) { - /* Compare in each iteration of current name is equal to a section of - the DNS packet and if so return the pointer to that section */ - if (memcmp((void *)iterator++, (void *)name, - pico_dns_strlen((char *)name) + 1u) == 0) - return (iterator - 1); - } + if ((name < data) || (name > (data + len))) return NULL; + + iterator = data; + + /* Iterate from the beginning of data up until the name-ptr */ + while (iterator < name) { + /* Compare in each iteration of current name is equal to a section of + the DNS packet and if so return the pointer to that section */ + if (memcmp((void *)iterator++, (void *)name, + pico_dns_strlen((char *)name) + 1u) == 0) + return (iterator - 1); + } + return NULL; } /* **************************************************************************** * Compresses a single name by looking for the same name somewhere else in the * packet-buffer. * ****************************************************************************/ -static int -pico_dns_packet_compress_name( uint8_t *name, - uint8_t *packet, - uint16_t *len) -{ - uint8_t *lbl_iterator = NULL; /* To iterate over labels */ - uint8_t *compression_ptr = NULL; /* PTR to somewhere else in the packet */ - uint8_t *offset = NULL; /* PTR after compression pointer */ - uint8_t *ptr_after_str = NULL; - uint8_t *last_byte = NULL; - uint8_t *i = NULL; - uint16_t ptr = 0; - uint16_t difference = 0; - - /* Check params */ - if (!name || !packet || !len) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - if ((name < packet) || (name > (packet + *len))) { - dns_dbg("Name ptr OOB. name: %p max: %p\n", name, packet + *len); - pico_err = PICO_ERR_EINVAL; - return -1; - } - - /* Try to compress name */ - lbl_iterator = name; - while (*lbl_iterator != '\0') { - /* Try to find a compression pointer with current name */ - compression_ptr = pico_dns_packet_compress_find_ptr(lbl_iterator, - packet + 12, *len); - /* If name can be compressed */ - if (compression_ptr) { - /* Point to place after current string */ - ptr_after_str = lbl_iterator + strlen((char *)lbl_iterator) + 1u; - - /* Calculate the compression pointer value */ - ptr = (uint16_t)(compression_ptr - packet); - - /* Set the compression pointer in the packet */ - *lbl_iterator = (uint8_t)(0xC0 | (uint8_t)(ptr >> 8)); - *(lbl_iterator + 1) = (uint8_t)(ptr & 0xFF); - - /* Move up the rest of the packet data to right after the pointer */ - offset = lbl_iterator + 2; - - /* Move up left over data */ - difference = (uint16_t)(ptr_after_str - offset); - last_byte = packet + *len; - for (i = ptr_after_str; i < last_byte; i++) { - *((uint8_t *)(i - difference)) = *i; - } - /* Update length */ - *len = (uint16_t)(*len - difference); - break; - } - - /* Move to next length label */ - lbl_iterator = lbl_iterator + *(lbl_iterator) + 1; - } - return 0; +static int pico_dns_packet_compress_name(uint8_t *name, uint8_t *packet, + uint16_t *len) { + uint8_t *lbl_iterator = NULL; /* To iterate over labels */ + uint8_t *compression_ptr = NULL; /* PTR to somewhere else in the packet */ + uint8_t *offset = NULL; /* PTR after compression pointer */ + uint8_t *ptr_after_str = NULL; + uint8_t *last_byte = NULL; + uint8_t *i = NULL; + uint16_t ptr = 0; + uint16_t difference = 0; + + /* Check params */ + if (!name || !packet || !len) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + if ((name < packet) || (name > (packet + *len))) { + dns_dbg("Name ptr OOB. name: %p max: %p\n", name, packet + *len); + pico_err = PICO_ERR_EINVAL; + return -1; + } + + /* Try to compress name */ + lbl_iterator = name; + while (*lbl_iterator != '\0') { + /* Try to find a compression pointer with current name */ + compression_ptr = + pico_dns_packet_compress_find_ptr(lbl_iterator, packet + 12, *len); + /* If name can be compressed */ + if (compression_ptr) { + /* Point to place after current string */ + ptr_after_str = lbl_iterator + strlen((char *)lbl_iterator) + 1u; + + /* Calculate the compression pointer value */ + ptr = (uint16_t)(compression_ptr - packet); + + /* Set the compression pointer in the packet */ + *lbl_iterator = (uint8_t)(0xC0 | (uint8_t)(ptr >> 8)); + *(lbl_iterator + 1) = (uint8_t)(ptr & 0xFF); + + /* Move up the rest of the packet data to right after the pointer */ + offset = lbl_iterator + 2; + + /* Move up left over data */ + difference = (uint16_t)(ptr_after_str - offset); + last_byte = packet + *len; + for (i = ptr_after_str; i < last_byte; i++) { + *((uint8_t *)(i - difference)) = *i; + } + /* Update length */ + *len = (uint16_t)(*len - difference); + break; + } + + /* Move to next length label */ + lbl_iterator = lbl_iterator + *(lbl_iterator) + 1; + } + return 0; } /* **************************************************************************** * Utility function compress a record section * ****************************************************************************/ -static int -pico_dns_compress_record_sections( uint16_t qdcount, uint16_t count, - uint8_t *buf, uint8_t **iterator, - uint16_t *len ) -{ - struct pico_dns_record_suffix *rsuffix = NULL; - uint8_t *_iterator = NULL; - uint16_t i = 0; - - /* Check params */ - if (!iterator || !(*iterator) || !buf || !len) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - _iterator = *iterator; - - for (i = 0; i < count; i++) { - if (qdcount || i) - pico_dns_packet_compress_name(_iterator, buf, len); - - /* To get rdlength */ - rsuffix = (struct pico_dns_record_suffix *) - (_iterator + pico_dns_namelen_comp((char *)_iterator) + 1u); - - /* Move to next res record */ - _iterator = ((uint8_t *)rsuffix + - sizeof(struct pico_dns_record_suffix) + - short_be(rsuffix->rdlength)); - } - *iterator = _iterator; - return 0; +static int pico_dns_compress_record_sections(uint16_t qdcount, uint16_t count, + uint8_t *buf, uint8_t **iterator, + uint16_t *len) { + struct pico_dns_record_suffix *rsuffix = NULL; + uint8_t *_iterator = NULL; + uint16_t i = 0; + + /* Check params */ + if (!iterator || !(*iterator) || !buf || !len) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + _iterator = *iterator; + + for (i = 0; i < count; i++) { + if (qdcount || i) + pico_dns_packet_compress_name(_iterator, buf, len); + + /* To get rdlength */ + rsuffix = (struct pico_dns_record_suffix *)(_iterator + + pico_dns_namelen_comp( + (char *)_iterator) + + 1u); + + /* Move to next res record */ + _iterator = ((uint8_t *)rsuffix + sizeof(struct pico_dns_record_suffix) + + short_be(rsuffix->rdlength)); + } + *iterator = _iterator; + return 0; } /* **************************************************************************** * Applies DNS name compression to an entire DNS packet * ****************************************************************************/ -static int -pico_dns_packet_compress( pico_dns_packet *packet, uint16_t *len ) -{ - uint8_t *packet_buf = NULL; - uint8_t *iterator = NULL; - uint16_t qdcount = 0, rcount = 0, i = 0; - - /* Check params */ - if (!packet || !len) { - pico_err = PICO_ERR_EINVAL; - return -1; - } - - packet_buf = (uint8_t *)packet; - - /* Temporarily store the question & record counts */ - qdcount = short_be(packet->qdcount); - rcount = (uint16_t)(rcount + short_be(packet->ancount)); - rcount = (uint16_t)(rcount + short_be(packet->nscount)); - rcount = (uint16_t)(rcount + short_be(packet->arcount)); - - /* Move past the DNS packet header */ - iterator = (uint8_t *)((uint8_t *) packet + 12u); - - /* Start with the questions */ - for (i = 0; i < qdcount; i++) { - if(i) { /* First question can't be compressed */ - pico_dns_packet_compress_name(iterator, packet_buf, len); - } - - /* Move to next question */ - iterator = (uint8_t *)(iterator + - pico_dns_namelen_comp((char *)iterator) + - sizeof(struct pico_dns_question_suffix) + 1u); - } - /* Then onto the answers */ - pico_dns_compress_record_sections(qdcount, rcount, packet_buf, &iterator, - len); - return 0; +static int pico_dns_packet_compress(pico_dns_packet *packet, uint16_t *len) { + uint8_t *packet_buf = NULL; + uint8_t *iterator = NULL; + uint16_t qdcount = 0, rcount = 0, i = 0; + + /* Check params */ + if (!packet || !len) { + pico_err = PICO_ERR_EINVAL; + return -1; + } + + packet_buf = (uint8_t *)packet; + + /* Temporarily store the question & record counts */ + qdcount = short_be(packet->qdcount); + rcount = (uint16_t)(rcount + short_be(packet->ancount)); + rcount = (uint16_t)(rcount + short_be(packet->nscount)); + rcount = (uint16_t)(rcount + short_be(packet->arcount)); + + /* Move past the DNS packet header */ + iterator = (uint8_t *)((uint8_t *)packet + 12u); + + /* Start with the questions */ + for (i = 0; i < qdcount; i++) { + if (i) { /* First question can't be compressed */ + pico_dns_packet_compress_name(iterator, packet_buf, len); + } + + /* Move to next question */ + iterator = (uint8_t *)(iterator + pico_dns_namelen_comp((char *)iterator) + + sizeof(struct pico_dns_question_suffix) + 1u); + } + /* Then onto the answers */ + pico_dns_compress_record_sections(qdcount, rcount, packet_buf, &iterator, + len); + return 0; } /* **************************************************************************** @@ -1694,27 +1598,25 @@ pico_dns_packet_compress( pico_dns_packet *packet, uint16_t *len ) * @param arcount Pointer to var to store amount of additionals. * @return Returns the total length that the DNS packet needs to be. * ****************************************************************************/ -static uint16_t -pico_dns_packet_len( struct pico_tree *qtree, - struct pico_tree *antree, - struct pico_tree *nstree, - struct pico_tree *artree, - uint8_t *qdcount, uint8_t *ancount, - uint8_t *nscount, uint8_t *arcount ) -{ - uint16_t len = (uint16_t) sizeof(pico_dns_packet); - - /* Check params */ - if (!qtree || !antree || !nstree || !artree) { - pico_err = PICO_ERR_EINVAL; - return 0; - } +static uint16_t pico_dns_packet_len(struct pico_tree *qtree, + struct pico_tree *antree, + struct pico_tree *nstree, + struct pico_tree *artree, uint8_t *qdcount, + uint8_t *ancount, uint8_t *nscount, + uint8_t *arcount) { + uint16_t len = (uint16_t)sizeof(pico_dns_packet); + + /* Check params */ + if (!qtree || !antree || !nstree || !artree) { + pico_err = PICO_ERR_EINVAL; + return 0; + } - *qdcount = (uint8_t)pico_tree_size(qtree, &len, &pico_dns_question_size); - *ancount = (uint8_t)pico_tree_size(antree, &len, &pico_dns_record_size); - *nscount = (uint8_t)pico_tree_size(nstree, &len, &pico_dns_record_size); - *arcount = (uint8_t)pico_tree_size(artree, &len, &pico_dns_record_size); - return len; + *qdcount = (uint8_t)pico_tree_size(qtree, &len, &pico_dns_question_size); + *ancount = (uint8_t)pico_tree_size(antree, &len, &pico_dns_record_size); + *nscount = (uint8_t)pico_tree_size(nstree, &len, &pico_dns_record_size); + *arcount = (uint8_t)pico_tree_size(artree, &len, &pico_dns_record_size); + return len; } /* **************************************************************************** @@ -1730,56 +1632,54 @@ pico_dns_packet_len( struct pico_tree *qtree, * @param len Will get fill with the entire size of the packet * @return Pointer to created DNS packet * ****************************************************************************/ -static pico_dns_packet * -pico_dns_packet_create( struct pico_tree *qtree, - struct pico_tree *antree, - struct pico_tree *nstree, - struct pico_tree *artree, - uint16_t *len ) -{ - PICO_DNS_QTREE_DECLARE(_qtree); - PICO_DNS_RTREE_DECLARE(_antree); - PICO_DNS_RTREE_DECLARE(_nstree); - PICO_DNS_RTREE_DECLARE(_artree); - pico_dns_packet *packet = NULL; - uint8_t qdcount = 0, ancount = 0, nscount = 0, arcount = 0; - - /* Set default vector, if arguments are NULL-pointers */ - _qtree = (qtree) ? (*qtree) : (_qtree); - _antree = (antree) ? (*antree) : (_antree); - _nstree = (nstree) ? (*nstree) : (_nstree); - _artree = (artree) ? (*artree) : (_artree); - - /* Get the size of the entire packet and determine the header counters */ - *len = pico_dns_packet_len(&_qtree, &_antree, &_nstree, &_artree, - &qdcount, &ancount, &nscount, &arcount); - - /* Provide space for the entire packet */ - if (!(packet = PICO_ZALLOC(*len))) { - pico_err = PICO_ERR_ENOMEM; - return NULL; - } +static pico_dns_packet *pico_dns_packet_create(struct pico_tree *qtree, + struct pico_tree *antree, + struct pico_tree *nstree, + struct pico_tree *artree, + uint16_t *len) { + PICO_DNS_QTREE_DECLARE(_qtree); + PICO_DNS_RTREE_DECLARE(_antree); + PICO_DNS_RTREE_DECLARE(_nstree); + PICO_DNS_RTREE_DECLARE(_artree); + pico_dns_packet *packet = NULL; + uint8_t qdcount = 0, ancount = 0, nscount = 0, arcount = 0; + + /* Set default vector, if arguments are NULL-pointers */ + _qtree = (qtree) ? (*qtree) : (_qtree); + _antree = (antree) ? (*antree) : (_antree); + _nstree = (nstree) ? (*nstree) : (_nstree); + _artree = (artree) ? (*artree) : (_artree); + + /* Get the size of the entire packet and determine the header counters */ + *len = pico_dns_packet_len(&_qtree, &_antree, &_nstree, &_artree, &qdcount, + &ancount, &nscount, &arcount); + + /* Provide space for the entire packet */ + if (!(packet = PICO_ZALLOC(*len))) { + pico_err = PICO_ERR_ENOMEM; + return NULL; + } - /* Fill the Question Section with questions */ - if (qtree && pico_tree_count(&_qtree) != 0) { - if (pico_dns_fill_packet_question_section(packet, &_qtree)) { - dns_dbg("Could not fill Question Section correctly!\n"); - return NULL; - } + /* Fill the Question Section with questions */ + if (qtree && pico_tree_count(&_qtree) != 0) { + if (pico_dns_fill_packet_question_section(packet, &_qtree)) { + dns_dbg("Could not fill Question Section correctly!\n"); + return NULL; } + } - /* Fill the Resource Record Sections with resource records */ - if (pico_dns_fill_packet_rr_sections(packet, &_qtree, &_antree, - &_nstree, &_artree)) { - dns_dbg("Could not fill Resource Record Sections correctly!\n"); - return NULL; - } + /* Fill the Resource Record Sections with resource records */ + if (pico_dns_fill_packet_rr_sections(packet, &_qtree, &_antree, &_nstree, + &_artree)) { + dns_dbg("Could not fill Resource Record Sections correctly!\n"); + return NULL; + } - /* Fill the DNS packet header and try to compress */ - pico_dns_fill_packet_header(packet, qdcount, ancount, nscount, arcount); - pico_dns_packet_compress(packet, len); + /* Fill the DNS packet header and try to compress */ + pico_dns_fill_packet_header(packet, qdcount, ancount, nscount, arcount); + pico_dns_packet_compress(packet, len); - return packet; + return packet; } /* **************************************************************************** @@ -1794,14 +1694,12 @@ pico_dns_packet_create( struct pico_tree *qtree, * @param len Will get filled with the entire size of the packet * @return Pointer to created DNS packet * ****************************************************************************/ -pico_dns_packet * -pico_dns_query_create( struct pico_tree *qtree, - struct pico_tree *antree, - struct pico_tree *nstree, - struct pico_tree *artree, - uint16_t *len ) -{ - return pico_dns_packet_create(qtree, antree, nstree, artree, len); +pico_dns_packet *pico_dns_query_create(struct pico_tree *qtree, + struct pico_tree *antree, + struct pico_tree *nstree, + struct pico_tree *artree, + uint16_t *len) { + return pico_dns_packet_create(qtree, antree, nstree, artree, len); } /* **************************************************************************** @@ -1815,12 +1713,10 @@ pico_dns_query_create( struct pico_tree *qtree, * @param len Will get filled with the entire size of the packet * @return Pointer to created DNS packet. * ****************************************************************************/ -pico_dns_packet * -pico_dns_answer_create( struct pico_tree *antree, - struct pico_tree *nstree, - struct pico_tree *artree, - uint16_t *len ) -{ - return pico_dns_packet_create(NULL, antree, nstree, artree, len); +pico_dns_packet *pico_dns_answer_create(struct pico_tree *antree, + struct pico_tree *nstree, + struct pico_tree *artree, + uint16_t *len) { + return pico_dns_packet_create(NULL, antree, nstree, artree, len); } /* MARK: ^ DNS PACKET FUNCTIONS */ diff --git a/modules/pico_dns_sd.c b/modules/pico_dns_sd.c index a5a2a7f9..b2c31b46 100644 --- a/modules/pico_dns_sd.c +++ b/modules/pico_dns_sd.c @@ -1,12 +1,12 @@ /********************************************************************* - * PicoTCP-NG + * PicoTCP-NG * Copyright (c) 2020 Daniele Lacamera * * This file also includes code from: * PicoTCP * Copyright (c) 2012-2017 Altran Intelligent Systems * Authors: Jelle De Vleeschouwer - * + * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only * * PicoTCP-NG is free software; you can redistribute it and/or modify @@ -73,9 +73,26 @@ pico_dns_sd_kv_vector_strlen( kv_vector *vector ) /* Iterate over the key-value pairs */ for (i = 0; i < vector->count; i++) { iterator = pico_dns_sd_kv_vector_get(vector, i); + + if (!iterator || iterator->key){ + pico_err = PICO_ERR_EINVAL; + return 0; + } + + if (len + 1u + strlen(iterator->key) > PICO_DNS_SD_KV_MAXLEN) { + pico_err = PICO_ERR_EINVAL; + return 0; + } + len = (uint16_t) (len + 1u + /* Length byte */ strlen(iterator->key) /* Length of the key */); + if (iterator->value) { + if (len + 1u + strlen(iterator->value) > PICO_DNS_SD_KV_MAXLEN) { + pico_err = PICO_ERR_EINVAL; + return 0; + } + len = (uint16_t) (len + 1u /* '=' char */ + strlen(iterator->value) /* Length of value */); } diff --git a/modules/pico_dns_sd.h b/modules/pico_dns_sd.h index d0b1a961..cd4da6f6 100644 --- a/modules/pico_dns_sd.h +++ b/modules/pico_dns_sd.h @@ -1,11 +1,11 @@ /********************************************************************* - * PicoTCP-NG + * PicoTCP-NG * Copyright (c) 2020 Daniele Lacamera * * This file also includes code from: * PicoTCP * Copyright (c) 2012-2017 Altran Intelligent Systems - * + * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only * * PicoTCP-NG is free software; you can redistribute it and/or modify @@ -44,6 +44,11 @@ typedef struct #define PICO_DNS_SD_KV_VECTOR_DECLARE(name) \ kv_vector (name) = {0} +/* **************************************************************************** + * Maximum length of a key-value pair. + * ****************************************************************************/ +#define PICO_DNS_SD_KV_MAXLEN (0xFFFFu) + /* **************************************************************************** * Just calls pico_mdns_init in it's turn to initialise the mDNS-module. * See pico_mdns.h for description. @@ -108,4 +113,3 @@ pico_dns_sd_kv_vector_add( kv_vector *vector, char *key, char *value ); #endif /* _INCLUDE_PICO_DNS_SD */ - diff --git a/modules/pico_mdns.c b/modules/pico_mdns.c index fa98b851..fb8ca2db 100644 --- a/modules/pico_mdns.c +++ b/modules/pico_mdns.c @@ -1,12 +1,12 @@ /********************************************************************* - * PicoTCP-NG + * PicoTCP-NG * Copyright (c) 2020 Daniele Lacamera * * This file also includes code from: * PicoTCP * Copyright (c) 2012-2017 Altran Intelligent Systems * Authors: Toon Stegen, Jelle De Vleeschouwer - * + * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only * * PicoTCP-NG is free software; you can redistribute it and/or modify @@ -26,6 +26,7 @@ * *********************************************************************/ #include "pico_config.h" +#include "pico_dns_common.h" #include "pico_stack.h" #include "pico_addressing.h" #include "pico_socket.h" @@ -934,7 +935,7 @@ pico_mdns_record_delete( void **record ) * Creates a single standalone mDNS resource record with given name, type and * data. * - * @param S TCP/IP stack reference + * @param S TCP/IP stack reference * @param url DNS rrecord name in URL format. Will be converted to DNS * name notation format. * @param _rdata Memory buffer with data to insert in the resource record. If @@ -1040,7 +1041,7 @@ pico_mdns_cookie_delete( void **ptr ) /* **************************************************************************** * Creates a single standalone mDNS cookie * - * @param S TCP/IP stack reference + * @param S TCP/IP stack reference * @param qtree DNS questions you want to insert in the cookie. * @param antree mDNS answers/authority records you want to add to cookie. * @param artree mDNS additional records you want to add to cookie. @@ -1050,7 +1051,7 @@ pico_mdns_cookie_delete( void **ptr ) * @return Pointer to newly create cookie, NULL on failure. * ****************************************************************************/ static struct pico_mdns_cookie * -pico_mdns_cookie_create( struct pico_stack *S, +pico_mdns_cookie_create( struct pico_stack *S, pico_dns_qtree qtree, pico_mdns_rtree antree, pico_mdns_rtree artree, @@ -1466,7 +1467,7 @@ pico_mdns_my_records_probed( pico_mdns_rtree *records ) PICO_FREE(record->stack->mdns_hostname); } /* Re-allocate hostname from given rname */ - record->stack->mdns_hostname = + record->stack->mdns_hostname = pico_dns_qname_to_url(found->record->rname); } @@ -2190,6 +2191,12 @@ pico_mdns_handle_data_as_answers_generic(struct pico_stack *S, return -1; } + // check that the number of answare/response corrispond to the number of questions + if (count != pico_tree_count(&S->MDNSOwnRecords)) { + mdns_dbg("Number of answers does not match the number of questions\n"); + return -1; + } + /* TODO: When receiving multiple authoritative answers, */ /* they should be sorted in lexicographical order */ /* (just like in pico_mdns_record_am_i_lexi_later) */ @@ -3000,7 +3007,7 @@ pico_mdns_getrecord_generic(struct pico_stack *S, const char *url, uint16_t typ } /* Associate the current TCP/IP stack reference to access relevant - * fields/trees + * fields/trees */ q->stack = S; diff --git a/modules/pico_mdns.h b/modules/pico_mdns.h index dbf78049..eea1a1c1 100644 --- a/modules/pico_mdns.h +++ b/modules/pico_mdns.h @@ -1,11 +1,11 @@ /* **************************************************************************** - * PicoTCP-NG + * PicoTCP-NG * Copyright (c) 2020 Daniele Lacamera * * This file also includes code from: * PicoTCP * Copyright (c) 2012-2017 Altran Intelligent Systems - * + * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only * * PicoTCP-NG is free software; you can redistribute it and/or modify