1 /* 2 * FreeRTOS+TCP <DEVELOPMENT BRANCH> 3 * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * http://aws.amazon.com/freertos 25 * http://www.FreeRTOS.org 26 */ 27 28 /* 29 * @file tcp_dump_packets.c 30 * @brief Used in the PC/Win project to dump Ethernet packets, along with some description. 31 * See tools/tcp_dump_packets.md for further description. 32 */ 33 34 /* Standard includes. */ 35 #include <stdio.h> 36 #include <stdint.h> 37 #include <stdarg.h> 38 #include <ctype.h> 39 40 /* FreeRTOS includes. */ 41 #include <FreeRTOS.h> 42 #include "task.h" 43 44 /* FreeRTOS+TCP includes. */ 45 #include "FreeRTOS_IP.h" 46 #include "FreeRTOS_Sockets.h" 47 #include "FreeRTOS_Stream_Buffer.h" 48 #include "FreeRTOS_IP_Private.h" 49 50 #if ( ipconfigUSE_DUMP_PACKETS != 0 ) 51 52 #include "tcp_dump_packets.h" 53 54 /* The priority of the windows thread. */ 55 #define dumpPROCESS_THREAD_PRIORITY THREAD_PRIORITY_NORMAL 56 57 /* There is a stream buffer between the FreeRTOS tasks sending network packets, 58 * and the Windows thread that writes these packets to disk. The macro 'dumpITEM_COUNT' 59 * determines the number of full-size packets that can be stored in this stream buffer. */ 60 #ifndef dumpITEM_COUNT 61 #define dumpITEM_COUNT 32 62 #endif 63 64 /* Packets are written in hex notation, no more than 16 bytes on a row. */ 65 #ifndef dumpBYTES_PER_ROW 66 #define dumpBYTES_PER_ROW 16 67 #endif 68 69 /* The TCP port number reserved for a DNS server. */ 70 #define dnsDNS_PORT 0x0035u 71 72 /* Some const values describing the 'flags' in a TCP packet. */ 73 #define tcpTCP_FLAG_FIN 0x0001u /* No more data from sender */ 74 #define tcpTCP_FLAG_SYN 0x0002u /* Synchronize sequence numbers */ 75 #define tcpTCP_FLAG_RST 0x0004u /* Reset the connection */ 76 #define tcpTCP_FLAG_PSH 0x0008u /* Push function: please push buffered data to the recv application */ 77 #define tcpTCP_FLAG_ACK 0x0010u /* Acknowledgment field is significant */ 78 79 /* A macro to add a type, both as a numeric value, as well as a string. */ 80 #define ADD_TYPE( FLAGS ) \ 81 vAddType( flag_ ## FLAGS, # FLAGS ) 82 83 /*-----------------------------------------------------------*/ 84 85 static char pcTypeString[ 255 ]; 86 static uint32_t ulTypeMask; 87 88 /* The name of the C source file to be written. */ 89 static char pcCodeFileName[ MAX_PATH ]; 90 91 /* The name of the header file to be written. */ 92 static char pcHeaderFileName[ MAX_PATH ]; 93 94 /* A stream buffer between the FreeRTOS tasks and the Windows thread. */ 95 static StreamBuffer_t * xPacketBuffer; 96 97 /* A process handle of the Windows thread. */ 98 static HANDLE pvProcessHandle; 99 100 static UBaseType_t uxNextPacketNumber; 101 static BaseType_t xFirstPacket = 1; 102 103 /* Boolean 'xDumpingReady' becomes true once all desired packet have been collected. 104 * Further packets will be dropped (ignored). */ 105 static volatile BaseType_t xDumpingReady = pdFALSE; 106 107 static DumpEntries_t * pxCurrentEntries; 108 109 static uint16_t usSourcePort; 110 static uint16_t usDestinationPort; 111 112 typedef struct xBufferheader 113 { 114 size_t uxLength; 115 UBaseType_t bIncoming : 1; 116 } Bufferheader_t; 117 118 static DumpEntries_t xExampleEntries = 119 { 120 .uxEntryCount = 4, /* No more than 'dumpMAX_DUMP_ENTRIES' elements. */ 121 .xEntries = 122 { 123 { .ulMask = flag_IN | flag_UDP, .uxMax = 2u }, 124 { .ulMask = flag_IN | flag_ARP, .uxMax = 2u }, 125 { .ulMask = flag_IN | flag_TCP, .uxMax = 5u }, 126 { .ulMask = flag_IN | flag_SYN, .uxMax = 1u }, 127 } 128 }; 129 130 const char pcHeaderCode[] = 131 "/*\n" 132 " * This file was created automatically by 'dump_packets.c'\n" 133 " */\n" 134 "\n" 135 "/* Standard includes. */\n" 136 "#include <stdio.h>\n" 137 "#include <stdint.h>\n" 138 "#include <stdarg.h>\n" 139 "#include <io.h>\n" 140 "#include <ctype.h>\n" 141 "\n" 142 "/* FreeRTOS includes. */\n" 143 "#include <FreeRTOS.h>\n" 144 "#include <task.h>\n\n" 145 "#include \"%s\"\n\n"; 146 147 const char pcHeaderHeader[] = 148 "/*\n" 149 " * This file was created automatically by 'dump_packets.c'\n" 150 " */\n" 151 "\n" 152 "#ifndef PACKET_LIST_H\n\n" 153 "#define PACKET_LIST_H\n\n" 154 "typedef struct xDumpPacket\n" 155 "{\n" 156 " const uint8_t *pucData;\n" 157 " size_t uxLength;\n" 158 " uint32_t ulType;\n" 159 " uint16_t usSource;\n" 160 " uint16_t usDestination;\n" 161 "} DumpPacket_t;\n\n"; 162 163 /*-----------------------------------------------------------*/ 164 165 /* The Windows thread that actually writes the network packets to a C source and header file. */ 166 static DWORD WINAPI prvWritePackets( LPVOID lpParameter ); 167 168 static void vAddProtocolTags( uint8_t * pucEthernetBuffer, 169 BaseType_t xIPType ); 170 static void vDetermineMessageType( uint8_t * pucBuffer, 171 BaseType_t xIncoming ); 172 static void vActualDump( uint8_t * pucBuffer, 173 size_t uxLength, 174 BaseType_t xIncoming ); 175 static void vAddType( uint32_t ulFlags, 176 const char * pcFlagName ); 177 static void vWriteHeaderFile( void ); 178 179 /*-----------------------------------------------------------*/ 180 dump_packet_init(const char * pcFileName,DumpEntries_t * pxEntries)181 void dump_packet_init( const char * pcFileName, 182 DumpEntries_t * pxEntries ) 183 { 184 size_t uxIndex; 185 186 snprintf( pcCodeFileName, sizeof pcCodeFileName, "%s.c", pcFileName ); 187 snprintf( pcHeaderFileName, sizeof pcHeaderFileName, "%s.h", pcFileName ); 188 189 if( pxEntries == NULL ) 190 { 191 pxEntries = &( xExampleEntries ); 192 } 193 194 configASSERT( pxEntries->uxEntryCount > 0 ); 195 configASSERT( pxEntries->uxEntryCount <= dumpMAX_DUMP_ENTRIES ); 196 197 for( uxIndex = 0; uxIndex < pxEntries->uxEntryCount; uxIndex++ ) 198 { 199 pxEntries->xEntries[ uxIndex ].uxCount = 0; 200 } 201 202 pxCurrentEntries = pxEntries; 203 204 if( xPacketBuffer == NULL ) 205 { 206 size_t uxLength, uxSize; 207 208 /* Enough space for e.g. 32 buffers and length words. */ 209 uxLength = dumpITEM_COUNT * ( sizeof( void * ) + ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ); 210 uxSize = ( sizeof( *xPacketBuffer ) + uxLength ) - sizeof( xPacketBuffer->ucArray ); 211 xPacketBuffer = ( StreamBuffer_t * ) pvPortMalloc( uxSize ); 212 configASSERT( xPacketBuffer != NULL ); 213 vStreamBufferClear( xPacketBuffer ); 214 xPacketBuffer->LENGTH = uxLength; 215 } 216 217 if( pvProcessHandle == NULL ) 218 { 219 pvProcessHandle = CreateThread( NULL, 0, prvWritePackets, NULL, CREATE_SUSPENDED, NULL ); 220 221 if( pvProcessHandle != NULL ) 222 { 223 SetThreadPriority( pvProcessHandle, dumpPROCESS_THREAD_PRIORITY ); 224 SetThreadPriorityBoost( pvProcessHandle, TRUE ); 225 SetThreadAffinityMask( pvProcessHandle, 0x0E ); 226 ResumeThread( pvProcessHandle ); 227 } 228 } 229 } 230 /*-----------------------------------------------------------*/ 231 dump_packet(const uint8_t * pucBuffer,size_t uxLength,BaseType_t xIncoming)232 void dump_packet( const uint8_t * pucBuffer, 233 size_t uxLength, 234 BaseType_t xIncoming ) 235 { 236 /* This function shall be called from a normal FreeRTOS task only. */ 237 if( xPacketBuffer != NULL ) 238 { 239 if( xDumpingReady == pdFALSE ) 240 { 241 size_t uxSpace = uxStreamBufferGetSpace( xPacketBuffer ); 242 size_t uxNeeded = uxLength + sizeof( size_t ); 243 244 if( uxNeeded < uxSpace ) 245 { 246 Bufferheader_t xheader; 247 248 xheader.uxLength = uxLength; 249 xheader.bIncoming = xIncoming; 250 uxStreamBufferAdd( xPacketBuffer, 0u, ( const uint8_t * ) &( xheader ), sizeof( xheader ) ); 251 uxStreamBufferAdd( xPacketBuffer, 0u, pucBuffer, uxLength ); 252 } 253 else 254 { 255 /* Drop this packet. */ 256 } 257 } 258 else 259 { 260 /* The Windows thread 'prvWritePackets()' had received enough packets. 261 * The packet buffer may be freed. */ 262 vPortFree( xPacketBuffer ); 263 xPacketBuffer = NULL; 264 } 265 } 266 } 267 /*-----------------------------------------------------------*/ 268 prvWritePackets(LPVOID lpParameter)269 static DWORD WINAPI prvWritePackets( LPVOID lpParameter ) 270 { 271 /* This is a Windows thread, not a FreeRTOS task. FreeRTOS API's may not be called. */ 272 for( ; ; ) 273 { 274 Sleep( 100 ); 275 276 while( ( xPacketBuffer != NULL ) && ( xDumpingReady == pdFALSE ) ) 277 { 278 Bufferheader_t xHeader; 279 size_t uxBytes = uxStreamBufferGetSize( xPacketBuffer ); 280 281 if( uxBytes <= sizeof( xHeader ) ) 282 { 283 break; 284 } 285 286 /* Peek the number of bytes available. */ 287 uxStreamBufferGet( xPacketBuffer, 0u, ( uint8_t * ) &( xHeader ), sizeof( xHeader ), pdTRUE ); 288 289 if( uxBytes >= sizeof( xHeader ) + xHeader.uxLength ) 290 { 291 } 292 293 { 294 size_t xBytesRead; 295 uint8_t pcBuffer[ ipconfigNETWORK_MTU ]; 296 size_t xActualCount; 297 298 uxStreamBufferGet( xPacketBuffer, 0u, NULL, sizeof( xHeader ), pdFALSE ); 299 xActualCount = uxStreamBufferGet( xPacketBuffer, 0u, pcBuffer, xHeader.uxLength, pdFALSE ); 300 vActualDump( pcBuffer, xActualCount, xHeader.bIncoming ); 301 } 302 } 303 } 304 } 305 /*-----------------------------------------------------------*/ 306 _fprintf(FILE * pxHandle,const char * pcFormat,...)307 static int _fprintf( FILE * pxHandle, 308 const char * pcFormat, 309 ... ) 310 { 311 char pcString[ 255 ]; 312 BaseType_t iCount; 313 314 va_list args; 315 316 va_start( args, pcFormat ); 317 iCount = vsnprintf( pcString, sizeof pcString, pcFormat, args ); 318 va_end( args ); 319 fwrite( pcString, 1u, iCount, pxHandle ); 320 321 return iCount; 322 } 323 /*-----------------------------------------------------------*/ 324 vWriteHeaderFile(void)325 static void vWriteHeaderFile( void ) 326 { 327 FILE * outfile; 328 329 outfile = fopen( pcHeaderFileName, "w" ); 330 331 if( outfile != NULL ) 332 { 333 fwrite( pcHeaderHeader, 1u, sizeof( pcHeaderHeader ) - 1u, outfile ); 334 _fprintf( outfile, "#define dumpPACKET_COUNT %lu\n\n", 335 ( uxNextPacketNumber < 1u ) ? 1u : uxNextPacketNumber ); 336 _fprintf( outfile, "extern DumpPacket_t *xPacketList[ dumpPACKET_COUNT ];\n\n" ); 337 _fprintf( outfile, "#endif PACKET_LIST_H\n" ); 338 339 fclose( outfile ); 340 } 341 } 342 /*-----------------------------------------------------------*/ 343 vAddType(uint32_t ulFlags,const char * pcFlagName)344 static void vAddType( uint32_t ulFlags, 345 const char * pcFlagName ) 346 { 347 size_t uxLength = strlen( pcTypeString ); 348 char pcString[ 64 ]; 349 BaseType_t iCount; 350 351 ulTypeMask |= ulFlags; 352 353 if( uxLength == 0 ) 354 { 355 snprintf( pcTypeString, sizeof pcTypeString, "%s", pcFlagName ); 356 } 357 else 358 { 359 snprintf( pcTypeString + uxLength, sizeof pcTypeString - 1, " | %s", pcFlagName ); 360 } 361 } 362 /*-----------------------------------------------------------*/ 363 vAddProtocolTags(uint8_t * pucEthernetBuffer,BaseType_t xIPType)364 static void vAddProtocolTags( uint8_t * pucEthernetBuffer, 365 BaseType_t xIPType ) 366 { 367 ProtocolHeaders_t * pxProtocolHeaders; 368 369 #if ( ipconfigUSE_IPv6 != 0 ) 370 const IPHeader_IPv6_t * pxIPHeader_IPv6; 371 #endif 372 UBaseType_t uxHeaderLength; 373 uint8_t ucProtocol; 374 IPPacket_t * pxIPPacket; 375 IPHeader_t * pxIPHeader; 376 377 pxIPPacket = ( IPPacket_t * ) pucEthernetBuffer; 378 pxIPHeader = &( pxIPPacket->xIPHeader ); 379 #if ( ipconfigUSE_IPv6 != 0 ) 380 pxIPHeader_IPv6 = ( const IPHeader_IPv6_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ); 381 382 if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) 383 { 384 uxHeaderLength = ipSIZE_OF_IPv6_HEADER; 385 ucProtocol = pxIPHeader_IPv6->ucNextHeader; 386 pxProtocolHeaders = ( ProtocolHeaders_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER ] ); 387 } 388 else 389 #endif 390 { 391 size_t uxLength = ( size_t ) pxIPHeader->ucVersionHeaderLength; 392 393 /* Check if the IP headers are acceptable and if it has our destination. 394 * The lowest four bits of 'ucVersionHeaderLength' indicate the IP-header 395 * length in multiples of 4. */ 396 uxHeaderLength = ( size_t ) ( ( uxLength & 0x0Fu ) << 2 ); 397 ucProtocol = pxIPPacket->xIPHeader.ucProtocol; 398 pxProtocolHeaders = ( ProtocolHeaders_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxHeaderLength ] ); 399 } 400 401 switch( ucProtocol ) 402 { 403 case ipPROTOCOL_ICMP: 404 ADD_TYPE( ICMP4 ); 405 break; 406 407 #if ( ipconfigUSE_IPv6 != 0 ) 408 case ipPROTOCOL_ICMP_IPv6: 409 ADD_TYPE( ICMP6 ); 410 break; 411 #endif 412 413 case ipPROTOCOL_UDP: 414 ADD_TYPE( UDP ); 415 usSourcePort = pxProtocolHeaders->xUDPHeader.usSourcePort; 416 usDestinationPort = pxProtocolHeaders->xUDPHeader.usDestinationPort; 417 418 if( usSourcePort == FreeRTOS_htons( dnsDNS_PORT ) ) 419 { 420 ADD_TYPE( DNS ); 421 ADD_TYPE( REPLY ); 422 } 423 else if( usDestinationPort == FreeRTOS_htons( dnsDNS_PORT ) ) 424 { 425 ADD_TYPE( DNS ); 426 ADD_TYPE( REQUEST ); 427 } 428 429 break; 430 431 #if ipconfigUSE_TCP == 1 432 case ipPROTOCOL_TCP: 433 ADD_TYPE( TCP ); 434 usSourcePort = pxProtocolHeaders->xTCPHeader.usSourcePort; 435 usDestinationPort = pxProtocolHeaders->xTCPHeader.usDestinationPort; 436 437 if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_SYN ) != 0u ) 438 { 439 ADD_TYPE( SYN ); 440 } 441 442 if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_FIN ) != 0u ) 443 { 444 ADD_TYPE( FIN ); 445 } 446 447 if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_RST ) != 0u ) 448 { 449 ADD_TYPE( RST ); 450 } 451 452 if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_ACK ) != 0u ) 453 { 454 ADD_TYPE( ACK ); 455 } 456 break; 457 #endif /* if ipconfigUSE_TCP == 1 */ 458 } 459 } 460 /*-----------------------------------------------------------*/ 461 vDetermineMessageType(uint8_t * pucBuffer,BaseType_t xIncoming)462 static void vDetermineMessageType( uint8_t * pucBuffer, 463 BaseType_t xIncoming ) 464 { 465 EthernetHeader_t * pxEthernetHeader; 466 467 if( xIncoming != 0 ) 468 { 469 ADD_TYPE( IN ); 470 } 471 else 472 { 473 ADD_TYPE( OUT ); 474 } 475 476 pxEthernetHeader = ( EthernetHeader_t * ) pucBuffer; 477 478 /* Interpret the received Ethernet packet. */ 479 switch( pxEthernetHeader->usFrameType ) 480 { 481 case ipARP_FRAME_TYPE: 482 { 483 ARPPacket_t * pxARPFrame; 484 ARPHeader_t * pxARPHeader; 485 486 /* The Ethernet frame contains an ARP packet. */ 487 ADD_TYPE( FRAME_ARP ); 488 pxARPFrame = ( ARPPacket_t * ) pucBuffer; 489 pxARPHeader = &( pxARPFrame->xARPHeader ); 490 ADD_TYPE( ARP ); 491 492 switch( pxARPHeader->usOperation ) 493 { 494 case ipARP_REQUEST: 495 ADD_TYPE( REQUEST ); 496 break; 497 498 case ipARP_REPLY: 499 ADD_TYPE( REPLY ); 500 break; 501 502 default: 503 ADD_TYPE( UNKNOWN ); 504 break; 505 } 506 } 507 break; 508 509 case ipIPv4_FRAME_TYPE: 510 ADD_TYPE( FRAME_4 ); 511 vAddProtocolTags( pucBuffer, 4 ); 512 break; 513 514 #if ( ipconfigUSE_IPv6 != 0 ) 515 case ipIPv6_FRAME_TYPE: 516 ADD_TYPE( FRAME_6 ); 517 vAddProtocolTags( pucBuffer, 6 ); 518 break; 519 #endif 520 default: 521 /* No other packet types are handled. Nothing to do. */ 522 ADD_TYPE( Unknown_FRAME ); 523 break; 524 } 525 } 526 /*-----------------------------------------------------------*/ 527 vActualDump(uint8_t * pucBuffer,size_t uxLength,BaseType_t xIncoming)528 static void vActualDump( uint8_t * pucBuffer, 529 size_t uxLength, 530 BaseType_t xIncoming ) 531 { 532 char pcString[ 513 ]; 533 size_t uxOffset; 534 size_t uxIndex; 535 size_t uxCompleteCount = 0; 536 BaseType_t xUseIt = pdFALSE; 537 538 usSourcePort = 0u; 539 usDestinationPort = 0u; 540 pcTypeString[ 0 ] = 0; 541 ulTypeMask = 0uL; 542 543 if( pxCurrentEntries == NULL ) 544 { 545 return; 546 } 547 548 vDetermineMessageType( pucBuffer, xIncoming ); 549 550 for( uxIndex = 0; uxIndex < pxCurrentEntries->uxEntryCount; uxIndex++ ) 551 { 552 if( pxCurrentEntries->xEntries[ uxIndex ].uxCount < pxCurrentEntries->xEntries[ uxIndex ].uxMax ) 553 { 554 uint32_t ulMask = pxCurrentEntries->xEntries[ uxIndex ].ulMask; 555 556 if( ( ulMask & ulTypeMask ) == ulMask ) 557 { 558 pxCurrentEntries->xEntries[ uxIndex ].uxCount++; 559 xUseIt = pdTRUE; 560 } 561 } 562 else 563 { 564 uxCompleteCount++; 565 } 566 } 567 568 FreeRTOS_printf( ( "prvWritePackets: done %d/%d : (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n", 569 uxCompleteCount, 570 pxCurrentEntries->uxEntryCount, 571 pxCurrentEntries->xEntries[ 0 ].uxCount, pxCurrentEntries->xEntries[ 0 ].uxMax, 572 pxCurrentEntries->xEntries[ 1 ].uxCount, pxCurrentEntries->xEntries[ 1 ].uxMax, 573 pxCurrentEntries->xEntries[ 2 ].uxCount, pxCurrentEntries->xEntries[ 2 ].uxMax, 574 pxCurrentEntries->xEntries[ 3 ].uxCount, pxCurrentEntries->xEntries[ 3 ].uxMax ) ); 575 576 if( uxCompleteCount >= pxCurrentEntries->uxEntryCount ) 577 { 578 FreeRTOS_printf( ( "prvWritePackets: all %lu packets have been collected\n", pxCurrentEntries->uxEntryCount ) ); 579 580 if( pxCurrentEntries != NULL ) 581 { 582 FILE * outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" ); 583 584 if( outfile == NULL ) 585 { 586 FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) ); 587 } 588 else 589 { 590 /* 591 * Create a list with pointers to each network packet. 592 * DumpPacket_t *xPacketList[ dumpPACKET_COUNT ] = 593 * { 594 * &xPacket_0000, 595 * &xPacket_0001, 596 * &xPacket_0002, 597 * &xPacket_0003, 598 * } 599 */ 600 _fprintf( outfile, "\nDumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =\n{\n" ); 601 602 for( uxIndex = 0; uxIndex < uxNextPacketNumber; uxIndex++ ) 603 { 604 _fprintf( outfile, "\t&xPacket_%04lu,\n", uxIndex ); 605 } 606 607 _fprintf( outfile, "};\n" ); 608 fclose( outfile ); 609 vWriteHeaderFile(); 610 } 611 612 pxCurrentEntries = NULL; 613 614 /* Tell the thread and the function dump_packet() that packet 615 * dumping is ready. */ 616 xDumpingReady = pdTRUE; 617 } 618 619 return; 620 } 621 622 if( xUseIt == pdFALSE ) 623 { 624 return; 625 } 626 627 printf( "prvWritePackets: Read %lu bytes, type %s\n", uxLength, pcTypeString ); 628 629 FILE * outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" ); 630 631 if( outfile == NULL ) 632 { 633 FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) ); 634 return; 635 } 636 637 if( xFirstPacket != 0 ) 638 { 639 char * pcPtr; 640 size_t xLength; 641 642 vWriteHeaderFile( pcHeaderFileName ); 643 xLength = snprintf( pcString, sizeof pcString, pcHeaderCode, pcHeaderFileName ); 644 fwrite( pcString, 1u, xLength, outfile ); 645 xFirstPacket = pdFALSE; 646 } 647 648 _fprintf( outfile, "\n/* Packet_%04d */\n", uxNextPacketNumber ); 649 _fprintf( outfile, "uint8_t ucPacket_%04lx[ %lu ] =\n{\n", uxNextPacketNumber, uxLength ); 650 651 for( uxOffset = 0u; uxOffset < uxLength; ) 652 { 653 size_t uxCurLength = 0u; 654 size_t uxLast = uxOffset + dumpBYTES_PER_ROW; 655 BaseType_t xFirst = pdTRUE; 656 657 if( uxLast > uxLength ) 658 { 659 uxLast = uxLength; 660 } 661 662 while( uxOffset < uxLast ) 663 { 664 uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s0x%02x", 665 ( uxCurLength == 0 ) ? "\t" : ", ", pucBuffer[ uxOffset ] ); 666 uxOffset++; 667 } 668 669 if( uxCurLength != 0u ) 670 { 671 uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s\n", 672 ( uxOffset == uxLength ) ? "\n};" : "," ); 673 fwrite( pcString, 1u, uxCurLength, outfile ); 674 } 675 } 676 677 _fprintf( outfile, "\n" ); 678 679 _fprintf( outfile, 680 "DumpPacket_t xPacket_%04lx =\n{\n" 681 "\t.pucData = ucPacket_%04lx,\n" 682 "\t.uxLength = %lu,\n" 683 "\t.ulType = 0x%lX, /* %s */\n", 684 uxNextPacketNumber, uxNextPacketNumber, uxLength, ulTypeMask, pcTypeString ); 685 686 if( usSourcePort != 0u ) 687 { 688 _fprintf( outfile, 689 "\t.usSource = %u,\n", FreeRTOS_ntohs( usSourcePort ) ); 690 } 691 692 if( usSourcePort != 0u ) 693 { 694 _fprintf( outfile, 695 "\t.usDestination = %u,\n", FreeRTOS_ntohs( usDestinationPort ) ); 696 } 697 698 _fprintf( outfile, 699 "};\n" 700 "/*-----------------------------------------------------------*/\n\n" ); 701 fclose( outfile ); 702 uxNextPacketNumber++; 703 } 704 /*-----------------------------------------------------------*/ 705 706 #endif /* ( ipconfigUSE_DUMP_PACKETS != 0 ) */ 707