capfileconvert_example.c Source File

Reference Documentation

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