capfileconvert_example.c Source File

Reference Documentation

Platform
Napatech SmartNIC
Content Type
Reference Information
Capture Software Version
Link™ Capture Software 12.15
Napatech Software Suite: examples/net/capfileconvert/capfileconvert_example.c Source File
capfileconvert_example.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2025 Napatech A/S. All Rights Reserved.
4  *
5  * 1. Copying, modification, and distribution of this file, or executable
6  * versions of this file, is governed by the terms of the Napatech Software
7  * license agreement under which this file was made available. If you do not
8  * agree to the terms of the license do not install, copy, access or
9  * otherwise use this file.
10  *
11  * 2. Under the Napatech Software license agreement you are granted a
12  * limited, non-exclusive, non-assignable, copyright license to copy, modify
13  * and distribute this file in conjunction with Napatech SmartNIC's and
14  * similar hardware manufactured or supplied by Napatech A/S.
15  *
16  * 3. The full Napatech Software License Agreement is included in this
17  * distribution, please see "NA-0009 Software License Agreement.pdf"
18  *
19  * 4. Redistributions of source code must retain this copyright notice,
20  * list of conditions and the following disclaimer.
21  *
22  * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, EXPRESS OR
23  * IMPLIED, AND NAPATECH DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING ANY
24  * IMPLIED WARRANTY OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, OR OF
25  * FITNESS FOR A PARTICULAR PURPOSE. TO THE EXTENT NOT PROHIBITED BY
26  * APPLICABLE LAW, IN NO EVENT SHALL NAPATECH BE LIABLE FOR PERSONAL INJURY,
27  * OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER,
28  * INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, CORRUPTION OR
29  * LOSS OF DATA, FAILURE TO TRANSMIT OR RECEIVE ANY DATA OR INFORMATION,
30  * BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING
31  * OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE NAPATECH SOFTWARE OR
32  * SERVICES OR ANY THIRD PARTY SOFTWARE OR APPLICATIONS IN CONJUNCTION WITH
33  * THE NAPATECH SOFTWARE OR SERVICES, HOWEVER CAUSED, REGARDLESS OF THE THEORY
34  * OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF NAPATECH HAS BEEN
35  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW
36  * THE EXCLUSION OR LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF
37  * INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU.
38  *
39  *
40 
41  */
42 
43 /**
44  * @example net/capfileconvert/capfileconvert_example.c
45  *
46  * @section capfileconvert_example_description Description
47  *
48  * This source file contain source code to convert cap files.
49  */
50 
51 // Include this in order to access the Napatech API
52 #include <nt.h>
53 
54 #define _GNU_SOURCE
55 #include <stdio.h>
56 #include <stdarg.h>
57 #include <string.h>
58 #include <stdlib.h>
59 #include <signal.h>
60 #include <unistd.h>
61 #include <sys/types.h>
62 #include <sys/mman.h>
63 #include <sys/stat.h>
64 #include <fcntl.h>
65 #include <netinet/in.h>
66 
67 #if defined(__linux__) || defined(__FreeBSD__)
68 #include <stdatomic.h>
69 #endif
70 
71 #include <argparse.h>
72 
73 #include "capfileconvert_example.h"
74 
75 #if defined(WIN32) || defined (WIN64)
76 #undef lseek
77 #define lseek _lseeki64
78 static volatile int appRunning = 1; /* The application will run as long as appRunning == 1 */
79 #else
80 static atomic_int appRunning = 1; /* The application will run as long as appRunning == 1 */
81 #endif
82 
83 #define PKTBUF_SIZE (16*1024)
84 #define CAPFILE_MAX_SIZE ((size_t)-1)
85 
86 
87 /******************************************************************************/
88 /* Internal variables */
89 /******************************************************************************/
90 static enum InputFormat_e {
97 } input_format = 0;
98 
99 // Complete version string constant which can be searched for in the binary
100 static const char* progname = "capfileconvert";
101 static unsigned long long pktNum; /* Count all packets */
102 static unsigned long long pktSkipNum; /* Count packets larger then 16kB */
103 
104 static char* opt_input_file = NULL;
105 static char* opt_output_file = NULL;
106 static char* opt_output_format = NULL;
107 static char* opt_input_format = NULL;
108 static int opt_verbose = 0;
109 
110 static enum OutputFormat_e {
116 } opt_outputformat = 0;
117 
118 static enum InputPCAPFormat_e {
122 } opt_inputformat = 0;
123 
124 /**
125  * Table of valid options. Mainly used for the getopt_long_only
126  * function. For further info see the manpage.
127  */
129  OPT_HELP(),
130  OPT_BOOLEAN('v', "verbose", &opt_verbose, "Print extra information", NULL, 0, 0, NULL),
131  OPT_STRING( 'i', "input", &opt_input_file, "Specifies the input file", NULL, 0, 0, "file"),
132  OPT_STRING( 'o', "output", &opt_output_file, "Specifies the output file", NULL, 0, 0, "file"),
133  OPT_STRING( 'f', "outputformat", &opt_output_format, "Specifies the output format: <pcap | pcapnano | nt3gd | nt3gdnano>", NULL, 0, 0, "format"),
134  OPT_STRING( 'n', "inputformat", &opt_input_format, "Specifies the input format when converting a pcap file: <libpcap | ntpcap>", NULL, 0, 0, "format"),
135  OPT_END(),
136 };
137 
138 #define NT_2GD_SEGMENT_DUMP_MAGIC 0xFEDEABBA
140  uint64_t magic0;
141  uint64_t magic1;
142  struct
143  {
144  uint32_t sectionOffset;
148  } segmentInfo;
149 };
150 
151 static struct NtFileHeader0_s nt3gdFileHeader =
152 {
153  NT_STID_FILE_HEADER0,
154  0,
155  NT_FILE_HEADER0_COOKIE,
157  0,
158  {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,
159  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,},
160  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
161  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
162 };
163 
164 static struct NtFileHeader0_s nt3gdNsFileHeader =
165 {
166  NT_STID_FILE_HEADER0,
167  0,
168  NT_FILE_HEADER0_COOKIE,
170  0,
171  {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,
172  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,},
173  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
174  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
175 };
176 
177 #define PCAP_MAGIC 0xa1b2c3d4
178 #define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
179 #define PCAP_MODIFIED_MAGIC 0xa1b2cd34
180 #define PCAP_SWAPPED_MODIFIED_MAGIC 0x34cdb2a1
181 #define PCAP_NSEC_MAGIC 0xa1b23c4d
182 #define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1
183 
184 #define SWAPLONG(y) \
185 ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
186 #define SWAPSHORT(y) \
187  ( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )
188 
189 /*
190  The following has been taken from:
191  http://wiki.wireshark.org/Development/LibpcapFileFormat
192 */
193 struct pcap_hdr_s {
194  uint32_t magic_number; /* magic number = 0xa1b2c3d4 */
195  uint16_t version_major; /* major version number = 2 */
196  uint16_t version_minor; /* minor version number = 4 */
197  int32_t thiszone; /* GMT to local correction = 0 */
198  uint32_t sigfigs; /* accuracy of timestamps = 0 */
199  uint32_t snaplen; /* max length of captured packets, in octets = 10k */
200  uint32_t network; /* data link type = 1 */
201 };
202 
203 static struct pcap_hdr_s pcapGlobalHdr =
204 {
205  PCAP_MAGIC,
206  2,
207  4,
208  0,
209  0,
210  10000,
211  1
212 };
213 
215 {
217  2,
218  4,
219  0,
220  0,
221  10000,
222  1
223 };
224 
225 struct nttimeval
226 {
227  uint32_t tv_sec;
228  uint32_t tv_usec;
229 };
230 
231 struct ntpcap {
232  struct nttimeval tv;
233  uint32_t caplen;
234  uint32_t len;
235 };
236 
237 static void DisplayProgramHeader(void)
238 {
239  printf("\r%s\n", progname);
240 
241  /* Print separator line */
242  for (int i = 0; i < 78; ++i) {
243  printf("=");
244  }
245  printf("\n");
246 }
247 
248 static void DisplayProgramFooter (void)
249 {
250  printf("\n");
251 }
252 
253 /*
254  * The function called when user is pressing CTRL-C
255  */
256 #if defined(WIN32) || defined (WIN64)
257 static BOOL WINAPI StopApplication(int sig)
258 {
259  (void) sig;
260  appRunning = 0;
261  return TRUE;
262 }
263 #else
264 static void StopApplication(int sig)
265 {
266  if (sig == SIGINT)
267  appRunning = 0;
268 }
269 #endif
270 
271 static int _Convert(void)
272 {
273  FILE* hof = NULL;
274  int fdin = -1; // init by invalid file descriptor
275  off_t tmp_fSize;
276  size_t fSize = 0, dSize = 0;
277  uint8_t* pin = 0;
278  size_t offset = 0;
279  int pcap = 0; // Pcap format?
280  int nanotime = 0; // Is the pcap in nano time
281  int nt3gdnano=0; //Is the nt3gd in nano time
282  int pcap_swapped = 0;
283  void* pktBuf;
284  int Result = 0;
285 
286  if ((pktBuf = malloc(PKTBUF_SIZE)) == NULL) {
287  perror("Failed to allocate packet buffer of 16k\n");
288  appRunning = 0;
289  return 7;
290  }
291 
292  // Open the output file
293  if ((hof = fopen(opt_output_file, "w+b")) == NULL) {
294  perror("Failed to create output file.");
295  appRunning = 0;
296  Result = 7;
297  goto _done;
298  }
299  // Open the input file
300 #if defined(WIN32) || defined (WIN64)
301  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
302 #else
303  if (strcmp(opt_input_file, "-") == 0) {
304  fdin = 0;
305  } 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
306 #endif
307  perror("Failed to open input file.");
308  appRunning = 0;
309  Result = 7;
310  goto _done;
311  }
312 
313  /* Get the file size.
314  Note: 32-bit platforms can only handle files up to 4 GB due because
315  the implementation mmap's the file into memory.
316  The type size_t is intended for sizes that relate to a process, whereas
317  the type off_t is intended for file offsets, and the range of off_t
318  is typically wider than that of size_t. */
319  (void)lseek(fdin, 0, SEEK_SET);
320  tmp_fSize = lseek(fdin, 0, SEEK_END);
321  if ((uint64_t)tmp_fSize > (uint64_t)CAPFILE_MAX_SIZE) {
322  fprintf(stderr, "The cap file is too big.\n");
323  appRunning = 0;
324  Result = 9;
325  goto _done;
326  }
327  fSize = (size_t)tmp_fSize; /* Safe to cast due to test above */
328  lseek(fdin, 0, SEEK_SET);
329  if (fSize < 16) {
330  fprintf(stderr, "Input file too small.\n");
331  appRunning = 0;
332  Result = 9;
333  goto _done;
334  }
335  // MMAP the input file, this makes it a lot easier to ++ through it
336  if ((pin = (uint8_t*)mmap(NULL, fSize, PROT_READ, MAP_PRIVATE, fdin, 0)) == MAP_FAILED) {
337  perror("Failed to mmap input file.\n");
338  appRunning = 0;
339  Result = 7;
340  goto _done;
341  }
342 
343  /**
344  * Try to detect input file format
345  */
346  // Check for 3GD file type
347  if ((((NtFileHeader0_t*)pin)->cookie == NT_FILE_HEADER0_COOKIE) &&
348  (((NtFileHeader0_t*)pin)->structid == NT_STID_FILE_HEADER0)) {
349  printf("Input file detected as 3GD capture file.\n");
350  offset=sizeof(NtFileHeader0_t);
351  dSize = fSize;
352  if (((NtFileHeader0_t*)pin)->tsType == NT_TIMESTAMP_TYPE_UNIX_NANOTIME) {
353  printf("Input file detected as 3GD capture file with UNIX_NANO timestamp.\n");
355  nanotime=1;
356  } else {
357  printf("Input file detected as 3GD capture file.\n");
359  }
360 
362  fprintf(stderr, "Input format must only be set when converting a PCAP file.\n");
363  appRunning = 0;
364  Result = 3;
365  goto _done;
366  }
367  } // Check for 2GD segment dump
368  else if ((((struct Nt2GSegmentDumpHeader_s*)pin)->magic0 == NT_2GD_SEGMENT_DUMP_MAGIC) &&
370 
371  printf("Input file detected as \"2GD segment dump\".\n");
372  offset=sizeof(struct Nt2GSegmentDumpHeader_s);
373  dSize = ((struct Nt2GSegmentDumpHeader_s*)pin)->segmentInfo.numBytesAvailable+offset;
376  fprintf(stderr, "Input format must only be set when converting a PCAP file.\n");
377  appRunning = 0;
378  Result = 3;
379  goto _done;
380  }
381  } // Check for pcap and default to legacy 2GD capture
382  else {
383  switch (((struct pcap_hdr_s*)pin)->magic_number) {
384  case PCAP_NSEC_MAGIC:
385  nanotime=1;
386  // fall through
387  case PCAP_MAGIC:
388  // fall through
389  case PCAP_MODIFIED_MAGIC:
390  pcap=1;
391  offset = sizeof(struct pcap_hdr_s);
392  dSize = fSize;
393  if (nanotime) {
395  printf("Input file detected as \"PCAP-nano\".\n");
396  } else {
398  printf("Input file detected as \"PCAP\".\n");
399  }
401  fprintf(stderr, "Input format detected is PCAP. Type of PCAP format must be specified.\n");
402  appRunning = 0;
403  Result = 3;
404  goto _done;
405  }
406  break;
407 
409  nanotime=1;
410  // fall through
412  // fall through
413  case PCAP_SWAPPED_MAGIC:
414  pcap=1;
415  offset = sizeof(struct pcap_hdr_s);
416  dSize = fSize;
417  if (nanotime) {
418  printf("Input file detected as \"PCAP-nano\".\n");
420  } else {
421  printf("Input file detected as \"PCAP\".\n");
423  }
424  pcap_swapped = 1;
426  fprintf(stderr, "Input format detected is PCAP. Type of PCAP format must be specified.\n");
427  appRunning = 0;
428  Result = 3;
429  goto _done;
430  }
431  break;
432 
433  default:
434  {
435  /**
436  * PCAP has not been detected, assume legacy 2GD Capture but
437  * perform some sanity checks first though.
438  */
439  const struct NtStd0Descr_s *p1 = (struct NtStd0Descr_s*)pin;
440  const unsigned SIZE_MAX_PKT = 10000U;
441  const unsigned SIZE_2GD_STD_DESC = 16U;
442  const unsigned SIZE_2GD_EXT_HDR = p1->extensionLength * 8U;
443  const unsigned MAX_STORED_LENGTH =
444  SIZE_MAX_PKT + SIZE_2GD_STD_DESC + SIZE_2GD_EXT_HDR;
445  int err=0;
446  if ((p1->storedLength <= fSize) && (p1->storedLength <= MAX_STORED_LENGTH)) {
447  if (p1->frameSliced) {
448  if (p1->wireLength < p1->storedLength) {
449  err=1;
450  }
451  } else if (p1->storedLength < p1->wireLength) {
452  err=1;
453  }
454  if (p1->storedLength < fSize) {
455  const struct NtStd0Descr_s *p2 = (struct NtStd0Descr_s*)((uint8_t*)pin+p1->storedLength);
456  if (p2->storedLength <= MAX_STORED_LENGTH) {
457  if (p2->frameSliced) {
458  if (p2->wireLength < p2->storedLength) {
459  err=1;
460  }
461  } else if (p2->storedLength < p2->wireLength) {
462  err=1;
463  }
464  } else {
465  err=1;
466  }
467  }
468  } else {
469  err=1;
470  }
471  if (err) {
472  fprintf(stderr, "Cannot detect input format.\n");
473  appRunning = 0;
474  Result = 9;
475  goto _done;
476  }
477  printf("Input file detected as \"2GD capture\".\n");
478  dSize = fSize;
480  }
481  break;
482  }
483  }
484 
485  /**
486  * The input file has been detected at this point. Do the convertion.
487  */
488  // Start by creating the file header
489  switch (opt_outputformat) {
490  case OUTPUT_FORMAT_PCAP:
491  printf("Outputfile type is PCAP\n");
492  fwrite(&pcapGlobalHdr, sizeof(pcapGlobalHdr), 1, hof);
493  break;
495  printf("Outputfile type is PCAP NANO\n");
496  fwrite(&pcapGlobalHdrNano, sizeof(pcapGlobalHdr), 1, hof);
497  break;
498  case OUTPUT_FORMAT_NT3GD:
499  printf("Outputfile type is NT3GD\n");
500  fwrite(&nt3gdFileHeader, sizeof(nt3gdFileHeader), 1, hof);
501  break;
503  printf("Outputfile type is NT3GD NANO\n");
504  fwrite(&nt3gdNsFileHeader, sizeof(nt3gdNsFileHeader), 1, hof);
505  nt3gdnano = 1;
506  break;
507  default:
508  fprintf(stderr, "Unhandled output format.\n");
509  appRunning = 0;
510  Result = 2;
511  goto _done;
512  }
513 
514  // Now convert the packets
515  while ((offset < dSize) && appRunning == 1) {
516  uint32_t storedLength;
517  void *descr = (void*)(pin+offset);
518 
519  if (((NtDynDescr_t*)descr)->ntDynDescr) {
520  storedLength = ((NtDynDescr_t*)descr)->capLength;
521  } else if (((NtStd0Descr_t*)descr)->descriptorType) {
522  storedLength = ((NtStd0Descr_t*)descr)->storedLength;
523  } else {
524  if (pcap_swapped == 1) {
525  // PCAP native swapped format. Must be swapped before saving
526  storedLength = 16 + ntohl(((struct ntpcap *)descr)->caplen);
527  } else {
528  storedLength = 16 + (((struct ntpcap *)descr)->caplen);
529  }
530  }
531 
532  if ((storedLength == 0) || (pcap && (storedLength == 16))){
533  fprintf(stderr, "File error. StoredLength == 0 detected.\n");
534  appRunning = 0;
535  Result = 9;
536  break;
537  }
538 
539  // Check that the packet is not too big
540  if (storedLength > PKTBUF_SIZE) {
541  (void)fprintf(stderr,
542  "Warning: Packet at offset %lld is too big (>%d kB) "
543  "and will be skipped.\n",
544  (unsigned long long)offset, (PKTBUF_SIZE / 1024));
545  pktSkipNum++;
546  goto _NEXT_PACKET;
547  }
548  switch (opt_outputformat) {
549  case OUTPUT_FORMAT_PCAP:
550  switch (input_format) {
551  case INPUT_FORMAT_PCAP:
553  if (pcap_swapped == 1) {
554  // PCAP native swapped format. Must be swapped before saving
555  memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen));
556  ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen);
557  ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len);
558  ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec);
559  ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec);
560  fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof);
561  }
562  else {
563  // PCAP native format. No convert. Just copy the packet
564  fwrite(descr, 16+((struct ntpcap *)descr)->caplen, 1, hof);
565  }
566  } else {
567  // PCAP format is Napatech PCAP. Remove Padding and CRC.
568  const struct NtStd0Descr_s *const src = descr;
569  struct NtStd0Descr_s *const dst = pktBuf;
570  memcpy(dst, src, 16U + src->storedLength);
571  if (src->storedLength >= src->wireLength) {
572  // Adjust for padding and CRC
573  dst->wireLength = (uint16_t)(src->wireLength - 4U);
574  dst->storedLength = src->wireLength;
575  }
576  fwrite(dst, 16U + dst->storedLength, 1, hof);
577  }
578  break;
579 
581  // Only convert timestamp
583  if (pcap_swapped == 1) {
584  // PCAP native swapped format. Must be swapped before saving and convert timestamp
585  memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen));
586  ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen);
587  ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len);
588  ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec);
589  ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec)/1000;
590  fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof);
591  }
592  else {
593  // PCAP native format. No convert. Just copy the packet
594  memcpy(pktBuf, descr, 16U + ((struct ntpcap *)descr)->caplen);
595  ((struct nttimeval*)pktBuf)->tv_usec = ((struct nttimeval*)pktBuf)->tv_usec/1000;
596  fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof);
597  }
598  } else {
599  // PCAP format is Napatech PCAP. Remove Padding and CRC.
600  memcpy(pktBuf, descr, 16U + ((struct ntpcap *)descr)->caplen);
601  ((struct nttimeval*)pktBuf)->tv_usec = ((struct nttimeval*)pktBuf)->tv_usec/1000;
602  if (((struct ntpcap *)pktBuf)->caplen >= ((struct ntpcap *)pktBuf)->len) {
603  ((struct NtStd0Descr_s *)pktBuf)->wireLength = (unsigned short)(((struct NtStd0Descr_s *)pktBuf)->wireLength - 4);
604  ((struct NtStd0Descr_s *)pktBuf)->storedLength = ((struct NtStd0Descr_s *)pktBuf)->wireLength;
605  fwrite(pktBuf, 16U+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof);
606  }
607  else {
608  fwrite(pktBuf, 16U+((struct ntpcap *)pktBuf)->caplen, 1, hof);
609  }
610  }
611  break;
612 
613  case INPUT_FORMAT_2GD:
614  case INPUT_FORMAT_3GD:
615  if (((NtDynDescr_t*)descr)->ntDynDescr) {
616  NtDynDescr_t *pDyn = (NtDynDescr_t*)descr;
617  // Convert by only copying storedLength, wireLength and timestamp
618  ((struct ntpcap*)pktBuf)->len = (uint32_t)(pDyn->capLength - pDyn->descrLength - 4); // pcap wirelength is wo crc
619  ((struct ntpcap*)pktBuf)->caplen = ((struct ntpcap*)pktBuf)->len;
620  switch ((enum NtDynamicDescriptorFormat_e)((NtDynDescr_t*)descr)->descrFormat) {
622  {
623  NtDyn1Descr_t *pDyn1 = (NtDyn1Descr_t*)descr;
624  // Convert the ts.
625  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn1->timestamp/100000000U);
626  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn1->timestamp%100000000U)/100U);
627  // Copy the payload
628  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn1->descrLength, ((struct ntpcap*)pktBuf)->caplen);
629  // Write the packet to disk
630  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
631  break;
632  }
633 
635  {
636  NtDyn2Descr_t *pDyn2 = (NtDyn2Descr_t*)descr;
637  // Convert the ts.
638  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn2->timestamp/100000000U);
639  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn2->timestamp%100000000U)/100U);
640  // Copy the payload
641  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn2->descrLength, ((struct ntpcap*)pktBuf)->caplen);
642  // Write the packet to disk
643  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
644  break;
645  }
646 
648  {
649  NtDyn3Descr_t *pDyn3 = (NtDyn3Descr_t*)descr;
650  // Convert the ts.
651  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn3->timestamp/100000000U);
652  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn3->timestamp%100000000U)/100U);
653  // Copy the payload
654  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn3->descrLength, ((struct ntpcap*)pktBuf)->caplen);
655  // Write the packet to disk
656  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
657  break;
658  }
659 
661  {
662  NtDyn4Descr_t *pDyn4 = (NtDyn4Descr_t*)descr;
663  // Convert the ts.
664  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn4->timestamp/100000000U);
665  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn4->timestamp%100000000U)/100U);
666  // Copy the payload
667  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn4->descrLength, ((struct ntpcap*)pktBuf)->caplen);
668  // Write the packet to disk
669  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
670  break;
671  }
672  }
673  } else {
674  // Convert by only copying storedLength, wireLength and timestamp
675  ((struct ntpcap*)pktBuf)->len = ((struct NtStd0Descr_s *)descr)->wireLength-4U; // pcap wirelength is wo crc
676  ((struct ntpcap*)pktBuf)->caplen = (((struct NtStd0Descr_s *)descr)->storedLength + 16U - (((struct NtStd0Descr_s *)descr)->extensionLength * 8U));
677  // In pcap stored cannot be longer than wire
678  if (((struct ntpcap*)pktBuf)->caplen > ((struct ntpcap*)pktBuf)->len) {
679  ((struct ntpcap*)pktBuf)->caplen = ((struct ntpcap*)pktBuf)->len;
680  }
681  // Convert the ts.
682  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(((struct NtStd0Descr_s *)descr)->timestamp/100000000U);
683  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((((struct NtStd0Descr_s *)descr)->timestamp%100000000U)/100U);
684  // Copy the payload
685  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+(((struct NtStd0Descr_s *)descr)->extensionLength<<3)+16, ((struct ntpcap*)pktBuf)->caplen);
686  // Write the packet to disk
687  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
688  }
689  break;
690 
691  default:
692  fprintf(stderr, "Unhandled input format.\n");
693  appRunning = 0;
694  Result = 2;
695  goto _done;
696  }
697  break;
698 
700  switch (input_format) {
701  case INPUT_FORMAT_PCAP:
702  // Only convert timestamp
704  if (pcap_swapped == 1) {
705  // PCAP native swapped format. Must be swapped before saving
706  memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen));
707  ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen);
708  ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len);
709  ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec);
710  ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec)*1000;
711  fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof);
712  }
713  else {
714  // PCAP native format. No convert. Just copy the packet
715  memcpy(pktBuf, descr, 16U+((NtStd0Descr_t *)descr)->storedLength);
716  ((struct nttimeval*)pktBuf)->tv_usec = (((struct nttimeval*)pktBuf)->tv_usec*1000);
717  fwrite(pktBuf, 16U+((NtStd0Descr_t *)descr)->storedLength, 1, hof);
718  }
719  } else {
720  // PCAP format is Napatech PCAP. Remove Padding and CRC.
721  if (((NtStd0Descr_t *)descr)->storedLength >= ((NtStd0Descr_t *)descr)->wireLength) {
722  memcpy(pktBuf, descr, 16U+((NtStd0Descr_t *)descr)->storedLength);
723  ((struct NtStd0Descr_s *)pktBuf)->wireLength = (unsigned short)(((struct NtStd0Descr_s *)pktBuf)->wireLength - 4);
724  ((struct NtStd0Descr_s *)pktBuf)->storedLength = ((struct NtStd0Descr_s *)pktBuf)->wireLength;
725  ((struct nttimeval*)pktBuf)->tv_usec = (((struct nttimeval*)pktBuf)->tv_usec*1000);
726  fwrite(pktBuf, 16U+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof);
727  }
728  else {
729  memcpy(pktBuf, descr, 16U+((NtStd0Descr_t *)descr)->storedLength);
730  ((struct nttimeval*)pktBuf)->tv_usec = (((struct nttimeval*)pktBuf)->tv_usec*1000);
731  fwrite(pktBuf, 16U+((NtStd0Descr_t *)descr)->storedLength, 1, hof);
732  }
733  }
734  break;
735 
738  if (pcap_swapped == 1) {
739  // PCAP native swapped format. Must be swapped before saving
740  memcpy(pktBuf, descr, 16+ntohl(((struct ntpcap *)descr)->caplen));
741  ((struct ntpcap *)pktBuf)->caplen = ntohl(((struct ntpcap *)pktBuf)->caplen);
742  ((struct ntpcap *)pktBuf)->len = ntohl(((struct ntpcap *)pktBuf)->len);
743  ((struct ntpcap *)pktBuf)->tv.tv_sec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_sec);
744  ((struct ntpcap *)pktBuf)->tv.tv_usec = ntohl(((struct ntpcap *)pktBuf)->tv.tv_usec);
745  fwrite(pktBuf, 16+((struct ntpcap *)pktBuf)->caplen, 1, hof);
746  }
747  else {
748  // PCAP native format. No convert. Just copy the packet
749  fwrite(descr, 16U+((NtStd0Descr_t *)descr)->storedLength, 1, hof);
750  }
751  } else {
752  // PCAP format is Napatech PCAP. Remove Padding and CRC.
753  if (((NtStd0Descr_t *)descr)->storedLength >= ((NtStd0Descr_t *)descr)->wireLength) {
754  memcpy(pktBuf, descr, 16U+((NtStd0Descr_t *)descr)->storedLength);
755  ((struct NtStd0Descr_s *)pktBuf)->wireLength = (unsigned short)(((struct NtStd0Descr_s *)pktBuf)->wireLength - 4);
756  ((struct NtStd0Descr_s *)pktBuf)->storedLength = ((struct NtStd0Descr_s *)pktBuf)->wireLength;
757  fwrite(pktBuf, 16U+((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof);
758  }
759  else {
760  fwrite(descr, 16U+((NtStd0Descr_t *)descr)->storedLength, 1, hof);
761  }
762  }
763  break;
764 
766  case INPUT_FORMAT_2GD:
767  case INPUT_FORMAT_3GD:
768  if (((NtDynDescr_t*)descr)->ntDynDescr) {
769  NtDynDescr_t *pDyn = (NtDynDescr_t*)descr;
770  // Convert by only copying storedLength, wireLength and timestamp
771  ((struct ntpcap*)pktBuf)->len = (uint32_t)(pDyn->capLength - pDyn->descrLength - 4); // pcap wirelength is wo crc
772  ((struct ntpcap*)pktBuf)->caplen = (uint32_t)((struct ntpcap*)pktBuf)->len;
773 
774  switch ((enum NtDynamicDescriptorFormat_e)((NtDynDescr_t*)descr)->descrFormat) {
776  {
777  NtDyn1Descr_t *pDyn1 = (NtDyn1Descr_t*)descr;
778  // Convert the ts.
779  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)((pDyn1->timestamp/100000000U));
780  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn1->timestamp%100000000U)*10U);
781  // Copy the payload
782  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn1->descrLength, ((struct ntpcap*)pktBuf)->caplen);
783  // Write the packet to disk
784  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
785  break;
786  }
787 
789  {
790  NtDyn2Descr_t *pDyn2 = (NtDyn2Descr_t*)descr;
791  // Convert the ts.
792  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn2->timestamp/100000000U);
793  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn2->timestamp%100000000U)*10U);
794  // Copy the payload
795  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn2->descrLength, ((struct ntpcap*)pktBuf)->caplen);
796  // Write the packet to disk
797  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
798  break;
799  }
800 
802  {
803  NtDyn3Descr_t *pDyn3 = (NtDyn3Descr_t*)descr;
804  // Convert the ts.
805  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn3->timestamp/100000000U);
806  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn3->timestamp%100000000U)*10U);
807  // Copy the payload
808  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn3->descrLength, ((struct ntpcap*)pktBuf)->caplen);
809  // Write the packet to disk
810  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
811  break;
812  }
813 
815  {
816  NtDyn4Descr_t *pDyn4 = (NtDyn4Descr_t*)descr;
817  // Convert the ts.
818  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(pDyn4->timestamp/100000000U);
819  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((pDyn4->timestamp%100000000U)*10U);
820  // Copy the payload
821  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+pDyn4->descrLength, ((struct ntpcap*)pktBuf)->caplen);
822  // Write the packet to disk
823  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
824  break;
825  }
826  }
827  } else {
828  // Convert by only copying storedLength, wireLength and timestamp
829  ((struct ntpcap*)pktBuf)->len = ((NtStd0Descr_t *)descr)->wireLength-(uint32_t)4; // pcap wirelength is wo crc
830  ((struct ntpcap*)pktBuf)->caplen = (uint32_t)(((NtStd0Descr_t *)descr)->storedLength-(((NtStd0Descr_t *)descr)->extensionLength<<3)-16);
831  // In pcap stored cannot be longer than wire
832  if (((struct ntpcap*)pktBuf)->caplen > ((struct ntpcap*)pktBuf)->len) {
833  ((struct ntpcap*)pktBuf)->caplen = ((struct ntpcap*)pktBuf)->len;
834  }
835  // Convert the ts.
836  if (nanotime) {
837  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(((NtStd0Descr_t *)descr)->timestamp/1000000000U);
838  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)(((NtStd0Descr_t *)descr)->timestamp%1000000000U);
839  } else {
840  ((struct ntpcap*)pktBuf)->tv.tv_sec = (uint32_t)(((NtStd0Descr_t *)descr)->timestamp/100000000U);
841  ((struct ntpcap*)pktBuf)->tv.tv_usec = (uint32_t)((((NtStd0Descr_t *)descr)->timestamp%100000000U)*10U);
842  }
843  // Copy the payload. Payload (packet data) will immediately follow the packet header (header size is 4*32-bit words (16 bytes))
844  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+(((NtStd0Descr_t *)descr)->extensionLength<<3)+16, ((struct ntpcap*)pktBuf)->caplen);
845  // Write the packet to disk
846  fwrite(pktBuf, 16+((struct ntpcap*)pktBuf)->caplen, 1, hof);
847  }
848  break;
849 
850  default:
851  fprintf(stderr, "Unhandled input format.\n");
852  appRunning = 0;
853  Result = 2;
854  goto _done;
855  }
856  break;
857 
859  case OUTPUT_FORMAT_NT3GD:
860  switch (input_format) {
862  case INPUT_FORMAT_PCAP:
863  // Clear the packet descriptor
864  *((uint64_t*)pktBuf+0)=0;
865  *((uint64_t*)pktBuf+1)=0;
866  // Convert timestamp
867  if (pcap_swapped == 1) {
868  if (nanotime) {
869  if (nt3gdnano) { //Going from a 1ns PCAP to a 1ns NT3gd
870  ((struct NtStd0Descr_s *)pktBuf)->timestamp = (((uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_sec))*1000000000)+(uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_usec);
871  } else { //Going from a 1ns PCAP to a 10ns NT3gd
872  ((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));
873  }
874  } else {
875  if (nt3gdnano) { //Going from a 1us PCAP to a 1ns NT3gd
876  ((struct NtStd0Descr_s *)pktBuf)->timestamp = (((uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_sec))*1000000000)+(uint64_t)ntohl(((struct ntpcap*)descr)->tv.tv_usec)*1000;
877  } else { //Going from a 1us PCAP to a 10ns NT3gd
878  ((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));
879  }
880  }
881  } else {
882  if (nanotime) {
883  if (nt3gdnano) { //Going from a 1ns PCAP to a 1ns NT3gd
884  ((struct NtStd0Descr_s *)pktBuf)->timestamp = (((uint64_t)((struct ntpcap*)descr)->tv.tv_sec)*1000000000)+
885  (((uint64_t)((struct ntpcap*)descr)->tv.tv_usec));
886  } else {
887  ((struct NtStd0Descr_s *)pktBuf)->timestamp = ((((uint64_t)((struct ntpcap*)descr)->tv.tv_sec)*100000000)+
888  (((uint64_t)((struct ntpcap*)descr)->tv.tv_usec)/10));
889  }
890  } else {
891  if (nt3gdnano) { //Going from a 1us PCAP to a 1ns NT3gd
892  ((struct NtStd0Descr_s *)pktBuf)->timestamp = ((((uint64_t)((struct ntpcap*)descr)->tv.tv_sec)*1000000000)+
893  (((uint64_t)((struct ntpcap*)descr)->tv.tv_usec)*1000));
894  } else {
895  ((struct NtStd0Descr_s *)pktBuf)->timestamp = ((((uint64_t)((struct ntpcap*)descr)->tv.tv_sec)*100000000)+
896  (((uint64_t)((struct ntpcap*)descr)->tv.tv_usec)*100));
897  }
898  }
899  }
900  ((struct NtStd0Descr_s *)pktBuf)->descriptorType=1; // Mark NT descriptor
902  // PCAP native format.
903  uint32_t caplen;
904  uint32_t len;
905 
906  if (pcap_swapped == 1) {
907  caplen = ntohl(((struct ntpcap*)descr)->caplen);
908  len = ntohl(((struct ntpcap*)descr)->len);
909  }
910  else {
911  caplen = ((struct ntpcap*)descr)->caplen;
912  len = ((struct ntpcap*)descr)->len;
913  }
914 
915  if (len > caplen) {
916  // Sliced packet
917  ((struct NtStd0Descr_s *)pktBuf)->frameSliced=1;
918  ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)((caplen+16U+7U)&~7U);
919  } else if (len < caplen) {
920  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,
921  caplen,
922  len);
923  fprintf(stderr, "This could be a Napatech capture file with PCAP headers.\n");
924  (void)fprintf(stderr, "Try to run the tool again with --inputformat=ntpcap.\n");
925  appRunning = 0;
926  Result = 9;
927  goto _done;
928  } else {
929  // Remember 4byte crc
930  ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)((caplen+16U+4U+7U)&~7U);
931  }
932  if (len > 10000) {
933  // Hard sliced packet
934  ((struct NtStd0Descr_s *)pktBuf)->hardSlice=1;
935  ((struct NtStd0Descr_s *)pktBuf)->storedLength=((10000U+sizeof(struct NtStd0Descr_s)+7U)&~7U); // StoredLength must be 8byte aligned
936  }
937  ((struct NtStd0Descr_s *)pktBuf)->wireLength=(uint16_t)(len+4); // NT format is with checksum but we need to ask the HW to recalc it
938  ((struct NtStd0Descr_s *)pktBuf)->txCrcOverride=1;
939 
940  // Copy payload
941  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+16, caplen);
942  } else {
943  // PCAP format is Napatech PCAP. Padding and CRC is already done in the file.
944  if (((struct ntpcap*)descr)->len > ((struct ntpcap*)descr)->caplen) {
945  // Sliced packet
946  ((struct NtStd0Descr_s *)pktBuf)->frameSliced=1;
947  ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)(((struct ntpcap*)descr)->caplen+16U);
948  } else {
949  // The 4 byte crc is already included. Remove padding if exist and add them again.
950  ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)((((struct ntpcap*)descr)->len+16U+7U)&~7U);
951  }
952  if (((struct ntpcap*)descr)->len > 10000) {
953  // Hard sliced packet
954  ((struct NtStd0Descr_s *)pktBuf)->hardSlice=1;
955  ((struct NtStd0Descr_s *)pktBuf)->storedLength=(uint16_t)((10000U+sizeof(struct NtStd0Descr_s)+7U)&~7U); // StoredLength must be 8byte aligned
956  }
957  ((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
958  ((struct NtStd0Descr_s *)pktBuf)->txCrcOverride=1;
959 
960  // Copy payload
961  memcpy((uint8_t*)pktBuf+16, (uint8_t*)descr+16, ((struct ntpcap*)descr)->caplen);
962  }
963  fwrite(pktBuf, ((struct NtStd0Descr_s *)pktBuf)->storedLength, 1, hof);
964  break;
965  case INPUT_FORMAT_2GD:
966  case INPUT_FORMAT_3GD:
967  // No convert. Just copy the packet
968  if (((NtDynDescr_t*)descr)->ntDynDescr) {
969  fwrite(descr, ((NtDynDescr_t *)descr)->capLength, 1, hof);
970  } else {
971  fwrite(descr, ((NtStd0Descr_t *)descr)->storedLength, 1, hof);
972  }
973  break;
974  default:
975  fprintf(stderr, "Unhandled input format.\n");
976  appRunning = 0;
977  Result = 2;
978  goto _done;
979  }
980  break;
981  default:
982  fprintf(stderr, "Unhandled output format.\n");
983  appRunning = 0;
984  Result = 2;
985  goto _done;
986  }
987  // Next packet
988  _NEXT_PACKET:
989  offset += storedLength;
990  pktNum++;
991  }
992 
993  if (opt_verbose) {
994  printf("File size: 0x%lX (%ld) offset: 0x%lX (%ld)\n", dSize, dSize, offset, offset);
995  }
996 
997  if (!pktSkipNum)
998  (void)printf("Conversion done. Converted %llu packets.\n", pktNum);
999  else
1000  (void)printf("Conversion done. Converted %llu and skipped %llu packets.\n",
1002 
1003 _done:
1004  // Unmap the input file
1005  if (pin) {
1006  munmap(pin, fSize);
1007  }
1008  // Close input file
1009  if (fdin != -1) {
1010  close(fdin);
1011  }
1012  // Close output file
1013  if (hof) {
1014  fclose(hof);
1015  }
1016  /* Release heap memory */
1017  free(pktBuf);
1018 
1019  return Result;
1020 }
1021 
1022 //
1023 // main
1024 //
1025 int main(int argc, const char *argv[])
1026 {
1027  int ApplExitCode;
1028  struct argparse argparse;
1029 
1031 
1032  argparse_init(&argparse, arg_options, usageText, 0);
1033  argparse_parse(&argparse, argc, argv);
1034  if (opt_output_format != NULL) {
1035  if (strstr(opt_output_format, "pcapnano")) {
1037  } else if (strstr(opt_output_format, "pcap")) {
1039  } else if (strstr(opt_output_format, "nt3gdnano")) {
1041  } else if (strstr(opt_output_format, "nt3gd")) {
1043  } else {
1044  fprintf(stderr, "Unknown output format: %s\n", opt_output_format);
1045  return 2;
1046  }
1047  }
1048 
1049  if (opt_input_format != NULL) {
1050  if (strstr(opt_input_format, "libpcap")) {
1052  } else if (strstr(opt_input_format, "ntpcap")) {
1054  } else {
1055  fprintf(stderr, "Unknown input format: %s\n", opt_input_format);
1056  return 2;
1057  }
1058  }
1059 
1060  if (opt_outputformat==0) {
1061  fprintf(stderr, "No output format provided.\n");
1062  return 4;
1063  }
1064  if (opt_input_file==NULL) {
1065  fprintf(stderr, "No input file provided.\n");
1066  return 4;
1067  }
1068 
1069  if (opt_output_file==NULL) {
1070  fprintf(stderr, "No output file provided.\n");
1071  return 4;
1072  }
1073 
1074  // Register ctrl+c handler so we are able to stop again
1075 #if defined(WIN32) || defined (WIN64)
1076  SetConsoleCtrlHandler((PHANDLER_ROUTINE)StopApplication, TRUE);
1077 #else
1078  struct sigaction newaction; // Ctrl+c signal handler container
1079  memset(&newaction, 0, sizeof(newaction));
1080  newaction.sa_handler = StopApplication;
1081  if (sigaction(SIGINT, &newaction, NULL) < 0) {
1082  fprintf(stderr, "Failed to register SIGINT sigaction.\n");
1083  exit(EXIT_FAILURE);
1084  }
1085 #endif
1086 
1087  if ((ApplExitCode = _Convert()) != 0) {
1088  fprintf(stderr, ">>> Error: Convert failed.\n");
1089  }
1090 
1092 
1093  return ApplExitCode;
1094 }
1095 
1096 //
1097 // EOF
1098 //