Use *, not *.*, as the wildcard pattern on UN*X.
[metze/wireshark/wip.git] / text2pcap.c
index 77310326cea996243dd32939e43712ad8aaf4795..bc958cbb4fe15c4aa538d35b8c2196407f5c516c 100644 (file)
@@ -75,7 +75,7 @@
  * snaplength is automatically set to 64KiB-1.
  */
 
-#include "config.h"
+#include <config.h>
 
 /*
  * Just make sure we include the prototype for strptime as well
 #  define __EXTENSIONS__
 #endif
 
-#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wsutil/file_util.h>
+#include <wsutil/crash_info.h>
+#include <wsutil/ws_diag_control.h>
+#include <wsutil/ws_version_info.h>
+#include <wsutil/inet_addr.h>
 
 #include <time.h>
 #include <glib.h>
 
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
 #endif
 
 #include <errno.h>
 #include <assert.h>
 
-#ifndef HAVE_GETOPT
+#ifdef HAVE_LIBZ
+#include <zlib.h>      /* to get the libz version number */
+#endif
+
+#ifndef HAVE_GETOPT_LONG
 #include "wsutil/wsgetopt.h"
 #endif
 
-#ifdef NEED_STRPTIME_H
+#ifndef HAVE_STRPTIME
 # include "wsutil/strptime.h"
 #endif
 
 #include "pcapio.h"
 #include "text2pcap.h"
-#include "version.h"
 
 #ifdef _WIN32
 #include <wsutil/unicode-utils.h>
 #endif /* _WIN32 */
 
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>       /* needed to define AF_ values on Windows */
-#endif
-
-#ifndef HAVE_INET_ATON_H
-# include "wsutil/inet_aton.h"
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef NEED_INET_V6DEFS_H
-# include "wsutil/inet_v6defs.h"
-#endif
-
 /*--- Options --------------------------------------------------------------------*/
 
 /* File format */
@@ -181,9 +167,9 @@ static long hdr_ip_proto = 0;
 /* Destination and source addresses for IP header */
 static guint32 hdr_ip_dest_addr = 0;
 static guint32 hdr_ip_src_addr = 0;
-static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-static guint8 hdr_ipv6_src_addr[16]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-static guint8 NO_IPv6_ADDRESS[16]    = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static struct e_in6_addr hdr_ipv6_dest_addr = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+static struct e_in6_addr hdr_ipv6_src_addr  = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+static struct e_in6_addr NO_IPv6_ADDRESS    = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
 
 /* Dummy UDP header */
 static int     hdr_udp       = FALSE;
@@ -243,7 +229,7 @@ static guint64 bytes_written       = 0;
 
 /* Time code of packet, derived from packet_preamble */
 static time_t   ts_sec  = 0;
-static guint32  ts_usec = 0;
+static guint32  ts_nsec = 0;
 static char    *ts_fmt  = NULL;
 static struct tm timecode_default;
 
@@ -343,17 +329,6 @@ static struct {         /* pseudo header for checksum calculation */
 
 /* headers taken from glibc */
 
-/* IPv6 address */
-struct hdr_in6_addr
-{
-    union
-    {
-       guint8  __u6_addr8[16];
-       guint16 __u6_addr16[8];
-       guint32 __u6_addr32[4];
-    } __in6_u;
-};
-
 typedef struct {
     union  {
         struct ip6_hdrctl {
@@ -364,15 +339,15 @@ typedef struct {
         } ip6_un1;
         guint8 ip6_un2_vfc;       /* 4 bits version, 4 bits priority */
     } ip6_ctlun;
-    struct hdr_in6_addr ip6_src;      /* source address */
-    struct hdr_in6_addr ip6_dst;      /* destination address */
+    struct e_in6_addr ip6_src;      /* source address */
+    struct e_in6_addr ip6_dst;      /* destination address */
 } hdr_ipv6_t;
 
 static hdr_ipv6_t HDR_IPv6;
 
 static struct {                 /* pseudo header ipv6 for checksum calculation */
-    struct  hdr_in6_addr src_addr6;
-    struct  hdr_in6_addr dst_addr6;
+    struct  e_in6_addr src_addr6;
+    struct  e_in6_addr dst_addr6;
     guint32 protocol;
     guint32 zero;
 } pseudoh6;
@@ -427,28 +402,8 @@ static char tempbuf[64];
 /*----------------------------------------------------------------------
  * Stuff for writing a PCap file
  */
-#define PCAP_MAGIC          0xa1b2c3d4
 #define PCAP_SNAPLEN        0xffff
 
-/* "libpcap" file header (minus magic number). */
-struct pcap_hdr {
-    guint32 magic;          /* magic */
-    guint16 version_major;  /* major version number */
-    guint16 version_minor;  /* minor version number */
-    guint32 thiszone;       /* GMT to local correction */
-    guint32 sigfigs;        /* accuracy of timestamps */
-    guint32 snaplen;        /* max length of captured packets, in octets */
-    guint32 network;        /* data link type */
-};
-
-/* "libpcap" record header. */
-struct pcaprec_hdr {
-    guint32 ts_sec;         /* timestamp seconds */
-    guint32 ts_usec;        /* timestamp microseconds */
-    guint32 incl_len;       /* number of octets of packet saved in file */
-    guint32 orig_len;       /* actual length of packet */
-};
-
 /* Link-layer type; see http://www.tcpdump.org/linktypes.html for details */
 static guint32 pcap_link_type = 1;   /* Default is LINKTYPE_ETHERNET */
 
@@ -463,6 +418,11 @@ parse_num (const char *str, int offset)
     guint32  num;
     char    *c;
 
+    if (str == NULL) {
+        fprintf(stderr, "FATAL ERROR: str is NULL\n");
+        exit(1);
+    }
+
     num = (guint32)strtoul(str, &c, offset ? offset_base : 16);
     if (c == str) {
         fprintf(stderr, "FATAL ERROR: Bad hex number? [%s]\n", str);
@@ -617,22 +577,22 @@ static guint32
 crc32c (const guint8* buf, unsigned int len, guint32 crc32_init)
 {
     unsigned int i;
-    guint32 crc32;
+    guint32 crc;
 
-    crc32 = crc32_init;
+    crc = crc32_init;
     for (i = 0; i < len; i++)
-        CRC32C(crc32, buf[i]);
+        CRC32C(crc, buf[i]);
 
-    return crc32;
+    return crc;
 }
 
 static guint32
-finalize_crc32c (guint32 crc32)
+finalize_crc32c (guint32 crc)
 {
     guint32 result;
     guint8 byte0,byte1,byte2,byte3;
 
-    result = ~crc32;
+    result = ~crc;
     byte0 = result & 0xff;
     byte1 = (result>>8) & 0xff;
     byte2 = (result>>16) & 0xff;
@@ -711,10 +671,10 @@ write_current_packet (gboolean cont)
             HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
             write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
         } else if (hdr_ipv6) {
-            if (memcmp(isInbound ? hdr_ipv6_dest_addr : hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
-                memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
-            if (memcmp(isInbound ? hdr_ipv6_src_addr : hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
-                memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
+            if (memcmp(isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, &NO_IPv6_ADDRESS, sizeof(struct e_in6_addr)))
+                memcpy(&HDR_IPv6.ip6_src, isInbound ? &hdr_ipv6_dest_addr : &hdr_ipv6_src_addr, sizeof(struct e_in6_addr));
+            if (memcmp(isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, &NO_IPv6_ADDRESS, sizeof(struct e_in6_addr)))
+                memcpy(&HDR_IPv6.ip6_dst, isInbound ? &hdr_ipv6_src_addr : &hdr_ipv6_dest_addr, sizeof(struct e_in6_addr));
 
             HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
             HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
@@ -881,15 +841,15 @@ write_current_packet (gboolean cont)
         if (use_pcapng) {
             success = pcapng_write_enhanced_packet_block(output_file,
                                                          NULL,
-                                                         ts_sec, ts_usec,
+                                                         ts_sec, ts_nsec,
                                                          length, length,
                                                          0,
-                                                         1000000,
+                                                         1000000000,
                                                          packet_buf, direction,
                                                          &bytes_written, &err);
         } else {
             success = libpcap_write_packet(output_file,
-                                           ts_sec, ts_usec,
+                                           ts_sec, ts_nsec/1000,
                                            length, length,
                                            packet_buf,
                                            &bytes_written, &err);
@@ -901,7 +861,10 @@ write_current_packet (gboolean cont)
         }
         if (ts_fmt == NULL) {
             /* fake packet counter */
-            ts_usec++;
+            if (use_pcapng)
+                ts_nsec++;
+            else
+                ts_nsec += 1000;
         }
         if (!quiet) {
             fprintf(stderr, "Wrote packet of %u bytes.\n", length);
@@ -924,22 +887,21 @@ write_file_header (void)
     gboolean success;
 
     if (use_pcapng) {
-#ifdef GITVERSION
-        const char *appname = "text2pcap (" GITVERSION " from " GITBRANCH ")";
-#else
-        const char *appname = "text2pcap";
-#endif
-        char comment[100];
+        char *appname;
+        char *comment;
 
-        g_snprintf(comment, sizeof(comment), "Generated from input file %s.", input_filename);
+        appname = g_strdup_printf("text2pcap (Wireshark) %s", get_ws_vcs_version_info());
+        comment = g_strdup_printf("Generated from input file %s.", input_filename);
         success = pcapng_write_session_header_block(output_file,
                                                     comment,
-                                                    NULL,
-                                                    NULL,
+                                                    NULL,    /* HW */
+                                                    NULL,    /* OS */
                                                     appname,
-                                                    -1,
+                                                    -1,      /* section_length */
                                                     &bytes_written,
                                                     &err);
+        g_free(appname);
+        g_free(comment);
         if (success) {
             success = pcapng_write_interface_description_block(output_file,
                                                                NULL,
@@ -951,46 +913,19 @@ write_file_header (void)
                                                                PCAP_SNAPLEN,
                                                                &bytes_written,
                                                                0,
-                                                               6,
+                                                               9,
                                                                &err);
         }
     } else {
-        success = libpcap_write_file_header(output_file, pcap_link_type, PCAP_SNAPLEN,
-                                            FALSE, &bytes_written, &err);
-    }
-    if (!success) {
-        fprintf(stderr, "File write error [%s] : %s\n",
-                output_filename, g_strerror(err));
-        exit(1);
-    }
-}
-
-static void
-write_file_trailer (void)
-{
-    int      err;
-    gboolean success;
-
-    if (use_pcapng) {
-        success = pcapng_write_interface_statistics_block(output_file,
-                                                          0,
-                                                          &bytes_written,
-                                                          "Counters provided by text2pcap",
-                                                          0,
-                                                          0,
-                                                          num_packets_written,
-                                                          num_packets_written - num_packets_written,
-                                                          &err);
-
-    } else {
-        success = TRUE;
+        success = libpcap_write_file_header(output_file, pcap_link_type,
+                                            PCAP_SNAPLEN, FALSE,
+                                            &bytes_written, &err);
     }
     if (!success) {
         fprintf(stderr, "File write error [%s] : %s\n",
                 output_filename, g_strerror(err));
         exit(1);
     }
-   return;
 }
 
 /*----------------------------------------------------------------------
@@ -1087,7 +1022,7 @@ parse_preamble (void)
      */
 
     timecode = timecode_default;
-    ts_usec = 0;
+    ts_nsec = 0;
 
     /* Ensure preamble has more than two chars before attempting to parse.
      * This should cover line breaks etc that get counted.
@@ -1115,34 +1050,34 @@ parse_preamble (void)
                     timecode.tm_hour, timecode.tm_min, timecode.tm_sec, timecode.tm_isdst);
             }
             ts_sec  = 0;  /* Jan 1,1970: 00:00 GMT; tshark/wireshark will display date/time as adjusted by timezone */
-            ts_usec = 0;
+            ts_nsec = 0;
         } else {
             /* Parse subseconds */
-            ts_usec = (guint32)strtol(subsecs, &p, 10);
+            ts_nsec = (guint32)strtol(subsecs, &p, 10);
             if (subsecs == p) {
                 /* Error */
-                ts_usec = 0;
+                ts_nsec = 0;
             } else {
                 /*
                  * Convert that number to a number
                  * of microseconds; if it's N digits
                  * long, it's in units of 10^(-N) seconds,
                  * so, to convert it to units of
-                 * 10^-6 seconds, we multiply by
-                 * 10^(6-N).
+                 * 10^-9 seconds, we multiply by
+                 * 10^(9-N).
                  */
                 subseclen = (int) (p - subsecs);
-                if (subseclen > 6) {
+                if (subseclen > 9) {
                     /*
-                     * *More* than 6 digits; 6-N is
+                     * *More* than 9 digits; 9-N is
                      * negative, so we divide by
-                     * 10^(N-6).
+                     * 10^(N-9).
                      */
-                    for (i = subseclen - 6; i != 0; i--)
-                        ts_usec /= 10;
-                } else if (subseclen < 6) {
-                    for (i = 6 - subseclen; i != 0; i--)
-                        ts_usec *= 10;
+                    for (i = subseclen - 9; i != 0; i--)
+                        ts_nsec /= 10;
+                } else if (subseclen < 9) {
+                    for (i = 9 - subseclen; i != 0; i--)
+                        ts_nsec *= 10;
                 }
             }
         }
@@ -1151,7 +1086,7 @@ parse_preamble (void)
         char *c;
         while ((c = strchr(packet_preamble, '\r')) != NULL) *c=' ';
         fprintf(stderr, "[[parse_preamble: \"%s\"]]\n", packet_preamble);
-        fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_usec);
+        fprintf(stderr, "Format(%s), time(%u), subsecs(%u)\n", ts_fmt, (guint32)ts_sec, ts_nsec);
     }
 
 
@@ -1284,9 +1219,10 @@ parse_token (token_t token, char *str)
                     write_current_packet(FALSE);
                     state = INIT;
                 }
-            } else
+            } else {
                 state = READ_OFFSET;
-                pkt_lnstart = packet_buf + num;
+            }
+            pkt_lnstart = packet_buf + num;
             break;
         case T_EOL:
             state = START_OF_LINE;
@@ -1354,7 +1290,7 @@ parse_token (token_t token, char *str)
                     tmp_str[1] = pkt_lnstart[i*3+1];
                     tmp_str[2] = '\0';
                     /* it is a valid convertable string */
-                    if (!isxdigit(tmp_str[0]) || !isxdigit(tmp_str[0])) {
+                    if (!g_ascii_isxdigit(tmp_str[0]) || !g_ascii_isxdigit(tmp_str[1])) {
                         break;
                     }
                     s2[i] = (char)strtoul(tmp_str, (char **)NULL, 16);
@@ -1419,25 +1355,9 @@ fail_null_str:
  * Print usage string and exit
  */
 static void
-usage (gboolean is_error)
+print_usage (FILE *output)
 {
-    FILE *output;
-
-    if (!is_error) {
-        output = stdout;
-    }
-    else {
-        output = stderr;
-    }
-
     fprintf(output,
-            "Text2pcap %s"
-#ifdef GITVERSION
-            " (" GITVERSION " from " GITBRANCH ")"
-#endif
-            "\n"
-            "Generate a capture file from an ASCII hexdump of packets.\n"
-            "See http://www.wireshark.org for more information.\n"
             "\n"
             "Usage: text2pcap [options] <infile> <outfile>\n"
             "\n"
@@ -1515,9 +1435,33 @@ usage (gboolean is_error)
             "  -q                     generate no output at all (automatically disables -d).\n"
             "  -n                     use PCAP-NG instead of PCAP as output format.\n"
             "",
-            VERSION, MAX_PACKET);
+            MAX_PACKET);
+}
+
+static void
+get_text2pcap_compiled_info(GString *str)
+{
+    /* LIBZ */
+    g_string_append(str, ", ");
+#ifdef HAVE_LIBZ
+    g_string_append(str, "with libz ");
+#ifdef ZLIB_VERSION
+    g_string_append(str, ZLIB_VERSION);
+#else /* ZLIB_VERSION */
+    g_string_append(str, "(version unknown)");
+#endif /* ZLIB_VERSION */
+#else /* HAVE_LIBZ */
+    g_string_append(str, "without libz");
+#endif /* HAVE_LIBZ */
+}
 
-    exit(is_error ? 1 : 0);
+static void
+get_text2pcap_runtime_info(GString *str)
+{
+    /* zlib */
+#if defined(HAVE_LIBZ) && !defined(_WIN32)
+    g_string_append_printf(str, ", with libz %s", zlibVersion());
+#endif
 }
 
 /*----------------------------------------------------------------------
@@ -1526,19 +1470,46 @@ usage (gboolean is_error)
 static void
 parse_options (int argc, char *argv[])
 {
+    GString *comp_info_str;
+    GString *runtime_info_str;
     int   c;
     char *p;
+    static const struct option long_options[] = {
+        {"help", no_argument, NULL, 'h'},
+        {"version", no_argument, NULL, 'v'},
+        {0, 0, 0, 0 }
+    };
 
 #ifdef _WIN32
     arg_list_utf_16to8(argc, argv);
     create_app_running_mutex();
 #endif /* _WIN32 */
 
+    /* Get the compile-time version information string */
+    comp_info_str = get_compiled_version_info(NULL, get_text2pcap_compiled_info);
+
+    /* get the run-time version information string */
+    runtime_info_str = get_runtime_version_info(get_text2pcap_runtime_info);
+
+    /* Add it to the information to be reported on a crash. */
+    ws_add_crash_info("Text2pcap (Wireshark) %s\n"
+         "\n"
+         "%s"
+         "\n"
+         "%s",
+      get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
+
     /* Scan CLI parameters */
-    while ((c = getopt(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:4:6:")) != -1) {
+    while ((c = getopt_long(argc, argv, "aDdhqe:i:l:m:no:u:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
         switch (c) {
-        case '?': usage(TRUE); break;
-        case 'h': usage(FALSE); break;
+        case 'h':
+            printf("Text2pcap (Wireshark) %s\n"
+                   "Generate a capture file from an ASCII hexdump of packets.\n"
+                   "See https://www.wireshark.org for more information.\n",
+                   get_ws_vcs_version_info());
+            print_usage(stdout);
+            exit(0);
+            break;
         case 'd': if (!quiet) debug++; break;
         case 'D': has_direction = TRUE; break;
         case 'q': quiet = TRUE; debug = FALSE; break;
@@ -1548,7 +1519,8 @@ parse_options (int argc, char *argv[])
         case 'o':
             if (optarg[0] != 'h' && optarg[0] != 'o' && optarg[0] != 'd') {
                 fprintf(stderr, "Bad argument for '-o': %s\n", optarg);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             switch (optarg[0]) {
             case 'o': offset_base =  8; break;
@@ -1560,7 +1532,8 @@ parse_options (int argc, char *argv[])
             hdr_ethernet = TRUE;
             if (sscanf(optarg, "%x", &hdr_ethernet_proto) < 1) {
                 fprintf(stderr, "Bad argument for '-e': %s\n", optarg);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             break;
 
@@ -1570,7 +1543,8 @@ parse_options (int argc, char *argv[])
             if (p == optarg || *p != '\0' || hdr_ip_proto < 0 ||
                   hdr_ip_proto > 255) {
                 fprintf(stderr, "Bad argument for '-i': %s\n", optarg);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             hdr_ethernet = TRUE;
             hdr_ethernet_proto = 0x800;
@@ -1584,29 +1558,34 @@ parse_options (int argc, char *argv[])
             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || (*p != ',' && *p != '\0')) {
                 fprintf(stderr, "Bad src port for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             if (*p == '\0') {
                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             p++;
             optarg = p;
             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || (*p != ',' && *p != '\0')) {
                 fprintf(stderr, "Bad dest port for '-s'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             if (*p == '\0') {
                 fprintf(stderr, "No tag specified for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             p++;
             optarg = p;
             hdr_sctp_tag = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || *p != '\0') {
                 fprintf(stderr, "Bad tag for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
 
             hdr_ip = TRUE;
@@ -1622,29 +1601,34 @@ parse_options (int argc, char *argv[])
             hdr_sctp_src   = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || (*p != ',' && *p != '\0')) {
                 fprintf(stderr, "Bad src port for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             if (*p == '\0') {
                 fprintf(stderr, "No dest port specified for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             p++;
             optarg = p;
             hdr_sctp_dest = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || (*p != ',' && *p != '\0')) {
                 fprintf(stderr, "Bad dest port for '-s'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             if (*p == '\0') {
                 fprintf(stderr, "No ppi specified for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             p++;
             optarg = p;
             hdr_data_chunk_ppid = (guint32)strtoul(optarg, &p, 10);
             if (p == optarg || *p != '\0') {
                 fprintf(stderr, "Bad ppi for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
 
             hdr_ip = TRUE;
@@ -1665,18 +1649,21 @@ parse_options (int argc, char *argv[])
             hdr_src_port = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || (*p != ',' && *p != '\0')) {
                 fprintf(stderr, "Bad src port for '-u'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             if (*p == '\0') {
                 fprintf(stderr, "No dest port specified for '-u'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             p++;
             optarg = p;
             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || *p != '\0') {
                 fprintf(stderr, "Bad dest port for '-u'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             hdr_ip = TRUE;
             hdr_ip_proto = 17;
@@ -1692,18 +1679,21 @@ parse_options (int argc, char *argv[])
             hdr_src_port = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || (*p != ',' && *p != '\0')) {
                 fprintf(stderr, "Bad src port for '-T'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             if (*p == '\0') {
                 fprintf(stderr, "No dest port specified for '-u'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             p++;
             optarg = p;
             hdr_dest_port = (guint32)strtol(optarg, &p, 10);
             if (p == optarg || *p != '\0') {
                 fprintf(stderr, "Bad dest port for '-T'\n");
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
             hdr_ip = TRUE;
             hdr_ip_proto = 6;
@@ -1715,13 +1705,21 @@ parse_options (int argc, char *argv[])
             identify_ascii = TRUE;
             break;
 
+        case 'v':
+            show_version("Text2pcap (Wireshark)", comp_info_str, runtime_info_str);
+            g_string_free(comp_info_str, TRUE);
+            g_string_free(runtime_info_str, TRUE);
+            exit(0);
+            break;
+
         case '4':
         case '6':
             p = strchr(optarg, ',');
 
             if (!p) {
                 fprintf(stderr, "Bad source param addr for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
 
             *p = '\0';
@@ -1738,45 +1736,53 @@ parse_options (int argc, char *argv[])
             hdr_ethernet = TRUE;
 
             if (hdr_ipv6 == TRUE) {
-                if (inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
+                if (!ws_inet_pton6(optarg, &hdr_ipv6_src_addr)) {
                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
-                        usage(TRUE);
+                        print_usage(stderr);
+                        exit(1);
                 }
             } else {
-                if (inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
+                if (!ws_inet_pton4(optarg, &hdr_ip_src_addr)) {
                         fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
-                        usage(TRUE);
+                        print_usage(stderr);
+                        exit(1);
                 }
             }
 
             p++;
             if (*p == '\0') {
                 fprintf(stderr, "No dest addr specified for '-%c'\n", c);
-                usage(TRUE);
+                print_usage(stderr);
+                exit(1);
             }
 
             if (hdr_ipv6 == TRUE) {
-                if (inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
+                if (!ws_inet_pton6(p, &hdr_ipv6_dest_addr)) {
                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
-                        usage(TRUE);
+                        print_usage(stderr);
+                        exit(1);
                 }
             } else {
-                if (inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
+                if (!ws_inet_pton4(p, &hdr_ip_dest_addr)) {
                         fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
-                        usage(TRUE);
+                        print_usage(stderr);
+                        exit(1);
                 }
             }
             break;
 
 
+        case '?':
         default:
-            usage(TRUE);
+            print_usage(stderr);
+            exit(1);
         }
     }
 
     if (optind >= argc || argc-optind < 2) {
         fprintf(stderr, "Must specify input and output filename\n");
-        usage(TRUE);
+        print_usage(stderr);
+        exit(1);
     }
 
     if (strcmp(argv[optind], "-")) {
@@ -1841,7 +1847,7 @@ parse_options (int argc, char *argv[])
                              hdr_src_port, hdr_dest_port);
         if (hdr_sctp) fprintf(stderr, "Generate dummy SCTP header: Source port: %u. Dest port: %u. Tag: %u\n",
                               hdr_sctp_src, hdr_sctp_dest, hdr_sctp_tag);
-        if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %d. SSN: %d. PPID: %u\n",
+        if (hdr_data_chunk) fprintf(stderr, "Generate dummy DATA chunk header: TSN: %u. SID: %u. SSN: %u. PPID: %u\n",
                                     hdr_data_chunk_tsn, hdr_data_chunk_sid, hdr_data_chunk_ssn, hdr_data_chunk_ppid);
     }
 }
@@ -1885,7 +1891,6 @@ main(int argc, char *argv[])
     yylex();
 
     write_current_packet(FALSE);
-    write_file_trailer();
     fclose(input_file);
     fclose(output_file);
     if (debug)