Add initial pcapng name resolution record support. Wireshark has read
authorgerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 24 Mar 2011 22:47:57 +0000 (22:47 +0000)
committergerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 24 Mar 2011 22:47:57 +0000 (22:47 +0000)
support; TShark has read+write support. Additionally TShark can read a
"hosts" file and write those records to a capture file.

This uses "struct addrinfo" in many places and probably won't compile on
some platforms.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@36318 f5534014-38df-0310-8fa8-9805f1628bb7

13 files changed:
doc/editcap.pod
doc/tshark.pod
epan/addr_resolv.c
epan/addr_resolv.h
epan/libwireshark.def
file.c
tshark.c
wiretap/file_access.c
wiretap/pcapng.c
wiretap/wtap-int.h
wiretap/wtap.c
wiretap/wtap.def
wiretap/wtap.h

index bf699723b5199a9e0f0e429325dde4530859bed1..deea34ea7644db765fc0beacab99dcdd7f4bdadf 100644 (file)
@@ -10,6 +10,8 @@ S<[ B<-c> E<lt>packets per fileE<gt> ]>
 S<[ B<-C> E<lt>choplenE<gt> ]>
 S<[ B<-E> E<lt>error probabilityE<gt> ]>
 S<[ B<-F> E<lt>file formatE<gt> ]>
+S<[ B<-W> E<lt>file format optionE<gt>]>
+S<[ B<-H> E<lt>input hosts file<gt> ]>
 S<[ B<-A> E<lt>start timeE<gt> ]>
 S<[ B<-B> E<lt>stop timeE<gt> ]>
 S<[ B<-h> ]>
@@ -150,6 +152,30 @@ B<Editcap> can write the file in several formats, B<editcap -F>
 provides a list of the available output formats. The default
 is the B<libpcap> format.
 
+=item -W  E<lt>file format optionE<gt>
+
+Save extra information in the file if the format supports it. For
+example,
+
+  -F pcapng -W n
+
+will save host name resolution records along with captured packets.
+
+Future versions of Wireshark may automatically change the capture format to
+B<pcapng> as needed.
+
+The argument is a string that may contain the following letter:
+
+B<n> write network address resolution information (pcapng only)
+
+=item -H  E<lt>input "hosts" fileE<gt>
+
+Read a list of address to host name mappings and include the result in
+the output file. Implies B<-W n>.
+
+The input file format is described at
+L<http://en.wikipedia.org/wiki/Hosts_%28file%29>.
+
 =item -A  E<lt>start timeE<gt>
 
 Saves only the packets whose timestamp is on or after start time.
index 7d94e4e8afd18fe149299d099c055dbebb4145ba..8813cc43ca532590206bfd5618f61487ebd4b75f 100644 (file)
@@ -18,6 +18,7 @@ S<[ B<-E> E<lt>field print optionE<gt> ]>
 S<[ B<-f> E<lt>capture filterE<gt> ]>
 S<[ B<-F> E<lt>file formatE<gt> ]>
 S<[ B<-h> ]>
+S<[ B<-H> E<lt>input hosts fileE<gt> ]>
 S<[ B<-i> E<lt>capture interfaceE<gt>|- ]>
 S<[ B<-I> ]>
 S<[ B<-K> E<lt>keytabE<gt> ]>
@@ -37,6 +38,7 @@ S<[ B<-T> pdml|psml|ps|text|fields ]>
 S<[ B<-v> ]>
 S<[ B<-V> ]>
 S<[ B<-w> E<lt>outfileE<gt>|- ]>
+S<[ B<-W> E<lt>file format optionE<gt>]>
 S<[ B<-x> ]>
 S<[ B<-X> E<lt>eXtension optionE<gt>]>
 S<[ B<-y> E<lt>capture link typeE<gt> ]>
@@ -398,6 +400,14 @@ B<currentprefs>  Dumps a copy of the current preferences file to stdout.
 
 Print the version and options and exits.
 
+=item -H  E<lt>input hosts fileE<gt>
+
+Read a list of entries from a "hosts" file, which will then be written
+to a capture file. Implies B<-W n>.
+
+The "hosts" file format is documented at
+L<http://en.wikipedia.org/wiki/Hosts_(file)>.
+
 =item -i  E<lt>capture interfaceE<gt> | -
 
 Set the name of the network interface or pipe to use for live packet
@@ -617,6 +627,22 @@ NOTE: -w provides raw packet data, not text. If you want text output
 you need to redirect stdout (e.g. using '>'), don't use the B<-w>
 option for this.
 
+=item -W  E<lt>file format optionE<gt>
+
+Save extra information in the file if the format supports it. For
+example,
+
+  -F pcapng -W n
+
+will save host name resolution records along with captured packets.
+
+Future versions of Wireshark may automatically change the capture format to
+B<pcapng> as needed.
+
+The argument is a string that may contain the following letter:
+
+B<n> write network address resolution information (pcapng only)
+
 =item -x
 
 Cause B<TShark> to print a hex and ASCII dump of the packet data
index 05fb9bc4949bfd6eca0b9524fbc8e5dc39cb3f5b..89094a82fcc8d9675f0c0de5d76bd100d380351d 100644 (file)
 
 #define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
 
+/*
+ * XXX Some of this is duplicated in addrinfo_list. We may want to replace the
+ * addr and name parts with a struct addrinfo or create our own addrinfo-like
+ * struct that simply points to the data below.
+ */
 typedef struct hashipv4 {
   guint             addr;
   gboolean          is_dummy_entry; /* name is IPv4 address in dot format */
@@ -272,6 +277,9 @@ static int      ipxnet_resolution_initialized = 0;
 static int      service_resolution_initialized = 0;
 static gboolean new_resolved_objects = FALSE;
 
+static struct addrinfo *addrinfo_list = NULL; /* IPv4 and IPv6 */
+static struct addrinfo *addrinfo_list_last = NULL;
+
 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
 static void add_serv_port_cb(const guint32 port);
 
@@ -2015,7 +2023,7 @@ ipxnet_addr_lookup(const gchar *name, gboolean *success)
 
 } /* ipxnet_addr_lookup */
 
-static gboolean
+gboolean
 read_hosts_file (const char *hostspath)
 {
   FILE *hf;
@@ -2065,6 +2073,7 @@ read_hosts_file (const char *hostspath)
 
     /*
      * Add the aliases, too, if there are any.
+     * XXX - host_lookup() only returns the first entry.
      */
     while ((cp = strtok(NULL, " \t")) != NULL) {
       if (is_ipv6) {
@@ -2112,6 +2121,10 @@ add_ip_name_from_string (const char *addr, const char *name)
   return TRUE;
 } /* add_ip_name_from_string */
 
+struct addrinfo *
+get_addrinfo_list(void) {
+  return addrinfo_list;
+}
 
 /* Read in a list of subnet definition - name pairs.
  * <line> = <comment> | <entry> | <whitespace>
@@ -2359,6 +2372,7 @@ subnet_name_lookup_init(void)
   g_free(subnetspath);
 }
 
+
 /*
  *  External Functions
  */
@@ -2366,6 +2380,7 @@ subnet_name_lookup_init(void)
 void
 host_name_lookup_init(void) {
   char *hostspath;
+  struct addrinfo *ai;
 
 #ifdef HAVE_GNU_ADNS
 #ifdef _WIN32
@@ -2375,6 +2390,11 @@ host_name_lookup_init(void) {
 #endif /* _WIN32 */
 #endif /*GNU_ADNS */
 
+  if (!addrinfo_list) {
+    ai = g_malloc0(sizeof(struct addrinfo));
+    addrinfo_list = addrinfo_list_last = ai;
+  }
+
   /*
    * Load the user's hosts file, if they have one.
    */
@@ -2392,7 +2412,7 @@ host_name_lookup_init(void) {
     report_open_failure(hostspath, errno, FALSE);
   }
   g_free(hostspath);
-
+  
 #ifdef HAVE_C_ARES
 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
   if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
@@ -2646,6 +2666,8 @@ add_ipv4_name(const guint addr, const gchar *name)
 {
   int hash_idx;
   hashipv4_t *tp;
+  struct addrinfo *ai;
+  struct sockaddr_in *sa4;
 
   hash_idx = HASH_IPV4_ADDRESS(addr);
 
@@ -2675,6 +2697,25 @@ add_ipv4_name(const guint addr, const gchar *name)
   g_strlcpy(tp->name, name, MAXNAMELEN);
   tp->resolve = TRUE;
   new_resolved_objects = TRUE;
+
+  if (!addrinfo_list) {
+    ai = g_malloc0(sizeof(struct addrinfo));
+    addrinfo_list = addrinfo_list_last = ai;
+  }
+  sa4 = g_malloc0(sizeof(struct sockaddr_in));
+  sa4->sin_family = AF_INET;
+  sa4->sin_addr.s_addr = addr;
+
+  ai = g_malloc0(sizeof(struct addrinfo));
+  ai->ai_family = AF_INET;
+  ai->ai_addrlen = sizeof(struct sockaddr_in);
+  ai->ai_canonname = (char *) tp->name;
+  ai->ai_addr = (struct sockaddr*) sa4;
+  
+  addrinfo_list_last->ai_next = ai;
+  addrinfo_list_last = ai;
+
 } /* add_ipv4_name */
 
 /* -------------------------- */
@@ -2683,6 +2724,8 @@ add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
 {
   int hash_idx;
   hashipv6_t *tp;
+  struct addrinfo *ai;
+  struct sockaddr_in6 *sa6;
 
   hash_idx = HASH_IPV6_ADDRESS(*addrp);
 
@@ -2709,11 +2752,28 @@ add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
       tp = tp->next;
     }
   }
-
   g_strlcpy(tp->name, name, MAXNAMELEN);
   tp->resolve = TRUE;
   new_resolved_objects = TRUE;
 
+  if (!addrinfo_list) {
+    ai = g_malloc0(sizeof(struct addrinfo));
+    addrinfo_list = addrinfo_list_last = ai;
+  }
+
+  sa6 = g_malloc0(sizeof(struct sockaddr_in6));
+  sa6->sin6_family = AF_INET;
+  memcpy(sa6->sin6_addr.s6_addr, addrp, 16);
+
+  ai = g_malloc0(sizeof(struct addrinfo));
+  ai->ai_family = AF_INET6;
+  ai->ai_addrlen = sizeof(struct sockaddr_in);
+  ai->ai_canonname = (char *) tp->name;
+  ai->ai_addr = (struct sockaddr *) sa6;
+
+  addrinfo_list_last->ai_next = ai;
+  addrinfo_list_last = ai;
+
 } /* add_ipv6_name */
 
 /* -----------------
index 79b424232a4bf8b82ab227a413f7c2d6406cfcf2..76fb481d7ed2b66947e2a184c74b8f5235992585 100644 (file)
@@ -176,9 +176,40 @@ extern void add_ipv4_name(const guint addr, const gchar *name);
 /* adds a hostname/IPv6 in the hash table */
 extern void add_ipv6_name(const struct e_in6_addr *addr, const gchar *name);
 
+/* read a "hosts" file and add its entries to the IPv4 & IPv6 hash tables */
+extern gboolean read_hosts_file (const char *hostspath);
+
 /* adds a hostname in the hash table */
 extern gboolean add_ip_name_from_string (const char *addr, const char *name);
 
+/** Get a list of host name to address mappings we know about.
+ * 
+ * Each list element is an addrinfo struct with the following fields defined:
+ *   - ai_family: 0, AF_INET or AF_INET6
+ *   - ai_addrlen: Length of ai_addr
+ *   - ai_canonname: Host name or NULL
+ *   - ai_addr: Pointer to a struct sockaddr or NULL (see below)
+ *   - ai_next: Next element or NULL
+ * All other fields are zero-filled.
+ *
+ * If ai_family is 0, this is a dummy entry which should only appear at the beginning of the list.
+ *
+ * If ai_family is AF_INET, ai_addr points to a struct sockaddr_in with the following fields defined:
+ *   - sin_family: AF_INET
+ *   - sin_addr: Host IPv4 address
+ * All other fields are zero-filled.
+ *
+ * If ai_family is AF_INET6, ai_addr points to a struct sockaddr_in6 with the following fields defined:
+ *   - sin6_family: AF_INET6
+ *   - sin6_addr: Host IPv6 address
+ * All other fields are zero-filled.
+ *
+ * The list and its elements MUST NOT be modified or freed.
+ * 
+ * @return The first element in our list of known addresses. May be NULL.
+ */
+extern struct addrinfo *get_addrinfo_list(void);
+
 /* add ethernet address / name corresponding to IP address  */
 extern void add_ether_byip(const guint ip, const guint8 *eth);
 
index 1b0846906a2bfa1788c8a21f5866f0f03e6def25..068890728bcb0462df798432eb4cff996f13e693 100644 (file)
@@ -13,6 +13,8 @@ abs_time_secs_to_str
 abs_time_to_str
 add_new_data_source
 add_ip_name_from_string
+add_ipv4_name
+add_ipv6_name
 add_itu_tcap_subdissector
 address_to_str_buf
 AdmissionRejectReason_vals      DATA
@@ -500,6 +502,7 @@ geoip_db_name
 geoip_db_num_dbs
 geoip_db_type
 get_addr_name
+get_addrinfo_list
 get_asn1_ctx
 get_basename
 get_ber_identifier
@@ -862,6 +865,7 @@ range_copy
 range_empty
 range_foreach
 ranges_are_equal
+read_hosts_file
 read_keytab_file
 read_keytab_file_from_preferences
 read_prefs
diff --git a/file.c b/file.c
index 72c1f3958e98fb4dfbdf524d427df4a052a85ac6..075d688f042e96024b3c36567349674a387c21ed 100644 (file)
--- a/file.c
+++ b/file.c
@@ -73,6 +73,7 @@
 #include <epan/dfilter/dfilter-macro.h>
 #include <wsutil/file_util.h>
 #include <epan/strutil.h>
+#include <epan/addr_resolv.h>
 
 #ifdef HAVE_LIBPCAP
 gboolean auto_scroll_live;
@@ -359,6 +360,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
     ber_set_filename(cf->filename);
   }
 
+  wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
+  wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
+
   return CF_OK;
 
 fail:
index 0b81d4978aebb0fd01a99e91a27820735102d82a..4278b1a94445367bcadc3ceba762cf01e512ddf1 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -166,7 +166,7 @@ static void report_counts_siginfo(int);
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
 
-static int load_cap_file(capture_file *, char *, int, int, gint64);
+static int load_cap_file(capture_file *, char *, int, gboolean, int, gint64);
 static gboolean process_packet(capture_file *cf, gint64 offset,
     const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
     const guchar *pd, gboolean filtering_tap_listeners, guint tap_flags);
@@ -819,6 +819,7 @@ main(int argc, char *argv[])
 #endif
   gboolean             quiet = FALSE;
   int                  out_file_type = WTAP_FILE_PCAP;
+  gboolean             out_file_name_res = FALSE;
   gchar               *cf_name = NULL, *rfilter = NULL;
 #ifdef HAVE_PCAP_OPEN_DEAD
   struct bpf_program   fcode;
@@ -845,7 +846,7 @@ main(int argc, char *argv[])
 #define OPTSTRING_I ""
 #endif
 
-#define OPTSTRING "a:b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hi:" OPTSTRING_I "K:lLnN:o:pPqr:R:s:St:T:u:vVw:xX:y:z:"
+#define OPTSTRING "a:b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hH:i:" OPTSTRING_I "K:lLnN:o:pPqr:R:s:St:T:u:vVw:W:xX:y:z:"
 
   static const char    optstring[] = OPTSTRING;
 
@@ -1159,6 +1160,20 @@ main(int argc, char *argv[])
           return 1;
         }
         break;
+      case 'W':        /* Select extra information to save in our capture file */
+        /* This is patterned after the -N flag which may not be the best idea. */
+        if (strchr(optarg, 'n'))
+            out_file_name_res = TRUE;
+        break;
+      case 'H':        /* Read address to name mappings from a hosts file */
+        if (! read_hosts_file(optarg))
+        {
+          cmdarg_err("Can't read host entries from \"%s\"", optarg);
+          return 1;
+        }
+        out_file_name_res = TRUE;
+        break;
+
       case 'h':        /* Print help and exit */
         print_usage(TRUE);
         return 0;
@@ -1694,11 +1709,11 @@ main(int argc, char *argv[])
 
     /* Process the packets in the file */
 #ifdef HAVE_LIBPCAP
-    err = load_cap_file(&cfile, global_capture_opts.save_file, out_file_type,
+    err = load_cap_file(&cfile, global_capture_opts.save_file, out_file_type, out_file_name_res,
         global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0,
         global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0);
 #else
-    err = load_cap_file(&cfile, NULL, out_file_type, 0, 0);
+    err = load_cap_file(&cfile, NULL, out_file_type, out_file_name_res, 0, 0);
 #endif
     if (err != 0) {
       /* We still dump out the results of taps, etc., as we might have
@@ -2548,7 +2563,7 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
 
 static int
 load_cap_file(capture_file *cf, char *save_file, int out_file_type,
-    int max_packet_count, gint64 max_byte_count)
+    gboolean out_file_name_res, int max_packet_count, gint64 max_byte_count)
 {
   gint         linktype;
   int          snapshot_length;
@@ -2616,6 +2631,13 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     pdh = NULL;
   }
 
+  if (pdh && out_file_name_res) {
+    if (!wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list())) {
+      cmdarg_err("The file format \"%s\" doesn't support name resolution information.",
+                 wtap_file_type_short_string(out_file_type));
+    }
+  }
+
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
 
@@ -3341,6 +3363,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 
   cf->state = FILE_READ_IN_PROGRESS;
 
+  wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
+  wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
+
   return CF_OK;
 
 fail:
index d3c271f3582cc11e9cd37c51223dfaa0f4fa9f88..19df5e9f80defa113a19e742dc1b1f23bfb7c116 100644 (file)
@@ -286,11 +286,7 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
        }
 
        errno = ENOMEM;
-       wth = (wtap *)g_malloc(sizeof(wtap));
-       if (wth == NULL) {
-               *err = errno;
-               return NULL;
-       }
+       wth = (wtap *)g_malloc0(sizeof(wtap));
 
        /* Open the file */
        errno = WTAP_ERR_CANT_OPEN;
@@ -394,241 +390,247 @@ success:
 /* Table of the file types we know about. */
 static const struct file_type_info dump_open_table_base[] = {
        /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
-       { NULL, NULL, NULL, NULL, FALSE,
+       { NULL, NULL, NULL, NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_WTAP (only used internally while capturing) */
-       { NULL, NULL, NULL, NULL, FALSE,
+       { NULL, NULL, NULL, NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_PCAP */
-       { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", TRUE,
+       { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", TRUE, FALSE,
          libpcap_dump_can_write_encap, libpcap_dump_open },
 
        /* WTAP_FILE_PCAP_NSEC */
-       { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", TRUE,
+       { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", TRUE, FALSE,
          libpcap_dump_can_write_encap, libpcap_dump_open },
 
        /* WTAP_FILE_PCAP_AIX */
-       { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
+       { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", TRUE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_PCAP_SS991029 */
-       { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
+       { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", TRUE, FALSE,
          libpcap_dump_can_write_encap, libpcap_dump_open },
 
        /* WTAP_FILE_PCAP_NOKIA */
-       { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", TRUE,
+       { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", TRUE, FALSE,
          libpcap_dump_can_write_encap, libpcap_dump_open },
 
        /* WTAP_FILE_PCAP_SS990417 */
-       { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", TRUE,
+       { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", TRUE, FALSE,
          libpcap_dump_can_write_encap, libpcap_dump_open },
 
        /* WTAP_FILE_PCAP_SS990915 */
-       { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", TRUE,
+       { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", TRUE, FALSE,
          libpcap_dump_can_write_encap, libpcap_dump_open },
 
        /* WTAP_FILE_5VIEWS */
-       { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", FALSE,
+       { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", FALSE, FALSE,
          _5views_dump_can_write_encap, _5views_dump_open },
 
        /* WTAP_FILE_IPTRACE_1_0 */
-       { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE,
+       { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_IPTRACE_2_0 */
-       { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE,
+       { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_BER */
-       { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE,
+       { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE, FALSE,
                NULL, NULL },
 
        /* WTAP_FILE_HCIDUMP */
-       { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE,
+       { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_CATAPULT_DCT2000 */
-       { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE,
+       { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE, FALSE,
          catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
 
        /* WTAP_FILE_NETXRAY_OLD */
-       { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", FALSE,
+       { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_NETXRAY_1_0 */
-       { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", FALSE,
+       { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_COSINE */
-       { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE,
+       { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_CSIDS */
-       { "CSIDS IPLog", "csids", "*.*", NULL, FALSE,
+       { "CSIDS IPLog", "csids", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_DBS_ETHERWATCH */
-       { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE,
+       { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE, FALSE,
          NULL, NULL},
 
        /* WTAP_FILE_ERF */
-       { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE,
+       { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_EYESDN */
-       { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.trc", ".trc", FALSE,
+       { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.trc", ".trc", FALSE, FALSE,
           eyesdn_dump_can_write_encap, eyesdn_dump_open },
 
        /* WTAP_FILE_NETTL */
-       { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE,
+       { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE, FALSE,
          nettl_dump_can_write_encap, nettl_dump_open },
 
        /* WTAP_FILE_ISERIES */
-       { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE,
+       { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_ISERIES_UNICODE */
-       { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE,
+       { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_I4BTRACE */
-       { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE,
+       { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_ASCEND */
-       { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE,
+       { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_NETMON_1_x */
-       { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", FALSE,
+       { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", FALSE, FALSE,
          netmon_dump_can_write_encap, netmon_dump_open },
 
        /* WTAP_FILE_NETMON_2_x */
-       { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", FALSE,
+       { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", FALSE, FALSE,
          netmon_dump_can_write_encap, netmon_dump_open },
 
        /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
-       { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE,
+       { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE, FALSE,
          ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
 
        /* WTAP_FILE_NGSNIFFER_COMPRESSED */
-       { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE,
+       { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_NETXRAY_1_1 */
-       { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", FALSE,
+       { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", FALSE, FALSE,
          netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
 
        /* WTAP_FILE_NETXRAY_2_00x */
-       { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", FALSE,
+       { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", FALSE, FALSE,
          netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
 
        /* WTAP_FILE_NETWORK_INSTRUMENTS_V9 */
-       { "Network Instruments Observer (V9)", "niobserverv9", "*.bfr", ".bfr", FALSE,
+       { "Network Instruments Observer (V9)", "niobserverv9", "*.bfr", ".bfr", FALSE, FALSE,
          network_instruments_dump_can_write_encap, network_instruments_dump_open },
 
        /* WTAP_FILE_LANALYZER */
-       { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", FALSE,
+       { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", FALSE, FALSE,
          lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
 
        /* WTAP_FILE_PPPDUMP */
-       { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE,
+       { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_RADCOM */
-       { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE,
+       { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_SNOOP */
-       { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE,
+       { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE, FALSE,
          snoop_dump_can_write_encap, snoop_dump_open },
 
        /* WTAP_FILE_SHOMITI */
-       { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE,
+       { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_VMS */
-       { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE,
+       { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE, FALSE,
          NULL, NULL},
 
        /* WTAP_FILE_K12 */
-       { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE,
+       { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE, FALSE,
                k12_dump_can_write_encap, k12_dump_open },
 
        /* WTAP_FILE_TOSHIBA */
-       { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE,
+       { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_VISUAL_NETWORKS */
-       { "Visual Networks traffic capture", "visual", "*.*", NULL, FALSE,
+       { "Visual Networks traffic capture", "visual", "*.*", NULL, FALSE, FALSE,
          visual_dump_can_write_encap, visual_dump_open },
 
        /* WTAP_FILE_ETHERPEEK_V56 */
-       { "WildPackets Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
+       { "WildPackets Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_ETHERPEEK_V7 */
-       { "WildPackets Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
+       { "WildPackets Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_ETHERPEEK_V9 */
-       { "WildPackets Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
+       { "WildPackets Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_MPEG */
-       { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE,
+       { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_K12TEXT  */
-       { "K12 text file", "k12text", "*.txt", ".txt", TRUE,
+       { "K12 text file", "k12text", "*.txt", ".txt", TRUE, FALSE,
          k12text_dump_can_write_encap, k12text_dump_open },
 
        /* WTAP_FILE_NETSCREEN */
-       { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE,
+       { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE, FALSE,
          NULL, NULL },
 
        /* WTAP_FILE_COMMVIEW */
-       { "TamoSoft CommView", "commview", "*.ncf", ".ncf", TRUE,
+       { "TamoSoft CommView", "commview", "*.ncf", ".ncf", TRUE, FALSE,
          commview_dump_can_write_encap, commview_dump_open },
 
        /* WTAP_FILE_PCAPNG */
-       { "Wireshark - pcapng (experimental)", "pcapng", "*.pcapng", NULL, FALSE,
+       { "Wireshark - pcapng", "pcapng", "*.pcapng", NULL, FALSE, TRUE,
          pcapng_dump_can_write_encap, pcapng_dump_open },
 
        /* WTAP_FILE_BTSNOOP */
-       { "Symbian OS btsnoop", "btsnoop", "*.log", ".log", FALSE,
+       { "Symbian OS btsnoop", "btsnoop", "*.log", ".log", FALSE, FALSE,
          btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
 
        /* WTAP_FILE_X2E_XORAYA */
-       { NULL, NULL, NULL, NULL, FALSE, NULL, NULL },
+       { NULL, NULL, NULL, NULL, FALSE, FALSE,
+         NULL, NULL },
 
        /* WTAP_FILE_TNEF */
-       { "Transport-Neutral Encapsulation Format", "tnef", "*.*", NULL, FALSE, NULL, NULL },
+       { "Transport-Neutral Encapsulation Format", "tnef", "*.*", NULL, FALSE, FALSE,
+         NULL, NULL },
 
        /* WTAP_FILE_DCT3TRACE */
-       { "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, NULL, NULL },
+       { "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, FALSE,
+         NULL, NULL },
 
        /* WTAP_FILE_PACKETLOGGER */
-       { "PacketLogger", "pklg", "*.pklg", NULL, FALSE, NULL, NULL },
+       { "PacketLogger", "pklg", "*.pklg", NULL, FALSE, FALSE,
+         NULL, NULL },
 
        /* WTAP_FILE_DAINTREE_SNA */
-       { "Daintree SNA", "dsna", "*.dcf", NULL, FALSE, NULL, NULL },
+       { "Daintree SNA", "dsna", "*.dcf", NULL, FALSE, FALSE,
+         NULL, NULL },
 
        /* WTAP_FILE_NETSCALER_1_0 */
-       { "NetScaler Trace (Version 1.0)", "nstrace10", "*.*", "*.*", FALSE,
+       { "NetScaler Trace (Version 1.0)", "nstrace10", "*.*", "*.*", FALSE, FALSE,
          nstrace_10_dump_can_write_encap, nstrace_dump_open },
 
        /* WTAP_FILE_NETSCALER_2_0 */
-       { "NetScaler Trace (Version 2.0)", "nstrace20", "*.cap", "*.cap", FALSE,
+       { "NetScaler Trace (Version 2.0)", "nstrace20", "*.cap", "*.cap", FALSE, FALSE,
          nstrace_20_dump_can_write_encap, nstrace_dump_open },
 
        /* WTAP_FILE_JPEG_JFIF */
-       { "JPEG/JFIF", "jpeg", "*.jpg;*.jpeg;*.jfif", ".jpg", FALSE, NULL, NULL },
+       { "JPEG/JFIF", "jpeg", "*.jpg;*.jpeg;*.jfif", ".jpg", FALSE, FALSE,
+         NULL, NULL },
 
        /* WTAP_FILE_IPFIX */
-       { "IPFIX File Format", "ipfix", "*.pfx;*.ipfix", NULL, FALSE,
+       { "IPFIX File Format", "ipfix", "*.pfx;*.ipfix", NULL, FALSE, FALSE,
          NULL, NULL }
 };
 
@@ -752,6 +754,14 @@ gboolean wtap_dump_can_compress(int filetype _U_)
 }
 #endif
 
+gboolean wtap_dump_has_name_resolution(int filetype)
+{
+       if (filetype < 0 || filetype >= wtap_num_file_types
+           || dump_open_table[filetype].has_name_resolution == FALSE)
+               return FALSE;
+
+       return TRUE;
+}
 
 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
@@ -879,7 +889,6 @@ static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compresse
        if (*err != 0)
                return FALSE;
 
-
        /* All systems go! */
        return TRUE;
 }
@@ -889,20 +898,16 @@ static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
 {
        wtap_dumper *wdh;
 
-       wdh = (wtap_dumper *)g_malloc(sizeof (wtap_dumper));
+       wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
        if (wdh == NULL) {
                *err = errno;
                return NULL;
        }
-       wdh->fh = NULL;
+
        wdh->file_type = filetype;
        wdh->snaplen = snaplen;
        wdh->encap = encap;
        wdh->compressed = compressed;
-       wdh->bytes_dumped = 0;
-       wdh->priv = NULL;
-       wdh->subtype_write = NULL;
-       wdh->subtype_close = NULL;
        return wdh;
 }
 
@@ -994,6 +999,14 @@ void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
        wdh->bytes_dumped = bytes_dumped;
 }
 
+gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list)
+{
+       if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
+               || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
+                       return FALSE;
+       wdh->addrinfo_list = addrinfo_list;
+       return TRUE;
+}
 
 /* internally open a file for writing (compressed or not) */
 #ifdef HAVE_LIBZ
index 7870a797b12de6cf87b355d6511ee94644fb45b8..e1ef077044cc93f9814ed541c9353981eee97639 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+
+/* Needed for addrinfo */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+#endif
+
 #include "wtap-int.h"
 #include "file_wrappers.h"
 #include "buffer.h"
@@ -125,6 +147,13 @@ typedef struct pcapng_simple_packet_block_s {
        /* ... Padding ... */
 } pcapng_simple_packet_block_t;
 
+/* pcapng: simple packet block */
+typedef struct pcapng_name_resolution_block_s {
+       guint16 record_type;
+       guint16 record_len;
+       /* ... Record ... */
+} pcapng_name_resolution_block_t;
+
 /* pcapng: interface statistics block */
 typedef struct pcapng_interface_statistics_block_s {
        guint32 interface_id;
@@ -281,6 +310,8 @@ typedef struct {
        gint8 if_fcslen;
        GArray *interface_data;
        guint number_of_interfaces;
+       wtap_new_ipv4_callback_t add_new_ipv4;
+       wtap_new_ipv6_callback_t add_new_ipv6;
 } pcapng_t;
 
 static int
@@ -1052,6 +1083,116 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *
        return block_read;
 }
 
+#define NRES_ENDOFRECORD 0
+#define NRES_IP4RECORD 1
+#define NRES_IP6RECORD 2
+#define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
+/* IPv6 + MAXNAMELEN */
+#define MAX_NRB_REC_SIZE (16 + 64)
+static int
+pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock _U_,int *err, gchar **err_info _U_)
+{
+       int bytes_read = 0;
+       int block_read = 0;
+       int to_read;
+       guint64 file_offset64;
+       pcapng_name_resolution_block_t nrb;
+       guchar nrb_rec[MAX_NRB_REC_SIZE];
+       guint32 v4_addr;
+
+       errno = WTAP_ERR_CANT_READ;
+       to_read = bh->block_total_length
+               - sizeof(pcapng_block_header_t)
+               - sizeof(bh->block_total_length);
+
+       while (block_read < to_read) {
+               bytes_read = file_read(&nrb, 1, sizeof nrb, fh);
+               if (bytes_read != sizeof nrb) {
+                       pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
+                       *err = file_error(fh);
+                       return 0;
+               }
+               block_read += bytes_read;
+
+               if (pn->byte_swapped) {
+                       nrb.record_type = BSWAP32(nrb.record_type);
+                       nrb.record_len  = BSWAP32(nrb.record_len);
+               }
+
+               switch(nrb.record_type) {
+                       case NRES_ENDOFRECORD:
+                               /* There shouldn't be any more data */
+                               to_read = 0;
+                               break;
+                       case NRES_IP4RECORD:
+                               if (nrb.record_len < 6 || nrb.record_len > MAX_NRB_REC_SIZE || to_read < nrb.record_len) {
+                                       pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv4 record");
+                                       return 0;
+                               }
+                               bytes_read = file_read(nrb_rec, 1, nrb.record_len, fh);
+                               if (bytes_read != nrb.record_len) {
+                                       pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
+                                       *err = file_error(fh);
+                                       return 0;
+                               }
+                               block_read += bytes_read;
+
+                               if (pn->add_new_ipv4) {
+                                       memcpy(&v4_addr, nrb_rec, 4);
+                                       if (pn->byte_swapped)
+                                               v4_addr = BSWAP32(v4_addr);
+                                       pn->add_new_ipv4(v4_addr, nrb_rec + 4);
+                               }
+
+                               file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
+                               if (file_offset64 <= 0) {
+                                       if (*err != 0)
+                                               return -1;
+                                       return 0;
+                               }
+                               block_read += PADDING4(nrb.record_len);
+                               break;
+                       case NRES_IP6RECORD:
+                               if (nrb.record_len < 18 || nrb.record_len > MAX_NRB_REC_SIZE || to_read < nrb.record_len) {
+                                       pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv6 record");
+                                       return 0;
+                               }
+                               bytes_read = file_read(nrb_rec, 1, nrb.record_len, fh);
+                               if (bytes_read != nrb.record_len) {
+                                       pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
+                                       *err = file_error(fh);
+                                       return 0;
+                               }
+                               block_read += bytes_read;
+
+                               if (pn->add_new_ipv6) {
+                                       pn->add_new_ipv6(nrb_rec, nrb_rec + 16);
+                               }
+
+                               file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
+                               if (file_offset64 <= 0) {
+                                       if (*err != 0)
+                                               return -1;
+                                       return 0;
+                               }
+                               block_read += PADDING4(nrb.record_len);
+                               break;
+                       default:
+                               pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
+                               file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
+                               if (file_offset64 <= 0) {
+                                       if (*err != 0)
+                                               return -1;
+                                       return 0;
+                               }
+                               block_read += nrb.record_len + PADDING4(nrb.record_len);
+                               break;
+               }
+       }
+
+       return block_read;
+}
+
 static int
 pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock,int *err, gchar **err_info _U_)
 {
@@ -1248,6 +1389,9 @@ pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t
                case(BLOCK_TYPE_EPB):
                        bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
                        break;
+               case(BLOCK_TYPE_NRB):
+                       bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
+                       break;
                case(BLOCK_TYPE_ISB):
                        bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
                        break;
@@ -1375,6 +1519,9 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
        wblock.packet_header = &wth->phdr;
        wblock.file_encap    = &wth->file_encap;
 
+       pcapng->add_new_ipv4 = wth->add_new_ipv4;
+       pcapng->add_new_ipv6 = wth->add_new_ipv6;
+
        /* read next block */
        while (1) {
                bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
@@ -1486,6 +1633,7 @@ pcapng_close(wtap *wth)
 typedef struct {
        GArray *interface_data;
        guint number_of_interfaces;
+       struct addrinfo *addrinfo_list_last;
 } pcapng_dump_t;
 
 static gboolean
@@ -1638,6 +1786,97 @@ pcapng_write_packet_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
        return TRUE;
 }
 
+/* Arbitrary. */
+#define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
+static gboolean
+pcapng_write_name_resolution_block(wtap_dumper *wdh, pcapng_dump_t *pcapng, int *err)
+{
+       pcapng_block_header_t bh;
+       pcapng_name_resolution_block_t nrb;
+       struct addrinfo *ai;
+       struct sockaddr_in *sa4;
+       struct sockaddr_in6 *sa6;
+       guchar *rec_data;
+       gint rec_off, namelen, tot_rec_len;
+
+       if (! pcapng->addrinfo_list_last || ! pcapng->addrinfo_list_last->ai_next) {
+               return TRUE;
+       }
+
+       rec_off = 8; /* block type + block total length */
+       bh.block_type = BLOCK_TYPE_NRB;
+       bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
+       rec_data = g_malloc(NRES_REC_MAX_SIZE);
+       
+       for (; pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next; pcapng->addrinfo_list_last = pcapng->addrinfo_list_last->ai_next ) {
+               ai = pcapng->addrinfo_list_last->ai_next; /* Skips over the first (dummy) entry */
+               namelen = strlen(ai->ai_canonname) + 1;
+               if (ai->ai_family == AF_INET) {
+                       nrb.record_type = NRES_IP4RECORD;
+                       nrb.record_len = 4 + namelen;
+                       tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
+                       bh.block_total_length += tot_rec_len;
+
+                       if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
+                               break;
+
+                       sa4 = (struct sockaddr_in *) ai->ai_addr;
+                       memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
+                       rec_off += 4;
+
+                       memcpy(rec_data + rec_off, &(sa4->sin_addr.s_addr), 4);
+                       rec_off += 4;
+
+                       memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
+                       rec_off += namelen;
+
+                       memset(rec_data + rec_off, 0, PADDING4(namelen));
+                       rec_off += PADDING4(namelen);
+                       pcapng_debug1("NRB: added IPv4 record for %s", ai->ai_canonname);
+               } else if (ai->ai_family == AF_INET6) {
+                       nrb.record_type = NRES_IP6RECORD;
+                       nrb.record_len = 16 + namelen;
+                       tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
+                       bh.block_total_length += tot_rec_len;
+
+                       if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
+                               break;
+
+                       sa6 = (struct sockaddr_in6 *) ai->ai_addr;
+                       memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
+                       rec_off += 4;
+
+                       memcpy(rec_data + rec_off, sa6->sin6_addr.s6_addr, 16);
+                       rec_off += 16;
+
+                       memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
+                       rec_off += namelen;
+
+                       memset(rec_data + rec_off, 0, PADDING4(namelen));
+                       rec_off += PADDING4(namelen);
+                       pcapng_debug1("NRB: added IPv6 record for %s", ai->ai_canonname);
+               }
+       }
+
+       /* We know the total length now; copy the block header. */
+       memcpy(rec_data, &bh, sizeof(bh));
+
+       /* End of record */
+       memset(rec_data + rec_off, 0, 4);
+       rec_off += 4;
+
+       memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+
+       if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
+               g_free(rec_data);
+               return FALSE;
+       }
+
+       g_free(rec_data);
+       wdh->bytes_dumped += bh.block_total_length;
+       return TRUE;
+}
+
 
 static gboolean
 pcapng_write_block(wtap_dumper *wdh, /*pcapng_t *pn, */wtapng_block_t *wblock, int *err)
@@ -1691,6 +1930,9 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
                      phdr->pkt_encap,
                      wtap_encap_string(phdr->pkt_encap));
 
+       if (!pcapng->addrinfo_list_last) 
+               pcapng->addrinfo_list_last = wdh->addrinfo_list;
+
        interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
        if (interface_id == G_MAXUINT32) {
                /* write the interface description block */
@@ -1724,6 +1966,11 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
                              wtap_encap_string(phdr->pkt_encap));
        }
 
+       /* Flush any hostname resolution info we may have */
+       while (pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next) {
+               pcapng_write_name_resolution_block(wdh, pcapng, err);
+       }
+
        wblock.frame_buffer  = pd;
        wblock.pseudo_header = pseudo_header;
        wblock.packet_header = NULL;
@@ -1786,10 +2033,9 @@ pcapng_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
        /* This is a pcapng file */
        wdh->subtype_write = pcapng_dump;
        wdh->subtype_close = pcapng_dump_close;
-       pcapng = (pcapng_dump_t *)g_malloc(sizeof(pcapng_dump_t));
+       pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
        wdh->priv = (void *)pcapng;
        pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
-       pcapng->number_of_interfaces = 0;
 
        /* write the section header block */
        wblock.type = BLOCK_TYPE_SHB;
index 361b57a819a0a0a3441b8a3f8829c89c2acf3f97..87ddf4a2fb251bfb60d093cc99ff4acde72b9483 100644 (file)
@@ -71,6 +71,8 @@ struct wtap {
                                                   types */
        int                     tsprecision;    /* timestamp precision of the lower 32bits
                                                 * e.g. WTAP_FILE_TSPREC_USEC */
+       wtap_new_ipv4_callback_t add_new_ipv4;
+       wtap_new_ipv6_callback_t add_new_ipv6;
 };
 
 struct wtap_dumper;
@@ -85,8 +87,8 @@ struct wtap_dumper {
        int                     file_type;
        int                     snaplen;
        int                     encap;
-       gboolean        compressed;
-       gint64          bytes_dumped;
+       gboolean                compressed;
+       gint64                  bytes_dumped;
 
        void                    *priv;
 
@@ -95,10 +97,14 @@ struct wtap_dumper {
 
        int                     tsprecision;    /* timestamp precision of the lower 32bits
                                                         * e.g. WTAP_FILE_TSPREC_USEC */
+       struct addrinfo *addrinfo_list;
 };
 
 extern gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf,
     size_t bufsize, int *err);
+extern gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err);
+extern gint64 wtap_dump_file_tell(wtap_dumper *wdh);
+
 
 extern gint wtap_num_file_types;
 
@@ -327,3 +333,16 @@ extern gint wtap_num_file_types;
 #endif
 
 #endif /* __WTAP_INT_H__ */
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set shiftwidth=8 tabstop=8 noexpandtab
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */
index ae070418b7287f4c75f54a355590ca63c703ed85..2c420fd4cae4b6279c9c2beca4d6ede8261ead9f 100644 (file)
@@ -40,7 +40,6 @@
 #endif
 
 #include "wtap-int.h"
-#include "wtap.h"
 
 #include "file_wrappers.h"
 #include <wsutil/file_util.h>
@@ -671,6 +670,16 @@ wtap_cleareof(wtap *wth _U_) {
 #endif
 }
 
+void wtap_set_cb_new_ipv4(wtap *wth, wtap_new_ipv4_callback_t add_new_ipv4) {
+       if (wth)
+               wth->add_new_ipv4 = add_new_ipv4;
+}
+
+void wtap_set_cb_new_ipv6(wtap *wth, wtap_new_ipv6_callback_t add_new_ipv6) {
+       if (wth)
+               wth->add_new_ipv6 = add_new_ipv6;
+}
+
 gboolean
 wtap_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
 {
index 422291001d3b7abc374e951a871304f19484cbfe..f0f3a3265df8048ee4ad7102b2dd406c074d1558 100644 (file)
@@ -30,6 +30,7 @@ wtap_dump_close
 wtap_dump_fdopen
 wtap_dump_flush
 wtap_dump_open
+wtap_dump_set_addrinfo_list
 wtap_encap_short_string
 wtap_encap_string
 wtap_file_encap
@@ -55,6 +56,8 @@ wtap_register_open_routine
 wtap_seek_read
 wtap_sequential_close
 wtap_set_bytes_dumped
+wtap_set_cb_new_ipv4
+wtap_set_cb_new_ipv6
 wtap_short_string_to_encap
 wtap_short_string_to_file_type
 wtap_snapshot_length
index de7060066a80a56533749f367baf2cded26c7eb6..6f73d0c0d66497cba3ec3b5fbd5e68fe4c3b2918 100644 (file)
@@ -822,6 +822,7 @@ struct wtap_dumper;
 typedef struct wtap wtap;
 typedef struct wtap_dumper wtap_dumper;
 
+/* XXX Should this be moved to wtap-int.h? It appears to be internal to wtap.c. */
 struct file_type_info {
     /* the file type name */
     /* should be NULL for all "pseudo" types that are only internally used and not read/writeable */
@@ -842,8 +843,12 @@ struct file_type_info {
     /* can this type be compressed with gzip? */
     gboolean can_compress;
 
+    /* does this type support name resolution records? */
+    /* should be NULL is this file type doesn't have write support */
+    gboolean has_name_resolution;
+
     /* can this type write this encapsulation format? */
-    /* should be NULL is this file type don't have write support */
+    /* should be NULL is this file type doesn't have write support */
     int (*can_write_encap)(int);
 
     /* the function to open the capture file for writing */
@@ -872,6 +877,16 @@ struct wtap* wtap_open_offline(const char *filename, int *err,
  */
 void wtap_cleareof(wtap *wth);
 
+/*
+ * Set callback functions to add new hostnames. Currently pcapng-only.
+ * MUST match add_ipv4_name and add_ipv6_name in addr_resolv.c.
+ */
+typedef void (*wtap_new_ipv4_callback_t) (const guint addr, const gchar *name);
+void wtap_set_cb_new_ipv4(wtap *wth, wtap_new_ipv4_callback_t add_new_ipv4);
+
+typedef void (*wtap_new_ipv6_callback_t) (const void *addrp, const gchar *name);
+void wtap_set_cb_new_ipv6(wtap *wth, wtap_new_ipv6_callback_t add_new_ipv6);
+
 /* Returns TRUE if read was successful. FALSE if failure. data_offset is
  * set to the offset in the file where the data for the read packet is
  * located. */
@@ -915,6 +930,8 @@ gboolean wtap_dump(wtap_dumper *, const struct wtap_pkthdr *,
 void wtap_dump_flush(wtap_dumper *);
 gint64 wtap_get_bytes_dumped(wtap_dumper *);
 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped);
+struct addrinfo;
+gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list);
 gboolean wtap_dump_close(wtap_dumper *, int *);
 
 /*** various string converter functions ***/