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