igmp_debug.c
Go to the documentation of this file.
1 /**
2  * @file igmp_debug.c
3  * @brief Data logging functions for debugging purpose (IGMP)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IGMP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "igmp/igmp_debug.h"
37 #include "debug.h"
38 
39 //Check TCP/IP stack configuration
40 #if (IPV4_SUPPORT == ENABLED && IGMP_TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
41 
42 //IGMP message types
44 {
45  {IGMP_TYPE_MEMBERSHIP_QUERY, "Membership Query"},
46  {IGMP_TYPE_MEMBERSHIP_REPORT_V1, "Version 1 Membership Report"},
47  {IGMP_TYPE_MEMBERSHIP_REPORT_V2, "Version 2 Membership Report"},
48  {IGMP_TYPE_LEAVE_GROUP, "Leave Group"},
49  {IGMP_TYPE_MEMBERSHIP_REPORT_V3, "Version 3 Membership Report"}
50 };
51 
52 //IGMPv3 group record types
54 {
55  {IGMP_GROUP_RECORD_TYPE_IS_IN, "MODE_IS_INCLUDE"},
56  {IGMP_GROUP_RECORD_TYPE_IS_EX, "MODE_IS_EXCLUDE"},
57  {IGMP_GROUP_RECORD_TYPE_TO_IN, "CHANGE_TO_INCLUDE_MODE"},
58  {IGMP_GROUP_RECORD_TYPE_TO_EX, "CHANGE_TO_EXCLUDE_MODE"},
59  {IGMP_GROUP_RECORD_TYPE_ALLOW, "ALLOW_NEW_SOURCES"},
60  {IGMP_GROUP_RECORD_TYPE_BLOCK, "BLOCK_OLD_SOURCES"}
61 };
62 
63 
64 /**
65  * @brief Dump IGMP message for debugging purpose
66  * @param[in] message Pointer to the IGMP message to dump
67  * @param[in] length Length of the IGMP message, in bytes
68  **/
69 
71 {
73  const char_t *name;
74 
75  //Malformed message?
76  if(length < sizeof(IgmpMessage))
77  return;
78 
79  //Convert the Type field to string representation
82 
83  //Dump Type field
84  TRACE_DEBUG(" Type = 0x%02" PRIX8 " (%s)\r\n", message->type, name);
85 
86  //Check message type
87  if(message->type == IGMP_TYPE_MEMBERSHIP_QUERY &&
88  length == sizeof(IgmpMessage))
89  {
90  //The Max Response Time field is meaningful only in Membership Query
91  //messages, and specifies the maximum allowed time before sending a
92  //responding report in units of 1/10 second
93  maxRespTime = message->maxRespTime;
94 
95  //Dump Max Response Time field
96  TRACE_DEBUG(" Max Resp Time = %" PRIu8 " (%u.%us)\r\n",
97  maxRespTime, maxRespTime / 10, maxRespTime % 10);
98 
99  //Dump Checksum field
100  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
101 
102  //Dump Group Address field
103  TRACE_DEBUG(" Group Address = %s\r\n",
104  ipv4AddrToString(message->groupAddr, NULL));
105  }
106  else if(message->type == IGMP_TYPE_MEMBERSHIP_QUERY &&
107  length >= sizeof(IgmpMembershipQueryV3))
108  {
109  //Dump Version 3 Membership Query message
111  }
112  else if(message->type == IGMP_TYPE_MEMBERSHIP_REPORT_V3)
113  {
114  //Dump Version 3 Membership Report message
116  length);
117  }
118  else
119  {
120  //Dump Checksum field
121  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
122 
123  //Dump Group Address field
124  TRACE_DEBUG(" Group Address = %s\r\n",
125  ipv4AddrToString(message->groupAddr, NULL));
126  }
127 }
128 
129 
130 /**
131  * @brief Dump Version 3 Membership Query message
132  * @param[in] message Pointer to the IGMP message to dump
133  * @param[in] length Length of the IGMP message, in bytes
134  **/
135 
137  size_t length)
138 {
139  uint_t i;
140  uint_t n;
141  uint_t qqic;
143 
144  //Malformed message?
145  if(length < sizeof(IgmpMembershipQueryV3))
146  return;
147 
148  //The Max Resp Code field specifies the maximum time allowed before
149  //sending a responding report
150  if(message->maxRespCode < 128)
151  {
152  //The time is represented in units of 1/10 second
153  maxRespTime = message->maxRespCode;
154  }
155  else
156  {
157  //Max Resp Code represents a floating-point value
159  }
160 
161  //Dump Max Response Code field
162  TRACE_DEBUG(" Max Resp Code = %" PRIu8 " (%u.%us)\r\n",
163  message->maxRespCode, maxRespTime / 10, maxRespTime % 10);
164 
165  //Dump Checksum field
166  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
167 
168  //Dump Group Address field
169  TRACE_DEBUG(" Group Address = %s\r\n",
170  ipv4AddrToString(message->groupAddr, NULL));
171 
172  //Dump Flags field
173  TRACE_DEBUG(" Flags = 0x%" PRIX8 "\r\n", message->flags);
174  //Dump S field
175  TRACE_DEBUG(" S = %" PRIu8 "\r\n", message->s);
176  //Dump QRV field
177  TRACE_DEBUG(" QRV = %" PRIu8 "\r\n", message->qrv);
178 
179  //The Querier's Query Interval Code field specifies the [Query Interval]
180  //used by the querier
181  if(message->qqic < 128)
182  {
183  //The time is represented in units of seconds
184  qqic = message->qqic;
185  }
186  else
187  {
188  //Max Resp Code represents a floating-point value
189  qqic = igmpDecodeFloatingPointValue(message->maxRespCode);
190  }
191 
192  //Dump QQIC field
193  TRACE_DEBUG(" QQIC = %" PRIu8 " (%us)\r\n", message->qqic, qqic);
194 
195  //The Number of Sources field specifies how many source addresses are
196  //present in the Query
197  n = ntohs(message->numOfSources);
198 
199  //Malformed message?
200  if(length < (sizeof(IgmpMembershipQueryV3) + n * sizeof(Ipv4Addr)))
201  return;
202 
203  //Dump Number of Sources field
204  TRACE_DEBUG(" Number of Sources = %u\r\n", n);
205 
206  //Dump Source Address field
207  for(i = 0; i < n; i++)
208  {
209  TRACE_DEBUG(" Source Address %u = %s\r\n", i + 1,
210  ipv4AddrToString(message->srcAddr[i], NULL));
211  }
212 }
213 
214 
215 /**
216  * @brief Dump Version 3 Membership Report message
217  * @param[in] message Pointer to the IGMP message to dump
218  * @param[in] length Length of the IGMP message, in bytes
219  **/
220 
222  size_t length)
223 {
224  size_t i;
225  size_t n;
226  uint_t k;
227  uint_t numRecords;
228  const IgmpGroupRecord *record;
229 
230  //Malformed message?
231  if(length < sizeof(IgmpMembershipReportV3))
232  return;
233 
234  //Get the length occupied by the group records
235  length -= sizeof(IgmpMembershipReportV3);
236 
237  //Dump Checksum field
238  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
239  //Dump Flags field
240  TRACE_DEBUG(" Flags = 0x%04" PRIX16 "\r\n", ntohs(message->flags));
241 
242  //The Number of Group Records field specifies how many Group Records are
243  //present in this Report
244  numRecords = ntohs(message->numOfGroupRecords);
245 
246  //Dump Number of Sources field
247  TRACE_DEBUG(" Number of Group Records = %u\r\n", numRecords);
248 
249  //Loop through the group records
250  for(i = 0, k = 0; i < length && k < numRecords; i += n, k++)
251  {
252  //Malformed message?
253  if((i + sizeof(IgmpGroupRecord)) > length)
254  break;
255 
256  //Point to the current group record
257  record = (IgmpGroupRecord *) (message->groupRecords + i);
258 
259  //Determine the length of the group record
260  n = sizeof(IgmpGroupRecord) + record->auxDataLen +
261  ntohs(record->numOfSources) * sizeof(Ipv4Addr);
262 
263  //Malformed message?
264  if((i + n) > length)
265  break;
266 
267  //Debug message
268  TRACE_DEBUG(" Group Record %u\r\n", k + 1);
269 
270  //Dump current group record
271  igmpDumpGroupRecord(record, n);
272  }
273 }
274 
275 
276 /**
277  * @brief Dump group record for debugging purpose
278  * @param[in] record Pointer to the group record to dump
279  * @param[in] length Length of the group record, in bytes
280  **/
281 
283  size_t length)
284 {
285  uint_t i;
286  uint_t n;
287  const char_t *name;
288 
289  //Malformed group record?
290  if(length < sizeof(IgmpGroupRecord))
291  return;
292 
293  //Convert the Record Type field to string representation
294  name = igmpGetParamName(record->recordType, igmpGroupRecordTypeList,
296 
297  //Dump Record Type field
298  TRACE_DEBUG(" Record Type = 0x%02" PRIX8 " (%s)\r\n", record->recordType,
299  name);
300 
301  //Dump Aux Data Len field
302  TRACE_DEBUG(" Aux Data Len = %" PRIu8 "\r\n", record->auxDataLen);
303 
304  //The Number of Sources field specifies how many source addresses are
305  //present in this Group Record
306  n = htons(record->numOfSources);
307 
308  //Malformed group record?
309  if(length < (sizeof(IgmpGroupRecord) + n * sizeof(Ipv4Addr)))
310  return;
311 
312  //Dump Number of Sources field
313  TRACE_DEBUG(" Number of Sources = %u\r\n", n);
314 
315  //Dump Multicast Address field
316  TRACE_DEBUG(" Multicast Address = %s\r\n",
317  ipv4AddrToString(record->multicastAddr, NULL));
318 
319  //Dump Source Address field
320  for(i = 0; i < n; i++)
321  {
322  TRACE_DEBUG(" Source Address %u = %s\r\n", i + 1,
323  ipv4AddrToString(record->srcAddr[i], NULL));
324  }
325 }
326 
327 
328 /**
329  * @brief Convert a parameter to string representation
330  * @param[in] value Parameter value
331  * @param[in] paramList List of acceptable parameters
332  * @param[in] paramListLen Number of entries in the list
333  * @return NULL-terminated string describing the parameter
334  **/
335 
337  size_t paramListLen)
338 {
339  uint_t i;
340 
341  //Default name for unknown values
342  static const char_t defaultName[] = "Unknown";
343 
344  //Loop through the list of acceptable parameters
345  for(i = 0; i < paramListLen; i++)
346  {
347  if(paramList[i].value == value)
348  return paramList[i].name;
349  }
350 
351  //Unknown value
352  return defaultName;
353 }
354 
355 #endif
IgmpMembershipReportV3
Definition: igmp_common.h:255
#define htons(value)
Definition: cpu_endian.h:413
uint8_t maxRespTime
Definition: igmp_common.h:212
IgmpMessage
Definition: igmp_common.h:215
uint8_t message[]
Definition: chap.h:154
Data logging functions for debugging purpose (IGMP)
void igmpDumpMessage(const IgmpMessage *message, size_t length)
Dump IGMP message for debugging purpose.
Definition: igmp_debug.c:70
char_t name[]
@ IGMP_TYPE_MEMBERSHIP_REPORT_V2
Definition: igmp_common.h:176
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:298
void igmpDumpMembershipQueryV3(const IgmpMembershipQueryV3 *message, size_t length)
Dump Version 3 Membership Query message.
Definition: igmp_debug.c:136
void igmpDumpGroupRecord(const IgmpGroupRecord *record, size_t length)
Dump group record for debugging purpose.
Definition: igmp_debug.c:282
@ IGMP_TYPE_MEMBERSHIP_REPORT_V1
Definition: igmp_common.h:175
@ IGMP_TYPE_MEMBERSHIP_QUERY
Definition: igmp_common.h:174
@ IGMP_GROUP_RECORD_TYPE_BLOCK
Definition: igmp_common.h:193
@ IGMP_GROUP_RECORD_TYPE_ALLOW
Definition: igmp_common.h:192
@ IGMP_TYPE_MEMBERSHIP_REPORT_V3
Definition: igmp_common.h:178
uint8_t length
Definition: tcp.h:375
const char_t * name
Definition: igmp_debug.h:52
uint8_t qqic
Definition: igmp_common.h:237
@ IGMP_GROUP_RECORD_TYPE_IS_EX
Definition: igmp_common.h:189
#define ntohs(value)
Definition: cpu_endian.h:421
const IgmpParamName igmpMessageTypeList[]
Definition: igmp_debug.c:43
uint32_t igmpDecodeFloatingPointValue(uint8_t code)
Decode a floating-point value.
Definition: igmp_common.c:399
#define TRACE_DEBUG(...)
Definition: debug.h:119
char char_t
Definition: compiler_port.h:55
@ IGMP_GROUP_RECORD_TYPE_TO_EX
Definition: igmp_common.h:191
uint8_t n
IgmpGroupRecord
Definition: igmp_common.h:269
IgmpMembershipQueryV3
Definition: igmp_common.h:240
const char_t * igmpGetParamName(uint_t value, const IgmpParamName *paramList, size_t paramListLen)
Convert a parameter to string representation.
Definition: igmp_debug.c:336
uint8_t value[]
Definition: tcp.h:376
const IgmpParamName igmpGroupRecordTypeList[]
Definition: igmp_debug.c:53
@ IGMP_GROUP_RECORD_TYPE_IS_IN
Definition: igmp_common.h:188
@ IGMP_GROUP_RECORD_TYPE_TO_IN
Definition: igmp_common.h:190
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1478
Parameter value/name binding.
Definition: igmp_debug.h:50
void igmpDumpMessageMembershipReportV3(const IgmpMembershipReportV3 *message, size_t length)
Dump Version 3 Membership Report message.
Definition: igmp_debug.c:221
@ IGMP_TYPE_LEAVE_GROUP
Definition: igmp_common.h:177
Debugging facilities.
#define arraysize(a)
Definition: os_port.h:71