dns_debug.c
Go to the documentation of this file.
1 /**
2  * @file dns_debug.c
3  * @brief Data logging functions for debugging purpose (DNS)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL DNS_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "dns/dns_debug.h"
35 #include "netbios/nbns_client.h"
36 #include "netbios/nbns_responder.h"
37 #include "netbios/nbns_common.h"
38 #include "debug.h"
39 
40 //Check TCP/IP stack configuration
41 #if (DNS_TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
42 
43 
44 /**
45  * @brief Dump DNS message for debugging purpose
46  * @param[in] message Pointer to the DNS message
47  * @param[in] length Length of the DNS message
48  **/
49 
50 void dnsDumpMessage(const DnsHeader *message, size_t length)
51 {
52  uint_t i;
53  size_t pos;
54  char_t *buffer;
55 
56  //Make sure the DNS message is valid
57  if(length >= sizeof(DnsHeader))
58  {
59  //Dump DNS message header
60  TRACE_DEBUG(" Identifier (ID) = %" PRIu16 "\r\n", ntohs(message->id));
61  TRACE_DEBUG(" Query Response (QR) = %" PRIu8 "\r\n", message->qr);
62  TRACE_DEBUG(" Opcode (OPCODE) = %" PRIu8 "\r\n", message->opcode);
63  TRACE_DEBUG(" Authoritative Answer (AA) = %" PRIu8 "\r\n", message->aa);
64  TRACE_DEBUG(" TrunCation (TC) = %" PRIu8 "\r\n", message->tc);
65  TRACE_DEBUG(" Recursion Desired (RD) = %" PRIu8 "\r\n", message->rd);
66  TRACE_DEBUG(" Recursion Available (RA) = %" PRIu8 "\r\n", message->ra);
67  TRACE_DEBUG(" Reserved (Z) = %" PRIu8 "\r\n", message->z);
68  TRACE_DEBUG(" Response Code (RCODE) = %" PRIu8 "\r\n", message->rcode);
69  TRACE_DEBUG(" Question Count (QDCOUNT) = %" PRIu8 "\r\n", ntohs(message->qdcount));
70  TRACE_DEBUG(" Answer Count (ANCOUNT) = %" PRIu8 "\r\n", ntohs(message->ancount));
71  TRACE_DEBUG(" Name Server Count (NSCOUNT) = %" PRIu8 "\r\n", ntohs(message->nscount));
72  TRACE_DEBUG(" Additional Record Count (ARCOUNT) = %" PRIu8 "\r\n", ntohs(message->arcount));
73 
74  //Allocate a memory buffer to holds domain names
76  //Failed to allocate memory
77  if(buffer == NULL)
78  return;
79 
80  //Point to the first question
81  pos = sizeof(DnsHeader);
82 
83  //Start of exception handling block
84  do
85  {
86  //Debug message
87  TRACE_DEBUG(" Questions\r\n");
88 
89  //Parse questions
90  for(i = 0; i < ntohs(message->qdcount); i++)
91  {
92  //Dump current question
93  pos = dnsDumpQuestion(message, length, pos, buffer);
94  //Any error to report?
95  if(!pos)
96  break;
97  }
98 
99  //Parsing error?
100  if(!pos)
101  break;
102 
103  //Debug message
104  TRACE_DEBUG(" Answer RRs\r\n");
105 
106  //Parse answer resource records
107  for(i = 0; i < ntohs(message->ancount); i++)
108  {
109  //Dump current resource record
110  pos = dnsDumpResourceRecord(message, length, pos, buffer);
111  //Any error to report?
112  if(!pos)
113  break;
114  }
115 
116  //Parsing error?
117  if(!pos)
118  break;
119 
120  //Debug message
121  TRACE_DEBUG(" Authority RRs\r\n");
122 
123  //Parse authority resource records
124  for(i = 0; i < ntohs(message->nscount); i++)
125  {
126  //Dump current resource record
127  pos = dnsDumpResourceRecord(message, length, pos, buffer);
128  //Any error to report?
129  if(!pos)
130  break;
131  }
132 
133  //Parsing error?
134  if(!pos)
135  break;
136 
137  //Debug message
138  TRACE_DEBUG(" Additional RRs\r\n");
139 
140  //Parse additional resource records
141  for(i = 0; i < ntohs(message->arcount); i++)
142  {
143  //Dump current resource record
144  pos = dnsDumpResourceRecord(message, length, pos, buffer);
145  //Any error to report?
146  if(!pos)
147  break;
148  }
149 
150  //End of exception handling block
151  } while(0);
152 
153  //Free previously allocated memory
154  memPoolFree(buffer);
155  }
156 }
157 
158 
159 /**
160  * @brief Dump DNS question for debugging purpose
161  * @param[in] message Pointer to the DNS message
162  * @param[in] length Length of the DNS message
163  * @param[in] pos Offset of the question to decode
164  * @param[in] buffer Memory buffer to holds domain names
165  * @return Offset to the next question
166  **/
167 
168 size_t dnsDumpQuestion(const DnsHeader *message, size_t length, size_t pos, char_t *buffer)
169 {
170  size_t n;
171  DnsQuestion *question;
172 
173  //Parse domain name
174  n = dnsParseName(message, length, pos, buffer, 0);
175  //Invalid name?
176  if(!n)
177  return 0;
178 
179  //Make sure the DNS question is valid
180  if((n + sizeof(DnsQuestion)) > length)
181  return 0;
182 
183  //Point to the corresponding entry
184  question = DNS_GET_QUESTION(message, n);
185 
186  //NB question found?
187  if(ntohs(question->qtype) == DNS_RR_TYPE_NB)
188  {
189 #if (NBNS_CLIENT_SUPPORT == ENABLED || NBNS_RESPONDER_SUPPORT == ENABLED)
190 #if (IPV4_SUPPORT == ENABLED)
191  //Decode NetBIOS name
192  pos = nbnsParseName((NbnsHeader *) message, length, pos, buffer);
193  //Invalid NetBIOS name?
194  if(!pos)
195  return 0;
196 #endif
197 #endif
198  }
199 
200  //Dump DNS question
201  TRACE_DEBUG(" Name (QNAME) = %s\r\n", buffer);
202  TRACE_DEBUG(" Query Type (QTYPE) = %" PRIu16 "\r\n", ntohs(question->qtype));
203  TRACE_DEBUG(" Query Class (QCLASS) = %" PRIu16 "\r\n", ntohs(question->qclass));
204 
205  //Point to the next question
206  n += sizeof(DnsQuestion);
207  //Return the current position
208  return n;
209 }
210 
211 
212 /**
213  * @brief Dump DNS resource record for debugging purpose
214  * @param[in] message Pointer to the DNS message
215  * @param[in] length Length of the DNS message
216  * @param[in] pos Offset of the question to decode
217  * @param[in] buffer Memory buffer to holds domain names
218  * @return Offset to the next question
219  **/
220 
221 size_t dnsDumpResourceRecord(const DnsHeader *message, size_t length, size_t pos, char_t *buffer)
222 {
223  size_t n;
224  DnsResourceRecord *record;
225  DnsSrvResourceRecord *srvRecord;
226 
227  //Parse domain name
228  n = dnsParseName(message, length, pos, buffer, 0);
229  //Invalid name?
230  if(!n)
231  return 0;
232 
233  //Point to the corresponding entry
234  record = DNS_GET_RESOURCE_RECORD(message, n);
235 
236  //Make sure the resource record is valid
237  if((n + sizeof(DnsResourceRecord)) > length)
238  return 0;
239  if((n + sizeof(DnsResourceRecord) + ntohs(record->rdlength)) > length)
240  return 0;
241 
242  //NB resource record found?
243  if(ntohs(record->rtype) == DNS_RR_TYPE_NB)
244  {
245 #if (NBNS_CLIENT_SUPPORT == ENABLED || NBNS_RESPONDER_SUPPORT == ENABLED)
246 #if (IPV4_SUPPORT == ENABLED)
247  //Decode NetBIOS name
248  pos = nbnsParseName((NbnsHeader *) message, length, pos, buffer);
249  //Invalid NetBIOS name?
250  if(!pos)
251  return 0;
252 #endif
253 #endif
254  }
255 
256  //Dump DNS resource record
257  TRACE_DEBUG(" Name (NAME) = %s\r\n", buffer);
258  TRACE_DEBUG(" Query Type (TYPE) = %" PRIu16 "\r\n", ntohs(record->rtype));
259  TRACE_DEBUG(" Query Class (CLASS) = %" PRIu16 "\r\n", ntohs(record->rclass));
260  TRACE_DEBUG(" Time-To-Live (TTL) = %" PRIu32 "\r\n", ntohl(record->ttl));
261  TRACE_DEBUG(" Data Length (RDLENGTH) = %" PRIu16 "\r\n", ntohs(record->rdlength));
262 
263  //Dump resource data
264 #if (IPV4_SUPPORT == ENABLED)
265  if(ntohs(record->rtype) == DNS_RR_TYPE_A &&
266  ntohs(record->rdlength) == sizeof(Ipv4Addr))
267  {
269 
270  //Copy IPv4 address
271  ipv4CopyAddr(&ipAddr, record->rdata);
272  //Dump IPv4 address
273  TRACE_DEBUG(" Data (RDATA) = %s\r\n", ipv4AddrToString(ipAddr, NULL));
274  }
275  else
276 #endif
277 #if (IPV6_SUPPORT == ENABLED)
278  if(ntohs(record->rtype) == DNS_RR_TYPE_AAAA &&
279  ntohs(record->rdlength) == sizeof(Ipv6Addr))
280  {
282 
283  //Copy IPv6 address
284  ipv6CopyAddr(&ipAddr, record->rdata);
285  //Dump IPv6 address
286  TRACE_DEBUG(" Data (RDATA) = %s\r\n", ipv6AddrToString(&ipAddr, NULL));
287  }
288  else
289 #endif
290  if(ntohs(record->rtype) == DNS_RR_TYPE_PTR)
291  {
292  //Decode domain name
293  pos = dnsParseName(message, length, n + sizeof(DnsResourceRecord), buffer, 0);
294  //Invalid domain name?
295  if(!pos)
296  return 0;
297 
298  //Dump name
299  TRACE_DEBUG(" Domain Name (PTRDNAME) = %s\r\n", buffer);
300  }
301  else if(ntohs(record->rtype) == DNS_RR_TYPE_SRV)
302  {
303  //Cast resource record
304  srvRecord = (DnsSrvResourceRecord *) record;
305 
306  //Dump SRV resource record
307  TRACE_DEBUG(" Priority = %" PRIu16 "\r\n", ntohs(srvRecord->priority));
308  TRACE_DEBUG(" Weight = %" PRIu16 "\r\n", ntohs(srvRecord->weight));
309  TRACE_DEBUG(" Port = %" PRIu16 "\r\n", ntohs(srvRecord->port));
310 
311  //Decode target name
312  pos = dnsParseName(message, length, n + sizeof(DnsSrvResourceRecord), buffer, 0);
313  //Invalid domain name?
314  if(!pos)
315  return 0;
316 
317  //Dump name
318  TRACE_DEBUG(" Target = %s\r\n", buffer);
319  }
320  else
321  {
322  //Dump resource data
323  TRACE_DEBUG(" Data (RDATA)\r\n");
324  TRACE_DEBUG_ARRAY(" ", record->rdata, ntohs(record->rdlength));
325  }
326 
327  //Point to the next resource record
328  n += sizeof(DnsResourceRecord) + ntohs(record->rdlength);
329  //Return the current position
330  return n;
331 }
332 
333 #endif
#define DNS_GET_QUESTION(message, offset)
Definition: dns_common.h:61
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:232
__start_packed struct @151 DnsQuestion
Question format.
#define DNS_GET_RESOURCE_RECORD(message, offset)
Definition: dns_common.h:62
IPv6 address.
Definition: dns_common.h:131
NBNS responder (NetBIOS Name Service)
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:115
char char_t
Definition: compiler_port.h:41
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1785
#define DNS_NAME_MAX_SIZE
Definition: dns_common.h:45
NetBIOS name service.
Definition: dns_common.h:132
TCP/IP stack core.
size_t nbnsParseName(const NbnsHeader *message, size_t length, size_t pos, char_t *dest)
Decode a NetBIOS name.
Definition: nbns_common.c:196
Debugging facilities.
uint8_t message[]
Definition: chap.h:150
__start_packed struct @183 Ipv6Addr
IPv6 network address.
void * memPoolAlloc(size_t size)
Allocate a memory block.
Definition: net_mem.c:98
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:99
uint8_t ipAddr[4]
Definition: mib_common.h:185
Data logging functions for debugging purpose (DNS)
#define ntohl(value)
Definition: cpu_endian.h:397
__start_packed struct @150 DnsHeader
DNS message header.
#define ntohs(value)
Definition: cpu_endian.h:396
size_t dnsDumpResourceRecord(const DnsHeader *message, size_t length, size_t pos, char_t *buffer)
Dump DNS resource record for debugging purpose.
Definition: dns_debug.c:221
void memPoolFree(void *p)
Release a memory block.
Definition: net_mem.c:164
__start_packed struct @263 NbnsHeader
NBNS message header.
void dnsDumpMessage(const DnsHeader *message, size_t length)
Dump DNS message for debugging purpose.
Definition: dns_debug.c:50
size_t dnsParseName(const DnsHeader *message, size_t length, size_t pos, char_t *dest, uint_t level)
Decode a domain name that uses the DNS name encoding.
Definition: dns_common.c:128
NBNS client (NetBIOS Name Service)
size_t dnsDumpQuestion(const DnsHeader *message, size_t length, size_t pos, char_t *buffer)
Dump DNS question for debugging purpose.
Definition: dns_debug.c:168
unsigned int uint_t
Definition: compiler_port.h:43
Server selection.
Definition: dns_common.h:133
Domain name pointer.
Definition: dns_common.h:126
__start_packed struct @152 DnsResourceRecord
Resource record format.
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2298
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
__start_packed struct @153 DnsSrvResourceRecord
SRV resource record format.
Definitions common to NBNS client and NBNS responder.
Host address.
Definition: dns_common.h:121
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:133
#define TRACE_DEBUG(...)
Definition: debug.h:98