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-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.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 S field
173  TRACE_DEBUG(" S = %" PRIu8 "\r\n", message->s);
174 
175  //The Querier's Query Interval Code field specifies the [Query Interval]
176  //used by the querier
177  if(message->qqic < 128)
178  {
179  //The time is represented in units of seconds
180  qqic = message->qqic;
181  }
182  else
183  {
184  //Max Resp Code represents a floating-point value
185  qqic = igmpDecodeFloatingPointValue(message->maxRespCode);
186  }
187 
188  //Dump QRV field
189  TRACE_DEBUG(" QRV = %" PRIu8 " (%us)\r\n", message->qrv, qqic);
190 
191  //Dump QQIC field
192  TRACE_DEBUG(" QQIC = %" PRIu8 "\r\n", message->qqic);
193 
194  //The Number of Sources field specifies how many source addresses are
195  //present in the Query
196  n = ntohs(message->numOfSources);
197 
198  //Malformed message?
199  if(length < (sizeof(IgmpMembershipQueryV3) + n * sizeof(Ipv4Addr)))
200  return;
201 
202  //Dump Number of Sources field
203  TRACE_DEBUG(" Number of Sources = %u\r\n", n);
204 
205  //Dump Source Address field
206  for(i = 0; i < n; i++)
207  {
208  TRACE_DEBUG(" Source Address %u = %s\r\n", i + 1,
209  ipv4AddrToString(message->srcAddr[i], NULL));
210  }
211 }
212 
213 
214 /**
215  * @brief Dump Version 3 Membership Report message
216  * @param[in] message Pointer to the IGMP message to dump
217  * @param[in] length Length of the IGMP message, in bytes
218  **/
219 
221  size_t length)
222 {
223  size_t i;
224  size_t n;
225  uint_t k;
226  uint_t numRecords;
227  const IgmpGroupRecord *record;
228 
229  //Malformed message?
230  if(length < sizeof(IgmpMembershipReportV3))
231  return;
232 
233  //Get the length occupied by the group records
234  length -= sizeof(IgmpMembershipReportV3);
235 
236  //Dump Checksum field
237  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
238 
239  //The Number of Group Records field specifies how many Group Records are
240  //present in this Report
241  numRecords = ntohs(message->numOfGroupRecords);
242 
243  //Dump Number of Sources field
244  TRACE_DEBUG(" Number of Group Records = %u\r\n", numRecords);
245 
246  //Loop through the group records
247  for(i = 0, k = 0; i < length && k < numRecords; i += n, k++)
248  {
249  //Malformed message?
250  if((i + sizeof(IgmpGroupRecord)) > length)
251  break;
252 
253  //Point to the current group record
254  record = (IgmpGroupRecord *) (message->groupRecords + i);
255 
256  //Determine the length of the group record
257  n = sizeof(IgmpGroupRecord) + record->auxDataLen +
258  ntohs(record->numOfSources) * sizeof(Ipv4Addr);
259 
260  //Malformed message?
261  if((i + n) > length)
262  break;
263 
264  //Debug message
265  TRACE_DEBUG(" Group Record %u\r\n", k + 1);
266 
267  //Dump current group record
268  igmpDumpGroupRecord(record, n);
269  }
270 }
271 
272 
273 /**
274  * @brief Dump group record for debugging purpose
275  * @param[in] record Pointer to the group record to dump
276  * @param[in] length Length of the group record, in bytes
277  **/
278 
280  size_t length)
281 {
282  uint_t i;
283  uint_t n;
284  const char_t *name;
285 
286  //Malformed group record?
287  if(length < sizeof(IgmpGroupRecord))
288  return;
289 
290  //Convert the Record Type field to string representation
291  name = igmpGetParamName(record->recordType, igmpGroupRecordTypeList,
293 
294  //Dump Record Type field
295  TRACE_DEBUG(" Record Type = 0x%02" PRIX8 " (%s)\r\n", record->recordType,
296  name);
297 
298  //Dump Aux Data Len field
299  TRACE_DEBUG(" Aux Data Len = %" PRIu8 "\r\n", record->auxDataLen);
300 
301  //The Number of Sources field specifies how many source addresses are
302  //present in this Group Record
303  n = htons(record->numOfSources);
304 
305  //Malformed group record?
306  if(length < (sizeof(IgmpGroupRecord) + n * sizeof(Ipv4Addr)))
307  return;
308 
309  //Dump Number of Sources field
310  TRACE_DEBUG(" Number of Sources = %u\r\n", n);
311 
312  //Dump Multicast Address field
313  TRACE_DEBUG(" Multicast Address = %s\r\n",
314  ipv4AddrToString(record->multicastAddr, NULL));
315 
316  //Dump Source Address field
317  for(i = 0; i < n; i++)
318  {
319  TRACE_DEBUG(" Source Address %u = %s\r\n", i + 1,
320  ipv4AddrToString(record->srcAddr[i], NULL));
321  }
322 }
323 
324 
325 /**
326  * @brief Convert a parameter to string representation
327  * @param[in] value Parameter value
328  * @param[in] paramList List of acceptable parameters
329  * @param[in] paramListLen Number of entries in the list
330  * @return NULL-terminated string describing the parameter
331  **/
332 
334  size_t paramListLen)
335 {
336  uint_t i;
337 
338  //Default name for unknown values
339  static const char_t defaultName[] = "Unknown";
340 
341  //Loop through the list of acceptable parameters
342  for(i = 0; i < paramListLen; i++)
343  {
344  if(paramList[i].value == value)
345  return paramList[i].name;
346  }
347 
348  //Unknown value
349  return defaultName;
350 }
351 
352 #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:297
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:279
@ 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:368
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:398
#define TRACE_DEBUG(...)
Definition: debug.h:107
char char_t
Definition: compiler_port.h:48
@ 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:333
uint8_t value[]
Definition: tcp.h:369
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:50
TCP/IP stack core.
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1457
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:220
@ IGMP_TYPE_LEAVE_GROUP
Definition: igmp_common.h:177
Debugging facilities.
#define arraysize(a)
Definition: os_port.h:71