capfileconvert_example.c

Reference Documentation

product_line_custom
Napatech SmartNIC
category
Reference Information

Go to the documentation of this file.

1/* 2 * %NT_SOFTWARE_LICENSE% 3 */ 4 5/** 6 * @example net/capfileconvert/capfileconvert_example.c 7 * 8 * @section capfileconvert_example_description Description 9 * 10 * This source file contain source code to convert cap files. 11 */ 12 13#define _GNU_SOURCE 14#include <stdio.h> 15#include <stdarg.h> 16#include <string.h> 17#include <stdlib.h> 18#include <signal.h> 19#include <unistd.h> 20#include <sys/types.h> 21#include <sys/mman.h> 22#include <sys/stat.h> 23#include <fcntl.h> 24#include <netinet/in.h> 25 26#include <argparse.h> 27#include <nt.h> 28#include "capfileconvert_example.h" 29 30#ifdef WIN32 31#undef lseek 32#define lseek _lseeki64 33#endif 34 35#define PKTBUF_SIZE (16*1024) 36#define CAPFILE_MAX_SIZE ((size_t)-1) 37 38 39/******************************************************************************/ 40/* Internal variables */ 41/******************************************************************************/ 42static enum InputFormat_e { 43 INPUT_FORMAT_UNKNOWN = 0, 44 INPUT_FORMAT_3GD, 45 INPUT_FORMAT_PCAP, 46 INPUT_FORMAT_PCAPNANO, 47 INPUT_FORMAT_2GD 48} input_format = 0; 49 50// Complete version string constant which can be searched for in the binary 51static const char* progname = "capfileconvert"; 52static int appRunning = 1; 53static unsigned long long pktNum; /* Count all packets */ 54static unsigned long long pktSkipNum; /* Count packets larger then 16kB */ 55 56static char* opt_input_file = NULL; 57static char* opt_output_file = NULL; 58static char* opt_output_format = NULL; 59static char* opt_input_format = NULL; 60static int opt_verbose = 0; 61 62static enum OutputFormat_e { 63 OUTPUT_FORMAT_UNKNOWN=0, 64 OUTPUT_FORMAT_PCAP, 65 OUTPUT_FORMAT_PCAPNANO, 66 OUTPUT_FORMAT_NT3GD 67} opt_outputformat = 0; 68static enum InputPCAPFormat_e { 69 INPUT_PCAPFORMAT_UNKNOWN=0, 70 INPUT_PCAPFORMAT_LIBPCAP, 71 INPUT_PCAPFORMAT_NAPATECH, 72} opt_inputformat = 0; 73 74/** 75 * Table of valid options. Mainly used for the getopt_long_only 76 * function. For further info see the manpage. 77 */ 78struct argparse_option arg_options[] = { 79 OPT_HELP(), 80 OPT_BOOLEAN('v', "verbose", &opt_verbose, "Print extra information", NULL, 0, 0, NULL), 81 OPT_STRING( 'i', "input", &opt_input_file, "Specifies the input file", NULL, 0, 0, "file"), 82 OPT_STRING( 'o', "output", &opt_output_file, "Specifies the output file", NULL, 0, 0, "file"), 83 OPT_STRING( 'f', "outputformat", &opt_output_format, "Specifies the output format: <pcap | pcapnano | nt3gd>", NULL, 0, 0, "format"), 84 OPT_STRING( 'n', "inputformat", &opt_input_format, "Specifies the input format when converting a pcap file: <libpcap | ntpcap>", NULL, 0, 0, "format"), 85 OPT_END(), 86}; 87 88#define NT_2GD_SEGMENT_DUMP_MAGIC 0xFEDEABBA 89struct Nt2GSegmentDumpHeader_s { 90 uint64_t magic0; 91 uint64_t magic1; 92 struct 93 { 94 uint32_t sectionOffset; 95 uint32_t numBytesAvailable; 96 uint32_t numDescriptorsAvailable; 97 uint64_t numDroppedFrames; 98 } segmentInfo; 99}; 100 101static struct NtFileHeader0_s nt3gdFileHeader = 102{ 103 NT_STID_FILE_HEADER0, 104 0, 105 NT_FILE_HEADER0_COOKIE, 106 NT_TIMESTAMP_TYPE_NATIVE, 107 0, 108 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 109 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}, 110 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 111 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}, 112}; 113#define PCAP_MAGIC 0xa1b2c3d4 114#define PCAP_SWAPPED_MAGIC 0xd4c3b2a1 115#define PCAP_MODIFIED_MAGIC 0xa1b2cd34 116#define PCAP_SWAPPED_MODIFIED_MAGIC 0x34cdb2a1 117#define PCAP_NSEC_MAGIC 0xa1b23c4d 118#define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1 119 120#define SWAPLONG(y) \ 121((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) 122#define SWAPSHORT(y) \ 123 ( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) ) 124 125/* 126 The following has been taken from: 127 http://wiki.wireshark.org/Development/LibpcapFileFormat 128*/ 129struct pcap_hdr_s { 130 uint32_t magic_number; /* magic number = 0xa1b2c3d4 */ 131 uint16_t version_major; /* major version number = 2 */ 132 uint16_t version_minor; /* minor version number = 4 */ 133 int32_t thiszone; /* GMT to local correction = 0 */ 134 uint32_t sigfigs; /* accuracy of timestamps = 0 */ 135 uint32_t snaplen; /* max length of captured packets, in octets = 10k */ 136 uint32_t network; /* data link type = 1 */ 137}; 138 139static struct pcap_hdr_s pcapGlobalHdr = 140{ 141 PCAP_MAGIC, 142 2, 143 4, 144 0, 145 0, 146 10000, 147 1 148}; 149 150static struct pcap_hdr_s pcapGlobalHdrNano = 151{ 152 PCAP_NSEC_MAGIC, 153 2, 154 4, 155 0, 156 0, 157 10000, 158 1 159}; 160 161struct nttimeval 162{ 163 uint32_t tv_sec; 164 uint32_t tv_usec; 165}; 166 167struct ntpcap { 168 struct nttimeval tv; 169 uint32_t caplen; 170 uint32_t len; 171}; 172 173static void DisplayProgramHeader(void) 174{ 175 printf("\r%s\n", progname); 176 177 /* Print separator line */ 178 for (int i = 0; i < 78; ++i) { 179 printf("="); 180 } 181 printf("\n"); 182} 183 184static void DisplayProgramFooter (void) 185{ 186 printf("\n"); 187} 188 189/* 190 * The function called when user is pressing CTRL-C 191 */ 192static void StopApplication(int sig) 193{ 194 (void)sig; 195 appRunning = 0; 196} 197 198static int _Convert(void) 199{ 200 FILE* hof = NULL; 201 int fdin = -1; // init by invalid file descriptor 202 off_t tmp_fSize; 203 size_t fSize = 0, dSize = 0; 204 uint8_t* pin = 0; 205 size_t offset = 0; 206 int pcap = 0; // Pcap format? 207 int nanotime = 0; // Is the pcap in nano time 208 int pcap_swapped = 0; 209 void* pktBuf; 210 int Result = 0; 211 212 if ((pktBuf = malloc(PKTBUF_SIZE)) == NULL) { 213 perror("Failed to allocate packet buffer of 16k\n"); 214 appRunning=0; 215 return 7; 216 } 217 218 // Open the output file 219 if ((hof = fopen(opt_output_file, "w+b")) == NULL) { 220 perror("Failed to create output file."); 221 appRunning = 0; 222 Result = 7; 223 goto _done; 224 } 225 // Open the input file 226#ifdef WIN32 227 if ((fdin = open(opt_input_file, _O_RDONLY | _O_BINARY, _S_IREAD)) == -1) { // NOTE: the mode parameter 0666 (RW-RW-RW) is ignored, because flag O_CREAT is not used 228#else 229 if (strcmp(opt_input_file, "-") == 0) { 230 fdin = 0; 231 } else if ((fdin = open(opt_input_file, O_RDONLY, 0666)) == -1) { // NOTE: the mode parameter 0666 (RW-RW-RW) is ignored, because flag O_CREAT is not used 232#endif 233 perror("Failed to open input file."); 234 appRunning = 0; 235 Result = 7; 236 goto _done; 237 } 238 239 /* Get the file size. 240 Note: 32-bit platforms can only handle files up to 4 GB due because 241 the implementation mmap's the file into memory. 242 The type size_t is intended for sizes that relate to a process, whereas 243 the type off_t is intended for file offsets, and the range of off_t 244 is typically wider than that of size_t. */ 245 (void)lseek(fdin, 0, SEEK_SET); 246 tmp_fSize = lseek(fdin, 0, SEEK_END); 247 if ((uint64_t)tmp_fSize > (uint64_t)CAPFILE_MAX_SIZE) { 248 fprintf(stderr, "The cap file is too big.\n"); 249 appRunning = 0; 250 Result = 9; 251 goto _done; 252 } 253 fSize = (size_t)tmp_fSize; /* Safe to cast due to test above */ 254 lseek(fdin, 0, SEEK_SET); 255 if (fSize < 16) { 256 fprintf(stderr, "Input file too small.\n"); 257 appRunning = 0; 258 Result = 9; 259 goto _done; 260 } 261 // MMAP the input file, this makes it a lot easier to ++ through it 262 if ((pin = (uint8_t*)mmap(NULL, fSize, PROT_READ, MAP_PRIVATE, fdin, 0)) == MAP_FAILED) { 263 perror("Failed to mmap input file.\n"); 264 appRunning = 0; 265 Result = 7; 266 goto _done; 267 } 268 269 /** 270 * Try to detect input file format 271 */ 272 // Check for 3GD file type 273 if ((((NtFileHeader0_t*)pin)->cookie == NT_FILE_HEADER0_COOKIE) && 274 (((NtFileHeader0_t*)pin)->structid == NT_STID_FILE_HEADER0)) { 275 printf("Input file detected as 3GD capture file.\n"); 276 offset=sizeof(NtFileHeader0_t); 277 dSize = fSize; 278 input_format = INPUT_FORMAT_3GD; 279 if (opt_inputformat != INPUT_PCAPFORMAT_UNKNOWN) { 280 fprintf(stderr, "Input format must only be set when converting a PCAP file.\n"); 281 appRunning = 0; 282 Result = 3; 283 goto _done; 284 } 285 } // Check for 2GD segment dump 286 else if ((((struct Nt2GSegmentDumpHeader_s*)pin)->magic0 == NT_2GD_SEGMENT_DUMP_MAGIC) && 287 (((struct Nt2GSegmentDumpHeader_s*)pin)->magic1 == NT_2GD_SEGMENT_DUMP_MAGIC)) { 288 289 printf("Input file detected as \"2GD segment dump\".\n"); 290 offset=sizeof(struct Nt2GSegmentDumpHeader_s); 291 dSize = ((struct Nt2GSegmentDumpHeader_s*)pin)->segmentInfo.numBytesAvailable+offset; 292 input_format = INPUT_FORMAT_2GD; 293 if (opt_inputformat != INPUT_PCAPFORMAT_UNKNOWN) { 294 fprintf(stderr, "Input format must only be set when converting a PCAP file.\n"); 295 appRunning = 0; 296 Result = 3; 297 goto _done; 298 } 299 } // Check for pcap and default to legacy 2GD capture 300 else { 301 switch (((struct pcap_hdr_s*)pin)->magic_number) { 302 case PCAP_NSEC_MAGIC: 303 nanotime=1; 304 // fall through 305 case PCAP_MAGIC: 306 // fall through 307 case PCAP_MODIFIED_MAGIC: 308 pcap=1; 309 offset = sizeof(struct pcap_hdr_s); 310 dSize = fSize; 311 if (nanotime) { 312 input_format = INPUT_FORMAT_PCAPNANO; 313 printf("Input file detected as \"PCAP-nano\".\n"); 314 } else { 315 input_format = INPUT_FORMAT_PCAP; 316 printf("Input file detected as \"PCAP\".\n"); 317 } 318 if (opt_inputformat == INPUT_PCAPFORMAT_UNKNOWN) { 319 fprintf(stderr, "Input format detected is PCAP. Type of PCAP format must be specified.\n"); 320 appRunning = 0; 321 Result = 3; 322 goto _done; 323 } 324 break; 325 case PCAP_SWAPPED_NSEC_MAGIC: 326 nanotime=1; 327 // fall through 328 case PCAP_SWAPPED_MODIFIED_MAGIC: 329 // fall through 330 case PCAP_SWAPPED_MAGIC: 331 pcap=1; 332 offset = sizeof(struct pcap_hdr_s); 333 dSize = fSize; 334 if (nanotime) { 335 printf("Input file detected as \"PCAP-nano\".\n"); 336 input_format = INPUT_FORMAT_PCAPNANO; 337 } else { 338 printf("Input file detected as \"PCAP\".\n"); 339 input_format = INPUT_FORMAT_PCAP; 340 } 341 pcap_swapped = 1; 342 if (opt_inputformat == INPUT_PCAPFORMAT_UNKNOWN) { 343 fprintf(stderr, "Input format detected is PCAP. Type of PCAP format must be specified.\n"); 344 appRunning = 0; 345 Result = 3; 346 goto _done; 347 } 348 break; 349 default: 350 { 351 /** 352 * PCAP has not been detected, assume legacy 2GD Capture but 353 * perform some sanity checks first though. 354 */ 355 const struct NtStd0Descr_s *p1 = (struct NtStd0Descr_s*)pin; 356 const unsigned SIZE_MAX_PKT = 10000U; 357 const unsigned SIZE_2GD_STD_DESC = 16U; 358 const unsigned SIZE_2GD_EXT_HDR = p1->extensionLength * 8U; 359 const unsigned MAX_STORED_LENGTH = 360 SIZE_MAX_PKT + SIZE_2GD_STD_DESC + SIZE_2GD_EXT_HDR; 361 int err=0; 362 if ((p1->storedLength <= fSize) && (p1->storedLength <= MAX_STORED_LENGTH)) { 363 if (p1->frameSliced) { 364 if (p1->wireLength < p1->storedLength) { 365 err=1; 366 } 367 } else if (p1->storedLength < p1->wireLength) { 368 err=1; 369 } 370 if (p1->storedLength < fSize) { 371 const struct NtStd0Descr_s *p2 = (struct NtStd0Descr_s*)((uint8_t*)pin+p1->storedLength); 372 if (p2->storedLength <= MAX_STORED_LENGTH) { 373 if (p2->frameSliced) { 374 if (p2->wireLength < p2->storedLength) { 375 err=1; 376 } 377 } else if (p2->storedLength < p2->wireLength) { 378 err=1; 379 } 380 } else { 381 err=1; 382 } 383 } 384 } else { 385 err=1; 386 } 387 if (err) { 388 fprintf(stderr, "Cannot detect input format.\n"); 389 appRunning=0; 390 Result = 9; 391 goto _done; 392 } 393 printf("Input file detected as \"2GD capture\".\n"); 394 dSize = fSize; 395 input_format = INPUT_FORMAT_2GD; 396 } 397 break; 398 } 399 } 400 401 /** 402 * The input file has been detected at this point. Do the convertion. 403 */ 404 // Start by creating the file header 405 switch (opt_outputformat) { 406 case OUTPUT_FORMAT_PCAP: 407 fwrite(&pcapGlobalHdr, sizeof(pcapGlobalHdr), 1, hof); 408 break; 409 case OUTPUT_FORMAT_PCAPNANO: 410 fwrite(&pcapGlobalHdrNano, sizeof(pcapGlobalHdr), 1, hof); 411 break; 412 case OUTPUT_FORMAT_NT3GD: 413 fwrite(&nt3gdFileHeader, sizeof(nt3gdFileHeader), 1, hof); 414 break; 415 default: 416 fprintf(stderr, "Unhandled output format.\n"); 417 appRunning = 0; 418 Result = 2; 419 goto _done; 420 } 421 // Now convert the packets 422 while ((offset < dSize) && appRunning) { 423 uint32_t storedLength; 424 void *descr = (void*)(pin+offset); 425 426 if (((NtDynDescr_t*)descr)->ntDynDescr) { 427 storedLength = ((NtDynDescr_t*)descr)->capLength; 428 } else if (((NtStd0Descr_t*)descr)->descriptorType) { 429 storedLength = ((NtStd0Descr_t*)descr)->storedLength; 430 } else { 431 if (pcap_swapped == 1) { 432 // PCAP native swapped format. Must be swapped before saving 433 storedLength = 16 + ntohl(((struct ntpcap *)descr)->caplen); 434 } else { 435 storedLength = 16 + (((struct ntpcap *)descr)->caplen); 436 } 437 } 438 if ((storedLength == 0) || (pcap && (storedLength == 16))){ 439 fprintf(stderr, "File error. StoredLength == 0 detected.\n"); 440 appRunning=0; 441 Result = 9; 442 break; 443 } 444 445 // Check that the packet is not too big 446 if (storedLength > PKTBUF_SIZE) { 447 (void)fprintf(stderr, 448 "Warning: Packet at offset %lld is too big (>%d kB) " 449 "and will be skipped.\n", 450 (unsigned long long)offset, (PKTBUF_SIZE / 1024)); 451 pktSkipNum++; 452 goto _NEXT_PACKET; 453 } 454 switch (opt_outputformat) { 455 case OUTPUT_FORMAT_PCAP: 456 switch (input_format) { 457 case INPUT_FORMAT_PCAP: 458 if (opt_inputformat == INPUT_PCAPFORMAT_LIBPCAP) { 459 if (pcap_swapped == 1) { 460 // PCAP native swapped format. Must be swapped before saving 461 memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen)); 462 ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen); 463 ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len); 464 ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec); 465 ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec); 466 fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof); 467 } 468 else { 469 // PCAP native format. No convert. Just copy the packet 470 fwrite(descr, 16+((struct ntpcap *)descr)->caplen, 1, hof); 471 } 472 } else { 473 // PCAP format is Napatech PCAP. Remove Padding and CRC. 474 if (((struct NtStd0Descr_s *)pktBuf)->storedLength >= ((struct NtStd0Descr_s *)pktBuf)->wireLength) { 475 memcpy(pktBuf, descr, 16+((struct NtStd0Descr_s *)pktBuf)->storedLength); 476 ((struct NtStd0Descr_s *)pktBuf)->wireLength = (unsigned short)(((struct NtStd0Descr_s *)pktBuf)->wireLength - 4); 477 ((struct NtStd0Descr_s *)pktBuf)->storedLength = ((struct NtStd0Descr_s *)pktBuf)->wireLength; 478 fwrite(pktBuf, 16+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof); 479 } 480 else { 481 fwrite(descr, 16+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof); 482 } 483 } 484 break; 485 case INPUT_FORMAT_PCAPNANO: 486 // Only convert timestamp 487 if (opt_inputformat == INPUT_PCAPFORMAT_LIBPCAP) { 488 if (pcap_swapped == 1) { 489 // PCAP native swapped format. Must be swapped before saving and convert timestamp 490 memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen)); 491 ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen); 492 ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len); 493 ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec); 494 ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec)/1000; 495 fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof); 496 } 497 else { 498 // PCAP native format. No convert. Just copy the packet 499 memcpy(pktBuf, descr, 16+((struct ntpcap *)pktBuf)->caplen); 500 ((struct nttimeval*)pktBuf)->tv_usec = ((struct nttimeval*)pktBuf)->tv_usec/1000; 501 fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof); 502 } 503 } else { 504 // PCAP format is Napatech PCAP. Remove Padding and CRC. 505 memcpy(pktBuf, descr, 16+((struct ntpcap *)pktBuf)->caplen); 506 ((struct nttimeval*)pktBuf)->tv_usec = ((struct nttimeval*)pktBuf)->tv_usec/1000; 507 if (((struct ntpcap *)pktBuf)->caplen >= ((struct ntpcap *)pktBuf)->len) { 508 ((struct NtStd0Descr_s *)pktBuf)->wireLength = (unsigned short)(((struct NtStd0Descr_s *)pktBuf)->wireLength - 4); 509 ((struct NtStd0Descr_s *)pktBuf)->storedLength = ((struct NtStd0Descr_s *)pktBuf)->wireLength; 510 fwrite(pktBuf, 16+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof); 511 } 512 else { 513 fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof); 514 } 515 } 516 break; 517 case INPUT_FORMAT_2GD: 518 case INPUT_FORMAT_3GD: 519 if (((NtDynDescr_t*)descr)->ntDynDescr) { 520 NtDynDescr_t *pDyn = (NtDynDescr_t*)descr; 521 // Convert by only copying storedLength, wireLength and timestamp 522 ((struct ntpcap*)pktBuf)->len = pDyn->capLength - pDyn->descrLength - 4; // pcap wirelength is wo crc 523 ((struct ntpcap*)pktBuf)->caplen = ((struct ntpcap*)pktBuf)->len; 524 switch ((enum NtDynamicDescriptorFormat_e)((NtDynDescr_t*)descr)->descrFormat) { 525 case NT_DYNAMIC_DESCRIPTOR_FORMAT_1: 526 { 527 NtDyn1Descr_t *pDyn1 = (NtDyn1Descr_t*)descr; 528 // Convert the ts. 529 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn1->timestamp/100000000); 530 ((struct ntpcap*)pktBuf)->tv.tv_usec = ((uint32_t)(pDyn1->timestamp%100000000)/100); 531 // Copy the payload 532 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn1->descrLength, ((struct ntpcap*)pktBuf)->caplen); 533 // Write the packet to disk 534 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 535 break; 536 } 537 case NT_DYNAMIC_DESCRIPTOR_FORMAT_2: 538 { 539 NtDyn2Descr_t *pDyn2 = (NtDyn2Descr_t*)descr; 540 // Convert the ts. 541 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn2->timestamp/100000000); 542 ((struct ntpcap*)pktBuf)->tv.tv_usec = ((uint32_t)(pDyn2->timestamp%100000000)/100); 543 // Copy the payload 544 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn2->descrLength, ((struct ntpcap*)pktBuf)->caplen); 545 // Write the packet to disk 546 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 547 break; 548 } 549 case NT_DYNAMIC_DESCRIPTOR_FORMAT_3: 550 { 551 NtDyn3Descr_t *pDyn3 = (NtDyn3Descr_t*)descr; 552 // Convert the ts. 553 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn3->timestamp/100000000); 554 ((struct ntpcap*)pktBuf)->tv.tv_usec = ((uint32_t)(pDyn3->timestamp%100000000)/100); 555 // Copy the payload 556 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn3->descrLength, ((struct ntpcap*)pktBuf)->caplen); 557 // Write the packet to disk 558 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 559 break; 560 } 561 case NT_DYNAMIC_DESCRIPTOR_FORMAT_4: 562 { 563 NtDyn4Descr_t *pDyn4 = (NtDyn4Descr_t*)descr; 564 // Convert the ts. 565 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn4->timestamp/100000000); 566 ((struct ntpcap*)pktBuf)->tv.tv_usec = ((uint32_t)(pDyn4->timestamp%100000000)/100); 567 // Copy the payload 568 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn4->descrLength, ((struct ntpcap*)pktBuf)->caplen); 569 // Write the packet to disk 570 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 571 break; 572 } 573 } 574 } else { 575 // Convert by only copying storedLength, wireLength and timestamp 576 ((struct ntpcap*)pktBuf)->len = ((struct NtStd0Descr_s *)descr)->wireLength-4; // pcap wirelength is wo crc 577 ((struct ntpcap*)pktBuf)->caplen = (((struct NtStd0Descr_s *)descr)->storedLength-(((struct NtStd0Descr_s *)descr)->extensionLength<<3)-16); 578 // In pcap stored cannot be longer than wire 579 if (((struct ntpcap*)pktBuf)->caplen > ((struct ntpcap*)pktBuf)->len) { 580 ((struct ntpcap*)pktBuf)->caplen = ((struct ntpcap*)pktBuf)->len; 581 } 582 // Convert the ts. 583 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(((struct NtStd0Descr_s *)descr)->timestamp/100000000); 584 ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((((struct NtStd0Descr_s *)descr)->timestamp%100000000)/100); 585 // Copy the payload 586 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+(((struct NtStd0Descr_s *)descr)->extensionLength<<3)+16, ((struct ntpcap*)pktBuf)->caplen); 587 // Write the packet to disk 588 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 589 } 590 break; 591 default: 592 fprintf(stderr, "Unhandled input format.\n"); 593 appRunning=0; 594 Result = 2; 595 goto _done; 596 } 597 break; 598 case OUTPUT_FORMAT_PCAPNANO: 599 switch (input_format) { 600 case INPUT_FORMAT_PCAP: 601 // Only convert timestamp 602 if (opt_inputformat == INPUT_PCAPFORMAT_LIBPCAP) { 603 if (pcap_swapped == 1) { 604 // PCAP native swapped format. Must be swapped before saving 605 memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen)); 606 ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen); 607 ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len); 608 ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec); 609 ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec)*1000; 610 fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof); 611 } 612 else { 613 // PCAP native format. No convert. Just copy the packet 614 memcpy(pktBuf, descr, 16+((NtStd0Descr_t *)descr)->storedLength); 615 ((struct nttimeval*)pktBuf)->tv_usec = (((struct nttimeval*)pktBuf)->tv_usec*1000); 616 fwrite(pktBuf, 16+((NtStd0Descr_t *)descr)->storedLength, 1, hof); 617 } 618 } else { 619 // PCAP format is Napatech PCAP. Remove Padding and CRC. 620 if (((NtStd0Descr_t *)descr)->storedLength >= ((NtStd0Descr_t *)descr)->wireLength) { 621 memcpy(pktBuf, descr, 16+((NtStd0Descr_t *)descr)->storedLength); 622 ((struct NtStd0Descr_s *)pktBuf)->wireLength = (unsigned short)(((struct NtStd0Descr_s *)pktBuf)->wireLength - 4); 623 ((struct NtStd0Descr_s *)pktBuf)->storedLength = ((struct NtStd0Descr_s *)pktBuf)->wireLength; 624 ((struct nttimeval*)pktBuf)->tv_usec = (((struct nttimeval*)pktBuf)->tv_usec*1000); 625 fwrite(pktBuf, 16+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof); 626 } 627 else { 628 memcpy(pktBuf, descr, 16+((NtStd0Descr_t *)descr)->storedLength); 629 ((struct nttimeval*)pktBuf)->tv_usec = (((struct nttimeval*)pktBuf)->tv_usec*1000); 630 fwrite(pktBuf, 16+((NtStd0Descr_t *)descr)->storedLength, 1, hof); 631 } 632 } 633 break; 634 case INPUT_FORMAT_PCAPNANO: 635 if (opt_inputformat == INPUT_PCAPFORMAT_LIBPCAP) { 636 if (pcap_swapped == 1) { 637 // PCAP native swapped format. Must be swapped before saving 638 memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen)); 639 ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen); 640 ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len); 641 ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec); 642 ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec); 643 fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof); 644 } 645 else { 646 // PCAP native format. No convert. Just copy the packet 647 fwrite(descr, 16+((NtStd0Descr_t *)descr)->storedLength, 1, hof); 648 } 649 } else { 650 // PCAP format is Napatech PCAP. Remove Padding and CRC. 651 if (((NtStd0Descr_t *)descr)->storedLength >= ((NtStd0Descr_t *)descr)->wireLength) { 652 memcpy(pktBuf, descr, 16+((NtStd0Descr_t *)descr)->storedLength); 653 ((struct NtStd0Descr_s *)pktBuf)->wireLength = (unsigned short)(((struct NtStd0Descr_s *)pktBuf)->wireLength - 4); 654 ((struct NtStd0Descr_s *)pktBuf)->storedLength = ((struct NtStd0Descr_s *)pktBuf)->wireLength; 655 fwrite(pktBuf, 16+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof); 656 } 657 else { 658 fwrite(descr, 16+((NtStd0Descr_t *)descr)->storedLength, 1, hof); 659 } 660 } 661 break; 662 case INPUT_FORMAT_2GD: 663 case INPUT_FORMAT_3GD: 664 if (((NtDynDescr_t*)descr)->ntDynDescr) { 665 NtDynDescr_t *pDyn = (NtDynDescr_t*)descr; 666 // Convert by only copying storedLength, wireLength and timestamp 667 ((struct ntpcap*)pktBuf)->len = pDyn->capLength - pDyn->descrLength - 4; // pcap wirelength is wo crc 668 ((struct ntpcap*)pktBuf)->caplen = ((struct ntpcap*)pktBuf)->len; 669 switch ((enum NtDynamicDescriptorFormat_e)((NtDynDescr_t*)descr)->descrFormat) { 670 case NT_DYNAMIC_DESCRIPTOR_FORMAT_1: 671 { 672 NtDyn1Descr_t *pDyn1 = (NtDyn1Descr_t*)descr; 673 // Convert the ts. 674 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn1->timestamp/100000000); 675 ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn1->timestamp%100000000)*10); 676 // Copy the payload 677 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn1->descrLength, ((struct ntpcap*)pktBuf)->caplen); 678 // Write the packet to disk 679 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 680 break; 681 } 682 case NT_DYNAMIC_DESCRIPTOR_FORMAT_2: 683 { 684 NtDyn2Descr_t *pDyn2 = (NtDyn2Descr_t*)descr; 685 // Convert the ts. 686 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn2->timestamp/100000000); 687 ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn2->timestamp%100000000)*10); 688 // Copy the payload 689 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn2->descrLength, ((struct ntpcap*)pktBuf)->caplen); 690 // Write the packet to disk 691 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 692 break; 693 } 694 case NT_DYNAMIC_DESCRIPTOR_FORMAT_3: 695 { 696 NtDyn3Descr_t *pDyn3 = (NtDyn3Descr_t*)descr; 697 // Convert the ts. 698 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn3->timestamp/100000000); 699 ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn3->timestamp%100000000)*10); 700 // Copy the payload 701 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn3->descrLength, ((struct ntpcap*)pktBuf)->caplen); 702 // Write the packet to disk 703 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 704 break; 705 } 706 case NT_DYNAMIC_DESCRIPTOR_FORMAT_4: 707 { 708 NtDyn4Descr_t *pDyn4 = (NtDyn4Descr_t*)descr; 709 // Convert the ts. 710 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn4->timestamp/100000000); 711 ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn4->timestamp%100000000)*10); 712 // Copy the payload 713 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn4->descrLength, ((struct ntpcap*)pktBuf)->caplen); 714 // Write the packet to disk 715 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 716 break; 717 } 718 } 719 } else { 720 // Convert by only copying storedLength, wireLength and timestamp 721 ((struct ntpcap*)pktBuf)->len = ((NtStd0Descr_t *)descr)->wireLength-4; // pcap wirelength is wo crc 722 ((struct ntpcap*)pktBuf)->caplen = (((NtStd0Descr_t *)descr)->storedLength-(((NtStd0Descr_t *)descr)->extensionLength<<3)-16); 723 // In pcap stored cannot be longer than wire 724 if (((struct ntpcap*)pktBuf)->caplen > ((struct ntpcap*)pktBuf)->len) { 725 ((struct ntpcap*)pktBuf)->caplen = ((struct ntpcap*)pktBuf)->len; 726 } 727 // Convert the ts. 728 ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(((NtStd0Descr_t *)descr)->timestamp/100000000); 729 ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((((NtStd0Descr_t *)descr)->timestamp%100000000)*10); 730 // Copy the payload. Payload (packet data) will immediately follow the packet header (header size is 4*32-bit words (16 bytes)) 731 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+(((NtStd0Descr_t *)descr)->extensionLength<<3)+16, ((struct ntpcap*)pktBuf)->caplen); 732 // Write the packet to disk 733 fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof); 734 } 735 break; 736 default: 737 fprintf(stderr, "Unhandled input format.\n"); 738 appRunning=0; 739 Result = 2; 740 goto _done; 741 } 742 break; 743 case OUTPUT_FORMAT_NT3GD: 744 switch (input_format) { 745 case INPUT_FORMAT_PCAPNANO: 746 case INPUT_FORMAT_PCAP: 747 // Clear the packet descriptor 748 *((uint64_t*)pktBuf+0)=0; 749 *((uint64_t*)pktBuf+1)=0; 750 // Convert timestamp 751 if (pcap_swapped == 1) { 752 if (nanotime) { 753 ((struct NtStd0Descr_s *)pktBuf)->timestamp = ((((uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_sec))*100000000)+(((uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_usec))/10)); 754 } else { 755 ((struct NtStd0Descr_s *)pktBuf)->timestamp = ((((uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_sec))*100000000)+(((uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_usec))*100)); 756 } 757 } 758 else { 759 if (nanotime) { 760 ((struct NtStd0Descr_s *)pktBuf)->timestamp = ((((uint64_t)((struct ntpcap*)descr)->tv.tv_sec)*100000000)+(((uint64_t)((struct ntpcap*)descr)->tv.tv_usec)/10)); 761 } else { 762 ((struct NtStd0Descr_s *)pktBuf)->timestamp = ((((uint64_t)((struct ntpcap*)descr)->tv.tv_sec)*100000000)+(((uint64_t)((struct ntpcap*)descr)->tv.tv_usec)*100)); 763 } 764 } 765 ((struct NtStd0Descr_s *)pktBuf)->descriptorType=1; // Mark NT descriptor 766 if (opt_inputformat == INPUT_PCAPFORMAT_LIBPCAP) { 767 // PCAP native format. 768 uint32_t caplen; 769 uint32_t len; 770 771 if (pcap_swapped == 1) { 772 caplen = ntohl(((struct ntpcap*)descr)->caplen); 773 len = ntohl(((struct ntpcap*)descr)->len); 774 } 775 else { 776 caplen = ((struct ntpcap*)descr)->caplen; 777 len = ((struct ntpcap*)descr)->len; 778 } 779 780 if (len > caplen) { 781 // Sliced packet 782 ((struct NtStd0Descr_s *)pktBuf)->frameSliced=1; 783 ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)((caplen+16+7)&~7); 784 } else if (len < caplen) { 785 fprintf(stderr, "Error in Packet at offset %lld. Stored length %d must not be larger than the wire length %d.\n", (unsigned long long)offset, 786 caplen, 787 len); 788 fprintf(stderr, "This could be a Napatech capture file with PCAP headers.\n"); 789 (void)fprintf(stderr, "Try to run the tool again with --inputformat=ntpcap.\n"); 790 appRunning=0; 791 Result = 9; 792 goto _done; 793 } else { 794 // Remember 4byte crc 795 ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)((caplen+16+4+7)&~7); 796 } 797 if (len > 10000) { 798 // Hard sliced packet 799 ((struct NtStd0Descr_s *)pktBuf)->hardSlice=1; 800 ((struct NtStd0Descr_s *)pktBuf)->storedLength=((10000+sizeof(struct NtStd0Descr_s)+7)&~7); // StoredLength must be 8byte aligned 801 } 802 ((struct NtStd0Descr_s *)pktBuf)->wireLength=(uint16_t)(len+4); // NT format is with checksum but we need to ask the HW to recalc it 803 ((struct NtStd0Descr_s *)pktBuf)->txCrcOverride=1; 804 805 // Copy payload 806 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+16, caplen); 807 } else { 808 // PCAP format is Napatech PCAP. Padding and CRC is already done in the file. 809 if (((struct ntpcap*)descr)->len > ((struct ntpcap*)descr)->caplen) { 810 // Sliced packet 811 ((struct NtStd0Descr_s *)pktBuf)->frameSliced=1; 812 ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)(((struct ntpcap*)descr)->caplen+16); 813 } else { 814 // The 4 byte crc is already included. Remove padding if exist and add them again. 815 ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)((((struct ntpcap*)descr)->len+16+7)&~7); 816 } 817 if (((struct ntpcap*)descr)->len > 10000) { 818 // Hard sliced packet 819 ((struct NtStd0Descr_s *)pktBuf)->hardSlice=1; 820 ((struct NtStd0Descr_s *)pktBuf)->storedLength=((10000+sizeof(struct NtStd0Descr_s)+7)&~7); // StoredLength must be 8byte aligned 821 } 822 ((struct NtStd0Descr_s *)pktBuf)->wireLength=(uint16_t)(((struct ntpcap*)descr)->len); // NT format is with checksum but we need to ask the HW to recalc it 823 ((struct NtStd0Descr_s *)pktBuf)->txCrcOverride=1; 824 825 // Copy payload 826 memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+16, ((struct ntpcap*)descr)->caplen); 827 } 828 fwrite(pktBuf, ((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof); 829 break; 830 case INPUT_FORMAT_2GD: 831 case INPUT_FORMAT_3GD: 832 // No convert. Just copy the packet 833 if (((NtDynDescr_t*)descr)->ntDynDescr) { 834 fwrite(descr, ((NtDynDescr_t *)descr)->capLength, 1, hof); 835 } else { 836 fwrite(descr, ((NtStd0Descr_t *)descr)->storedLength, 1, hof); 837 } 838 break; 839 default: 840 fprintf(stderr, "Unhandled input format.\n"); 841 appRunning=0; 842 Result = 2; 843 goto _done; 844 } 845 break; 846 default: 847 fprintf(stderr, "Unhandled output format.\n"); 848 appRunning=0; 849 Result = 2; 850 goto _done; 851 } 852 // Next packet 853 _NEXT_PACKET: 854 offset += storedLength; 855 pktNum++; 856 } 857 858 if (opt_verbose) { 859 printf("File size: 0x%lX (%ld) offset: 0x%lX (%ld)\n", dSize, dSize, offset, offset); 860 } 861 862 if (!pktSkipNum) 863 (void)printf("Conversion done. Converted %llu packets.\n", pktNum); 864 else 865 (void)printf("Conversion done. Converted %llu and skipped %llu packets.\n", 866 (pktNum - pktSkipNum), pktSkipNum); 867 868_done: 869 // Unmap the input file 870 if (pin) { 871 munmap(pin, fSize); 872 } 873 // Close input file 874 if (fdin != -1) { 875 close(fdin); 876 } 877 // Close output file 878 if (hof) { 879 fclose(hof); 880 } 881 /* Release heap memory */ 882 free(pktBuf); 883 884 return Result; 885} 886 887// 888// main 889// 890int main(int argc, const char *argv[]) 891{ 892 int ApplExitCode; 893 struct argparse argparse; 894 895 DisplayProgramHeader(); 896 897 argparse_init(&argparse, arg_options, usageText, 0); 898 argparse_parse(&argparse, argc, argv); 899 if (opt_output_format != NULL) { 900 if (strstr(opt_output_format, "pcapnano")) { 901 opt_outputformat = OUTPUT_FORMAT_PCAPNANO; 902 } else if (strstr(opt_output_format, "pcap")) { 903 opt_outputformat = OUTPUT_FORMAT_PCAP; 904 } else if (strstr(opt_output_format, "nt3gd")) { 905 opt_outputformat = OUTPUT_FORMAT_NT3GD; 906 } else { 907 fprintf(stderr, "Unknown output format: %s\n", opt_output_format); 908 return 2; 909 } 910 } 911 if (opt_input_format != NULL) { 912 if (strstr(opt_input_format, "libpcap")) { 913 opt_inputformat = INPUT_PCAPFORMAT_LIBPCAP; 914 } else if (strstr(opt_input_format, "ntpcap")) { 915 opt_inputformat = INPUT_PCAPFORMAT_NAPATECH; 916 } else { 917 fprintf(stderr, "Unknown input format: %s\n", opt_input_format); 918 return 2; 919 } 920 } 921 922 if (opt_outputformat==0) { 923 fprintf(stderr, "No output format provided.\n"); 924 return 4; 925 } 926 if (opt_input_file==NULL) { 927 fprintf(stderr, "No input file provided.\n"); 928 return 4; 929 } 930 931 if (opt_output_file==NULL) { 932 fprintf(stderr, "No output file provided.\n"); 933 return 4; 934 } 935 936 struct sigaction newaction; 937 memset(&newaction, 0, sizeof(newaction)); 938 newaction.sa_handler = StopApplication; 939 if (sigaction(SIGINT, &newaction, NULL) < 0) { 940 fprintf(stderr, "Failed to register SIGINT sigaction.\n"); 941 exit(7); 942 } 943 944 945 if ((ApplExitCode = _Convert()) != 0) { 946 fprintf(stderr, ">>> Error: Convert failed.\n"); 947 } 948 949 DisplayProgramFooter(); 950 951 return ApplExitCode; 952} 953 954// 955// EOF 956//