diff --git a/doc/editcap.pod b/doc/editcap.pod index bf699723b5..deea34ea76 100644 --- a/doc/editcap.pod +++ b/doc/editcap.pod @@ -10,6 +10,8 @@ S<[ B<-c> Epackets per fileE ]> S<[ B<-C> EchoplenE ]> S<[ B<-E> Eerror probabilityE ]> S<[ B<-F> Efile formatE ]> +S<[ B<-W> Efile format optionE]> +S<[ B<-H> Einput hosts file ]> S<[ B<-A> Estart timeE ]> S<[ B<-B> Estop timeE ]> S<[ B<-h> ]> @@ -150,6 +152,30 @@ B can write the file in several formats, B provides a list of the available output formats. The default is the B format. +=item -W Efile format optionE + +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 as needed. + +The argument is a string that may contain the following letter: + +B write network address resolution information (pcapng only) + +=item -H Einput "hosts" fileE + +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. + =item -A Estart timeE Saves only the packets whose timestamp is on or after start time. diff --git a/doc/tshark.pod b/doc/tshark.pod index 7d94e4e8af..8813cc43ca 100644 --- a/doc/tshark.pod +++ b/doc/tshark.pod @@ -18,6 +18,7 @@ S<[ B<-E> Efield print optionE ]> S<[ B<-f> Ecapture filterE ]> S<[ B<-F> Efile formatE ]> S<[ B<-h> ]> +S<[ B<-H> Einput hosts fileE ]> S<[ B<-i> Ecapture interfaceE|- ]> S<[ B<-I> ]> S<[ B<-K> EkeytabE ]> @@ -37,6 +38,7 @@ S<[ B<-T> pdml|psml|ps|text|fields ]> S<[ B<-v> ]> S<[ B<-V> ]> S<[ B<-w> EoutfileE|- ]> +S<[ B<-W> Efile format optionE]> S<[ B<-x> ]> S<[ B<-X> EeXtension optionE]> S<[ B<-y> Ecapture link typeE ]> @@ -398,6 +400,14 @@ B Dumps a copy of the current preferences file to stdout. Print the version and options and exits. +=item -H Einput hosts fileE + +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. + =item -i Ecapture interfaceE | - 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 Efile format optionE + +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 as needed. + +The argument is a string that may contain the following letter: + +B write network address resolution information (pcapng only) + =item -x Cause B to print a hex and ASCII dump of the packet data diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c index 05fb9bc494..89094a82fc 100644 --- a/epan/addr_resolv.c +++ b/epan/addr_resolv.c @@ -149,6 +149,11 @@ #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. * = | | @@ -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 */ /* ----------------- diff --git a/epan/addr_resolv.h b/epan/addr_resolv.h index 79b424232a..76fb481d7e 100644 --- a/epan/addr_resolv.h +++ b/epan/addr_resolv.h @@ -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); diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 1b0846906a..068890728b 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -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 72c1f3958e..075d688f04 100644 --- a/file.c +++ b/file.c @@ -73,6 +73,7 @@ #include #include #include +#include #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: diff --git a/tshark.c b/tshark.c index 0b81d4978a..4278b1a944 100644 --- 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: diff --git a/wiretap/file_access.c b/wiretap/file_access.c index d3c271f358..19df5e9f80 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -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 diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index 7870a797b1..e1ef077044 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -36,6 +36,28 @@ #include #include #include + +/* Needed for addrinfo */ +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#ifdef HAVE_NETDB_H +# include +#endif + +#ifdef HAVE_WINSOCK2_H +# include +#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; diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h index 361b57a819..87ddf4a2fb 100644 --- a/wiretap/wtap-int.h +++ b/wiretap/wtap-int.h @@ -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: + */ diff --git a/wiretap/wtap.c b/wiretap/wtap.c index ae070418b7..2c420fd4ca 100644 --- a/wiretap/wtap.c +++ b/wiretap/wtap.c @@ -40,7 +40,6 @@ #endif #include "wtap-int.h" -#include "wtap.h" #include "file_wrappers.h" #include @@ -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) { diff --git a/wiretap/wtap.def b/wiretap/wtap.def index 422291001d..f0f3a3265d 100644 --- a/wiretap/wtap.def +++ b/wiretap/wtap.def @@ -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 diff --git a/wiretap/wtap.h b/wiretap/wtap.h index de7060066a..6f73d0c0d6 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -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 ***/