This wiki has been migrated to https://gitlab.com/wireshark/wireshark/-/wikis/home and is now deprecated. Please use that site instead.

Attachment 'ntartest.c'

Download

   1 /*
   2  * ntartest.c
   3  *
   4  *  $Id: ntartest.c 13 2008-01-10 17:35:21Z jyoung $
   5  *
   6  * Copyright 2008 Jim Young 
   7  *
   8  * This program is free software; you can redistribute it and/or
   9  * modify it under the terms of the GNU General Public License
  10  * as published by the Free Software Foundation; either version 2
  11  * of the License, or (at your option) any later version.
  12  *
  13  * This program is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16  * GNU General Public License for more details.
  17  *
  18  * You should have received a copy of the GNU General Public License
  19  * along with this program; if not, write to the Free Software
  20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21  *
  22  * ====
  23  *
  24  * This is an extemely simple minded utility to test certain 
  25  * charteristics regarding the block headers of the ntar (aka 
  26  * PcapNG) file format.
  27  *
  28  * It really only pays attention to the block headers.  It does 
  29  * not try to parse or validate that the payload types are well
  30  * formed nor if the block trailers are consistent with their
  31  * respective block headers.
  32  *
  33  * An ntar file consists of a series of variable length blocks.
  34  * Each block consists of two mandatory components a block header
  35  * (8 octets) and a block trailer (4 octets), and may optionally
  36  * contain a payload.
  37  *
  38  * The block header consists of two 32 bit components:
  39  *   A block type (32 bits (4 octets))
  40  *   A block length (32 bits (4 octets))
  41  *
  42  * The block trailer conists of one 32 bit component:
  43  *   The block length (32 bits (4 octets))
  44  *
  45  * Therefore a minimum length block (i.e. a block with no 
  46  * payload) is 12 octets in length.
  47  * 
  48  * If the optional payload is prosent it must contain one or 
  49  * more octets of data.
  50  *
  51  * The actual length of a block must be evenly divisable by four.
  52  * 
  53  * If the number of data octets is not a multiple of four, then
  54  * 1 to 3 padding bytes (NUL characters) must be inserted after
  55  * the last payload byte and before the block trailer.
  56  *
  57  * Please note that the reported block length (the block length
  58  * written into the block header and block trailer) MAY be 1 to 
  59  * 3 octets less that the actual blocklength due to the padding.
  60  *
  61  * NOTE: The discepency of the reported block length versus the 
  62  * actual block length could arguably be be considered a defect 
  63  * in the current ntar spec and could possible be corrected.  
  64  * Each of currently defined payloads have their own header 
  65  * structure and in theory would indicate payloads whose
  66  * length is not evenly divisable by 4.  Would could argue that
  67  * the blockLength filed should always directly indicate the 
  68  * actual length of the block.
  69  *
  70  * For the offical ntar/pcapng format see:
  71  *
  72  *   http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
  73  */
  74 
  75 #include <stdio.h>
  76 
  77 /*
  78  * The following typedef name (gunit32) was "borrowed" from glib 
  79  * which is defines the guint32 as follows:
  80  *
  81  * "An unsigned integer guaranteed to be 32 bits on all platforms. 
  82  * Values of this type can range from 0 to 4,294,967,295."
  83  *
  84  * WARNING: Within this context of this little source module the 
  85  * above compile time claim of the byte width is NOT assured!!! 
  86  * A startup runtime test within this source attempts to verify 
  87  * that this gunit32 is really 32 bits wide.
  88  */
  89 
  90 typedef unsigned int guint32;
  91 
  92 /*
  93  * defines
  94  */
  95 
  96 #define min(a, b) ((a) > (b) ? (b) : (a)) 
  97 
  98 #define ENDIAN_MAGIC 0x1A2B3C4D
  99 
 100 #define READ_START_OF_FILE 1
 101 #define READ_BLOCK_HEADER 2
 102 #define READ_MAGIC 3
 103 #define READ_DATA 4
 104 
 105 
 106 #define ENDIAN_UNKNOWN	0
 107 #define ENDIAN_BIG	1
 108 #define ENDIAN_LITTLE	2
 109 
 110 struct ntarHeader {
 111     guint32 blockType;
 112     guint32 blockLength;
 113 };
 114 
 115 /*
 116  * prototypes
 117  */
 118 
 119 static guint32 GetDataWord(int /* mySystemEndianness */ , int /* endiantype */ , unsigned char * /* data */ );
 120 static int ReadBlockHeader(FILE * /* myFile */ , struct ntarHeader * /* myHeader */ );
 121 static int GetSystemEndianness(void);
 122 static int GetSectionEndianness(unsigned char * /* inData */ );
 123 
 124 /*
 125  * globals
 126  */
 127 
 128 unsigned char myBuffer[4096];
 129 
 130 /*
 131  * main():
 132  */
 133 
 134 int main(int argc, char *argv[])
 135 {
 136     guint32 blockType = 0;
 137     guint32 blockTotalStart = 0;
 138     guint32 blockTotalEnd = 0;
 139     FILE *myFile;
 140     char *myFileName;
 141     int readLength;
 142     guint32 totalRead = 0;
 143     int nextRead = READ_START_OF_FILE;
 144     int myBlockType = 0;
 145     guint32 myDataWord;
 146     struct ntarHeader myHeader;
 147     int mySystemEndianness;
 148     int mySectionEndianness;
 149     int blockEndianType = 0;
 150     unsigned adjustedBlockLength;
 151     guint32 blockNumber = 0;
 152 
 153     if (argc != 2) {
 154         printf("Usage: ntartest FILENAME\n");
 155         exit(1);    
 156     }
 157 
 158     myFileName = argv[1];
 159  
 160     mySystemEndianness = GetSystemEndianness();
 161 
 162     if ( sizeof(guint32) != 4 ) {
 163         printf ("oops: sizeof guint32 (in octets) = %d, which is not 4 (32 bits)!\n", sizeof(guint32)); 
 164         exit(99);
 165     }
 166 
 167     myFile = fopen(myFileName, "rb");
 168 
 169     if(myFile == NULL) {
 170          printf("Could not open file \"%s\"\n", myFileName);
 171          exit(99);
 172     }
 173 
 174     printf("+++Working on file: %s\n", myFileName);
 175 
 176     switch(mySystemEndianness)
 177     {
 178         case ENDIAN_BIG: {
 179             printf("This machine is big-endian.\n");
 180             break;
 181         }
 182         case ENDIAN_LITTLE: {
 183             printf("This machine is little-endian.\n");
 184             break;
 185         }
 186         case ENDIAN_UNKNOWN: {
 187             printf("Endianness for this machine could not be determined.\n");
 188             exit(99);
 189             break;
 190         }
 191         default: {
 192             printf("Unexpected endianness value %d (%0x).\n", mySystemEndianness, mySystemEndianness);
 193             exit(99);
 194             break;
 195         }
 196     }
 197              
 198     while(!feof(myFile)) {
 199 
 200         readLength = ReadBlockHeader(myFile, &myHeader);
 201 
 202         if(readLength < 8) {
 203             if(readLength == 0 && feof(myFile))
 204                  break;
 205 
 206             printf ("Oops: short read, should have read 8 bytes, only read %d, are we reading from a pipe or an open file?.\n", \
 207                     readLength);
 208             exit(99);
 209         }
 210 
 211         blockNumber++;
 212 
 213         if (myHeader.blockType == 0x0a0d0d0a) {
 214             readLength = fread(myBuffer, 1, 4, myFile);
 215 
 216             if (readLength != 4) {
 217                 printf ("Oops: short read, should have read %d bytes, only read %d.\n", 4, readLength);
 218                 exit(99);
 219             }
 220 
 221             mySectionEndianness = GetSectionEndianness(myBuffer);
 222 
 223             switch(mySectionEndianness)
 224             {
 225                 case ENDIAN_BIG: {
 226                     printf("This section is big-endian.\n");
 227                     break;
 228                 }
 229                 case ENDIAN_LITTLE: {
 230                     printf("This section is little-endian.\n");
 231                     break;
 232                 }
 233                 case ENDIAN_UNKNOWN: {
 234                     printf("Endianness for this section could not be determined.\n");
 235                     break;
 236                 }
 237                 default: {
 238                     printf("Unexpected endianness value %d (%0x).\n", mySectionEndianness, mySectionEndianness);
 239                     break;
 240                 }
 241             }
 242         }
 243              
 244         myHeader.blockType = GetDataWord(mySystemEndianness, mySectionEndianness, (unsigned char *)&myHeader.blockType);
 245         myHeader.blockLength = GetDataWord(mySystemEndianness, mySectionEndianness, (unsigned char *)&myHeader.blockLength);
 246 
 247         printf("\n");
 248 
 249         switch(myHeader.blockType)
 250         {
 251              case 0x00000001: /* Interface Description Block */
 252                  printf("%08x: Block #%u, Type = Interface Description Block (%08x)\n", totalRead, blockNumber, myHeader.blockType);
 253                  break;
 254              case 0x00000002: /* Packet Block */
 255                  printf("%08x: Block #%u, Type = Packet Block (%08x)\n", totalRead, blockNumber, myHeader.blockType);
 256                  break;
 257              case 0x00000003: /* Simple Packet Block */
 258                  printf("%08x: Block #%u, Type = Simple Packet Block (%08x)\n", totalRead, blockNumber, myHeader.blockType);
 259                  break;
 260              case 0x00000004: /* Name Resolution Block */
 261                  printf("%08x: Block #%u, Type = Name Resolution Block (%08x)\n", totalRead, blockNumber, myHeader.blockType);
 262                  break;
 263              case 0x00000005: /* Interface Statistics Block */
 264                  printf("%08x: Block #%u, Type = Interface Statistics Block (%08x)\n", totalRead, blockNumber, myHeader.blockType);
 265                  break;
 266              case 0x00000006: /* Enhanced Packet Block */
 267                  printf("%08x: Block #%u, Type = Enhanced Packet Block (%08x)\n", totalRead, blockNumber, myHeader.blockType);
 268                  break;
 269              case 0x0a0d0d0a: /* Section Header Block */
 270                  printf("%08x: Block #%u, Type = Section Header Block (%08x)\n", totalRead, blockNumber, myHeader.blockType);
 271                  break;
 272              default:
 273                  if (myHeader.blockType == 0x0a0a0d0a
 274                  || (myHeader.blockType >= 0x0a0d0a00 && myHeader.blockType <= 0x0a0d0aff)
 275                  || (myHeader.blockType >= 0x0d0d0a00 && myHeader.blockType <= 0x0d0d0aff)) {
 276                      printf("%08x: Corrupted Section header. (%08x)\n", totalRead, myHeader.blockType);
 277                      exit(99);
 278                  } else {
 279                      printf("%08x: Unknown Block Type (%08x)\n", totalRead, myHeader.blockType);
 280                  }
 281         }
 282 
 283         totalRead += 4;
 284 
 285         /*
 286          * adjusted block length
 287          *
 288          * A non-obvious characteristic of the current ntar blocklength is
 289          * that blocklength MAY not actually indicate the length of the
 290          * actual data block (the payload).  If the number of payload 
 291          * octets is NOT evenly divisable by four (4) then the one or 
 292          * more padding bytes will have been added after the payload and 
 293          * before the blocktrailer to pad the length of the payload to a
 294          * 32 bit boundry.  To seek forwards or backwards to the next or 
 295          * previous block one will need to add from 0 to 3 to the reported 
 296          * blockLength to detremine where the next block will start.
 297          */
 298 
 299         adjustedBlockLength = myHeader.blockLength;
 300 
 301         switch(adjustedBlockLength % 4)
 302         {
 303              case 0:
 304                  printf("+++ blockLength %% 4 = 0, no pad bytes\n");
 305                  break;
 306              case 1:
 307                  printf("+++ blockLength %% 4 = 1, add 3 pad bytes\n");
 308                  adjustedBlockLength +=3;
 309                  break;
 310              case 2:
 311                  printf("+++ blockLength %% 4 = 2, add 2 pad bytes\n");
 312                  adjustedBlockLength +=2;
 313                  break;
 314              case 3:
 315                  printf("+++ blockLength %% 4 = 3, add 1 pad bytes\n");
 316                  adjustedBlockLength +=1;
 317                  break;
 318              default:
 319                  printf("+++ Unexpected remainder: %d\n", adjustedBlockLength % 4);
 320                  break;
 321         }
 322 
 323         printf("%08x: Reported Block Length %u (%08x), Adjusted Block Length %u (%08x), next block at offset %08x\n", \
 324                  totalRead, \
 325                  myHeader.blockLength, \
 326                  myHeader.blockLength, \
 327                  adjustedBlockLength, \
 328                  adjustedBlockLength, \
 329                  totalRead + ( adjustedBlockLength - 4));
 330 
 331         totalRead += 4;
 332 
 333         printf("%08x: Remainder of Block Data (%08x) bytes\n", totalRead, (adjustedBlockLength - 8), (adjustedBlockLength - 8));
 334 
 335         /*
 336          * Read in the rest of the block of data.
 337          *
 338          * Note: The following assumes that the payload will NOT exceed 
 339          * 4096 bytes.  A real program would have read loop that wouldn't 
 340          * break until the entire block in consumed.
 341          */
 342 
 343         if(myHeader.blockType == 0x0a0d0d0a) {
 344             readLength = fread(&myBuffer[4], 1, min((adjustedBlockLength - 12), 4096), myFile);
 345 
 346             if (readLength != (adjustedBlockLength - 12)) {
 347                     printf ("Oops: short read, should have read %d bytes, only read %d.\n",
 348                             (adjustedBlockLength - 12), readLength);
 349                     exit(99);
 350             }
 351              
 352         } else {
 353             readLength = fread(myBuffer, 1, min((adjustedBlockLength - 8), 4096), myFile);
 354 
 355             if (readLength != (adjustedBlockLength - 8)) {
 356                     printf ("Oops: short read, should have read %d bytes, only read %d.\n",
 357                             (adjustedBlockLength - 8), readLength);
 358                     exit(99);
 359             }
 360         }
 361 
 362         totalRead += readLength;
 363     }
 364 
 365     fclose(myFile);
 366 
 367     myFile = NULL;
 368 
 369     return 0;
 370 }
 371 
 372 /*
 373  * GetDataWord():
 374  */
 375 
 376 static guint32 GetDataWord(int mySystemEndianness, int endianType, unsigned char *inData)
 377 {
 378     union {
 379         guint32 l;
 380         char c[sizeof(guint32)];
 381     } ul;
 382 
 383     if(mySystemEndianness == endianType) {
 384         ul.c[0] = inData[0];
 385         ul.c[1] = inData[1];
 386         ul.c[2] = inData[2];
 387         ul.c[3] = inData[3];
 388     } else {
 389         ul.c[0] = inData[3];
 390         ul.c[1] = inData[2];
 391         ul.c[2] = inData[1];
 392         ul.c[3] = inData[0];
 393     }
 394 
 395     return ul.l;
 396 }
 397 
 398 
 399 /*
 400  * ReadBlockHeader():
 401  */
 402 
 403 static int ReadBlockHeader(FILE *myFile, struct ntarHeader *myHeader) 
 404 {
 405     return  fread(myHeader, 1, sizeof(struct ntarHeader), myFile); 
 406 }
 407 
 408 /*
 409  * GetSystemEndianness():
 410  *
 411  * Adapted from wikipedia:
 412  * http://en.wikipedia.org/wiki/Endianness
 413  */
 414 
 415 static int GetSystemEndianness(void)
 416 {
 417     union {
 418         short s;
 419         char c[sizeof(short)];
 420     } un;
 421 
 422     un.s = 0x0102;
 423 
 424     if(sizeof(short) == 2)
 425     {
 426         if(un.c[0] == 1 && un.c[1] == 2)
 427             return ENDIAN_BIG;
 428         else if(un.c[0] == 2 && un.c[1] == 1)
 429             return ENDIAN_LITTLE;
 430         else
 431             return ENDIAN_UNKNOWN;
 432     }
 433     else
 434     {
 435         return ENDIAN_UNKNOWN;
 436     }
 437 }
 438 
 439 
 440 /*
 441  * GetSectionEndianness():
 442  */
 443 
 444 static int GetSectionEndianness(unsigned char *inData)
 445 {
 446     if (inData[0] == 0x1a && inData[1] == 0x2b && inData[2] == 0x3c && inData[3] == 0x4d) {
 447         return ENDIAN_BIG;
 448     } else if (inData[0] == 0x4d && inData[1] == 0x3c && inData[2] == 0x2b && inData[3] == 0x1a) {
 449         return ENDIAN_LITTLE;
 450     } else {
 451         return ENDIAN_UNKNOWN;
 452     }
 453 }

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2015-08-23 17:12:48, 1.5 KB) [[attachment:dhcp.pcapng]]
  • [get | view] (2015-08-23 17:13:28, 1.5 KB) [[attachment:dhcp_big_endian.pcapng]]
  • [get | view] (2015-08-23 17:21:45, 1.5 KB) [[attachment:dhcp_little_endian.pcapng]]
  • [get | view] (2008-01-11 06:17:38, 26.0 KB) [[attachment:http.bigendian.ntar]]
  • [get | view] (2008-01-11 06:17:18, 26.0 KB) [[attachment:http.littleendian.ntar]]
  • [get | view] (2008-01-18 01:40:10, 29.5 KB) [[attachment:icmp.jpg]]
  • [get | view] (2008-01-18 01:39:40, 29.5 KB) [[attachment:icmp.ntar]]
  • [get | view] (2008-01-18 04:54:33, 0.9 KB) [[attachment:icmp2.ntar]]
  • [get | view] (2015-08-23 17:13:58, 20.4 KB) [[attachment:many_interfaces.pcapng]]
  • [get | view] (2008-01-11 06:43:23, 14.2 KB) [[attachment:ntartest.c]]
  • [get | view] (2009-05-22 00:29:40, 68.9 KB) [[attachment:pcap-ng_Wi-Fi_Bluetooth_USB_Cooked_timestamps_issue_1.ntar]]
  • [get | view] (2008-01-11 06:17:50, 0.0 KB) [[attachment:test001.ntar]]
  • [get | view] (2008-01-11 06:17:58, 0.0 KB) [[attachment:test002.ntar]]
  • [get | view] (2008-01-11 06:18:06, 0.0 KB) [[attachment:test003.ntar]]
  • [get | view] (2008-01-11 06:18:14, 0.1 KB) [[attachment:test004.ntar]]
  • [get | view] (2008-01-11 06:18:22, 0.1 KB) [[attachment:test005.ntar]]
  • [get | view] (2008-01-11 06:18:29, 0.3 KB) [[attachment:test006.ntar]]
  • [get | view] (2008-01-11 06:18:44, 0.2 KB) [[attachment:test007.ntar]]
  • [get | view] (2008-01-11 06:18:52, 0.2 KB) [[attachment:test008.ntar]]
  • [get | view] (2008-01-11 06:19:00, 0.1 KB) [[attachment:test009.ntar]]
  • [get | view] (2009-05-22 01:31:28, 0.2 KB) [[attachment:test010.ntar]]
 All files | Selected Files: delete move to page

You are not allowed to attach a file to this page.