diff --git a/include/dns.h b/include/dns.h index 141c9ce3be9d4b952a47d4eebbbcf393b9402e2f..707a5e067bcdbd58074b64fa9c1fd93295ab6bb2 100644 --- a/include/dns.h +++ b/include/dns.h @@ -82,13 +82,25 @@ typedef struct dns_question { uint16_t qclass; } dns_question_t; +/** + * @brief RDATA field of a DNS SRV Resource Record + * + */ +typedef struct srv_data { + uint16_t priority; + uint16_t weight; + uint16_t port; + char *target; +} srv_data_t; + /** * RDATA field of a DNS Resource Record */ typedef union { - char *domain_name; // Domain name, character string - ip_addr_t ip; // IP (v4 or v6) address - uint8_t *data; // Generic data, series of bytes + char *domain_name; // Domain name, character string + ip_addr_t ip; // IP (v4 or v6) address + srv_data_t srv_data; // SRV data + uint8_t *data; // Generic data, series of bytes } rdata_t; /** diff --git a/src/dns.c b/src/dns.c index 3b7c305047bcf4393161ad0e9beec17299dcd1d1..8a33cd0f5e1c7097cb7f4f19f7b4ee86bc387936 100644 --- a/src/dns.c +++ b/src/dns.c @@ -142,9 +142,29 @@ dns_question_t* dns_parse_questions(uint16_t qdcount, uint8_t *data, uint16_t *o return questions; } +/** + * @brief Parse the RDATA field of a SRV DNS Resource Record. + * + * @param rdlength the length, in bytes, of the RDATA field + * @param data pointer to the start of the DNS message + * @param offset pointer to the current parsing offset + * @return the parsed SRV RDATA field + */ +srv_data_t dns_parse_srv_data(uint8_t *data, uint16_t *offset) +{ + srv_data_t srv_data; + srv_data.priority = ntohs(*((uint16_t *) (data + *offset))); + srv_data.weight = ntohs(*((uint16_t *) (data + *offset + 2))); + srv_data.port = ntohs(*((uint16_t *) (data + *offset + 4))); + *offset += 6; + srv_data.target = dns_parse_domain_name(data, offset); + return srv_data; +} + /** * Parse a DNS Resource Record RDATA field. * + * @param rtype Resource Record type * @param rdlength the length, in bytes, of the RDATA field * @param data a pointer pointing to the start of the DNS message * @param offset a pointer to the current parsing offset @@ -173,9 +193,13 @@ static rdata_t dns_parse_rdata(dns_rr_type_t rtype, uint16_t rdlength, uint8_t * case NS: case CNAME: case PTR: - // RDATA contains is a domain name + // RDATA contains a domain name rdata.domain_name = dns_parse_domain_name(data, offset); break; + case SRV: + // RDATA contains SRV data + rdata.srv_data = dns_parse_srv_data(data, offset); + break; default: // RDATA contains is generic data rdata.data = (uint8_t *) malloc(sizeof(char) * rdlength); @@ -556,6 +580,9 @@ static void dns_free_rdata(rdata_t rdata, dns_rr_type_t rtype) { case PTR: free(rdata.domain_name); break; + case SRV: + free(rdata.srv_data.target); + break; default: free(rdata.data); } @@ -679,6 +706,10 @@ char* dns_rdata_to_str(dns_rr_type_t rtype, uint16_t rdlength, rdata_t rdata) { // RDATA is a domain name return rdata.domain_name; break; + case SRV: + // RDATA is SRV data + return rdata.srv_data.target; + break; default: ; // Generic RDATA char *buffer = (char *) malloc(rdlength * 4 + 1); // Allocate memory for each byte (4 characters) + the NULL terminator