From 04d950130624c14ac8af39c621f69851d8088ed6 Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Tue, 18 Mar 2014 13:21:51 -0400 Subject: Add capture file reader/writer support for Lua so scripts can implement new capture file formats. This enables a Lua script to implement a brand new capture file format reader/writer, so that for example one could write a script to read from vendor-specific "logs" of packets, and show them as normal packets in wireshark. Change-Id: Id394edfffa94529f39789844c382b7ab6cc2d814 Reviewed-on: https://code.wireshark.org/review/431 Reviewed-by: Hadriel Kaplan Reviewed-by: Michael Mann Reviewed-by: Anders Broman --- wiretap/file_access.c | 496 ++++++++++++++++++++++++++++++++++-------------- wiretap/file_wrappers.c | 47 +++++ wiretap/file_wrappers.h | 5 +- wiretap/wtap-int.h | 13 +- wiretap/wtap.h | 40 +++- 5 files changed, 448 insertions(+), 153 deletions(-) (limited to 'wiretap') diff --git a/wiretap/file_access.c b/wiretap/file_access.c index 1be8b35a72..d641aaaea1 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -300,39 +300,39 @@ GSList *wtap_get_all_file_extensions_list(void) */ static struct open_info open_info_base[] = { - { "Pcap", OPEN_INFO_MAGIC, libpcap_open, "pcap" }, - { "PcapNG", OPEN_INFO_MAGIC, pcapng_open, "pcapng"}, - { "NgSniffer", OPEN_INFO_MAGIC, ngsniffer_open, NULL }, - { "Snoop", OPEN_INFO_MAGIC, snoop_open, NULL }, - { "IP Trace", OPEN_INFO_MAGIC, iptrace_open, NULL }, - { "Netmon", OPEN_INFO_MAGIC, netmon_open, NULL }, - { "Netxray", OPEN_INFO_MAGIC, netxray_open, NULL }, - { "Radcom", OPEN_INFO_MAGIC, radcom_open, NULL }, - { "Nettl", OPEN_INFO_MAGIC, nettl_open, NULL }, - { "Visual", OPEN_INFO_MAGIC, visual_open, NULL }, - { "5 Views", OPEN_INFO_MAGIC, _5views_open, NULL }, - { "Network Instruments", OPEN_INFO_MAGIC, network_instruments_open, NULL }, - { "Peek Tagged", OPEN_INFO_MAGIC, peektagged_open, NULL }, - { "DBS Etherwatch", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL }, - { "K12", OPEN_INFO_MAGIC, k12_open, NULL }, - { "Catapult DCT 2000", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL }, - { "Aethra", OPEN_INFO_MAGIC, aethra_open, NULL }, - { "BTSNOOP", OPEN_INFO_MAGIC, btsnoop_open, "log" }, - { "EYESDN", OPEN_INFO_MAGIC, eyesdn_open, NULL }, - { "TNEF", OPEN_INFO_MAGIC, tnef_open, NULL }, - { "MIME Files with Magic Bytes", OPEN_INFO_MAGIC, mime_file_open, NULL }, - { "Lanalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1" }, + { "Pcap", OPEN_INFO_MAGIC, libpcap_open, "pcap", NULL }, + { "PcapNG", OPEN_INFO_MAGIC, pcapng_open, "pcapng", NULL }, + { "NgSniffer", OPEN_INFO_MAGIC, ngsniffer_open, NULL, NULL }, + { "Snoop", OPEN_INFO_MAGIC, snoop_open, NULL, NULL }, + { "IP Trace", OPEN_INFO_MAGIC, iptrace_open, NULL, NULL }, + { "Netmon", OPEN_INFO_MAGIC, netmon_open, NULL, NULL }, + { "Netxray", OPEN_INFO_MAGIC, netxray_open, NULL, NULL }, + { "Radcom", OPEN_INFO_MAGIC, radcom_open, NULL, NULL }, + { "Nettl", OPEN_INFO_MAGIC, nettl_open, NULL, NULL }, + { "Visual", OPEN_INFO_MAGIC, visual_open, NULL, NULL }, + { "5 Views", OPEN_INFO_MAGIC, _5views_open, NULL, NULL }, + { "Network Instruments", OPEN_INFO_MAGIC, network_instruments_open, NULL, NULL }, + { "Peek Tagged", OPEN_INFO_MAGIC, peektagged_open, NULL, NULL }, + { "DBS Etherwatch", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL, NULL }, + { "K12", OPEN_INFO_MAGIC, k12_open, NULL, NULL }, + { "Catapult DCT 2000", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL, NULL }, + { "Aethra", OPEN_INFO_MAGIC, aethra_open, NULL, NULL }, + { "BTSNOOP", OPEN_INFO_MAGIC, btsnoop_open, "log", NULL }, + { "EYESDN", OPEN_INFO_MAGIC, eyesdn_open, NULL, NULL }, + { "TNEF", OPEN_INFO_MAGIC, tnef_open, NULL, NULL }, + { "MIME Files with Magic Bytes", OPEN_INFO_MAGIC, mime_file_open, NULL, NULL }, + { "Lanalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1", NULL }, /* * PacketLogger must come before MPEG, because its files * are sometimes grabbed by mpeg_open. */ - { "Packet Logger", OPEN_INFO_HEURISTIC, packetlogger_open, "pklg" }, + { "Packet Logger", OPEN_INFO_HEURISTIC, packetlogger_open, "pklg", NULL }, /* Some MPEG files have magic numbers, others just have heuristics. */ - { "Mpeg", OPEN_INFO_HEURISTIC, mpeg_open, "mpg;mp3" }, - { "DCT3 Trace", OPEN_INFO_HEURISTIC, dct3trace_open, "xml" }, - { "Daintree SNA", OPEN_INFO_HEURISTIC, daintree_sna_open, "dcf" }, - { "Stanag 4607", OPEN_INFO_HEURISTIC, stanag4607_open, NULL }, - { "BER", OPEN_INFO_HEURISTIC, ber_open, NULL }, + { "Mpeg", OPEN_INFO_HEURISTIC, mpeg_open, "mpg;mp3", NULL }, + { "DCT3 Trace", OPEN_INFO_HEURISTIC, dct3trace_open, "xml", NULL }, + { "Daintree SNA", OPEN_INFO_HEURISTIC, daintree_sna_open, "dcf", NULL }, + { "Stanag 4607", OPEN_INFO_HEURISTIC, stanag4607_open, NULL, NULL }, + { "BER", OPEN_INFO_HEURISTIC, ber_open, NULL, NULL }, /* I put NetScreen *before* erf, because there were some * false positives with my test-files (Sake Blok, July 2007) * @@ -345,34 +345,59 @@ static struct open_info open_info_base[] = { * because there were some cases where files of those types were * misidentified as vwr files (Guy Harris, December 2013) */ - { "Netscreen", OPEN_INFO_HEURISTIC, netscreen_open, "txt" }, - { "ERF", OPEN_INFO_HEURISTIC, erf_open, "erf" }, - { "IPfix", OPEN_INFO_HEURISTIC, ipfix_open, "pfx;ipfix" }, - { "K12 Text", OPEN_INFO_HEURISTIC, k12text_open, "txt" }, - { "Peek Classic", OPEN_INFO_HEURISTIC, peekclassic_open, "pkt;tpc;apc;wpz" }, - { "PPP Dump", OPEN_INFO_HEURISTIC, pppdump_open, NULL }, - { "iSeries", OPEN_INFO_HEURISTIC, iseries_open, "txt" }, - { "i4btrace", OPEN_INFO_HEURISTIC, i4btrace_open, NULL }, - { "Mp2t", OPEN_INFO_HEURISTIC, mp2t_open, "ts;mpg" }, - { "Csids", OPEN_INFO_HEURISTIC, csids_open, NULL }, - { "VMS", OPEN_INFO_HEURISTIC, vms_open, "txt" }, - { "Cosine", OPEN_INFO_HEURISTIC, cosine_open, "txt" }, - { "Hcidump", OPEN_INFO_HEURISTIC, hcidump_open, NULL }, - { "Commview", OPEN_INFO_HEURISTIC, commview_open, "ncf" }, - { "Nstrace", OPEN_INFO_HEURISTIC, nstrace_open, "txt" }, + { "Netscreen", OPEN_INFO_HEURISTIC, netscreen_open, "txt", NULL }, + { "ERF", OPEN_INFO_HEURISTIC, erf_open, "erf", NULL }, + { "IPfix", OPEN_INFO_HEURISTIC, ipfix_open, "pfx;ipfix",NULL }, + { "K12 Text", OPEN_INFO_HEURISTIC, k12text_open, "txt", NULL }, + { "Peek Classic", OPEN_INFO_HEURISTIC, peekclassic_open, "pkt;tpc;apc;wpz", NULL }, + { "PPP Dump", OPEN_INFO_HEURISTIC, pppdump_open, NULL, NULL }, + { "iSeries", OPEN_INFO_HEURISTIC, iseries_open, "txt", NULL }, + { "i4btrace", OPEN_INFO_HEURISTIC, i4btrace_open, NULL, NULL }, + { "Mp2t", OPEN_INFO_HEURISTIC, mp2t_open, "ts;mpg", NULL }, + { "Csids", OPEN_INFO_HEURISTIC, csids_open, NULL, NULL }, + { "VMS", OPEN_INFO_HEURISTIC, vms_open, "txt", NULL }, + { "Cosine", OPEN_INFO_HEURISTIC, cosine_open, "txt", NULL }, + { "Hcidump", OPEN_INFO_HEURISTIC, hcidump_open, NULL, NULL }, + { "Commview", OPEN_INFO_HEURISTIC, commview_open, "ncf", NULL }, + { "Nstrace", OPEN_INFO_HEURISTIC, nstrace_open, "txt", NULL }, /* ASCII trace files from Telnet sessions. */ - { "Ascend", OPEN_INFO_HEURISTIC, ascend_open, "txt" }, - { "Toshiba", OPEN_INFO_HEURISTIC, toshiba_open, "txt" }, + { "Ascend", OPEN_INFO_HEURISTIC, ascend_open, "txt", NULL }, + { "Toshiba", OPEN_INFO_HEURISTIC, toshiba_open, "txt", NULL }, /* Extremely weak heuristics - put them at the end. */ - { "VWR", OPEN_INFO_HEURISTIC, vwr_open, "vwr" }, - { "Camins", OPEN_INFO_HEURISTIC, camins_open, "camins" }, - { NULL, 0, NULL, NULL} + { "VWR", OPEN_INFO_HEURISTIC, vwr_open, "vwr", NULL }, + { "Camins", OPEN_INFO_HEURISTIC, camins_open, "camins", NULL }, + { NULL, 0, NULL, NULL, NULL } }; + +/* this is only used to build the dynamic array on load, do NOT use this + * for anything else, because the size of the actual array will change if + * Lua scripts register a new file reader. + */ #define N_OPEN_INFO_ROUTINES ((sizeof open_info_base / sizeof open_info_base[0])) +static GArray *open_info_arr = NULL; + +/* this always points to the top of the created array */ struct open_info *open_routines = NULL; -static GArray *open_info_arr = NULL; +/* this points to the first OPEN_INFO_HEURISTIC type in the array */ +static guint heuristic_open_routine_idx = 0; + +static void set_heuristic_routine(void) { + guint i; + g_assert(open_info_arr != NULL); + + for (i = 0; i < open_info_arr->len - 1; i++) { + if (open_routines[i].type == OPEN_INFO_HEURISTIC) { + heuristic_open_routine_idx = i; + break; + } + /* sanity check */ + g_assert(open_routines[i].type == OPEN_INFO_MAGIC); + } + + g_assert(heuristic_open_routine_idx > 0); +} void init_open_routines(void) { @@ -382,15 +407,87 @@ void init_open_routines(void) { g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES); - open_routines = (struct open_info *) open_info_arr->data; + open_routines = (struct open_info *)(void*) open_info_arr->data; + set_heuristic_routine(); +} + +/* Registers a new file reader - currently only called by wslua code for Lua readers. + * If first_routine is true, it's added before other readers of its type (magic or heuristic). + * Also, it checks for an existing reader of the same name and errors if it finds one; if + * you want to handle that condition more gracefully, call wtap_has_open_info() first. + */ +void wtap_register_open_info(const struct open_info *oi, const gboolean first_routine) { + init_open_routines(); + + if (!oi || !oi->name) { + g_error("No open_info name given to register"); + return; + } + + /* verify name doesn't already exist */ + if (wtap_has_open_info(oi->name)) { + g_error("Name given to register_open_info already exists"); + return; + } + + /* if it's magic and first, prepend it; if it's heuristic and not first, + append it; if it's anything else, stick it in the middle */ + if (first_routine && oi->type == OPEN_INFO_MAGIC) { + g_array_prepend_val(open_info_arr, *oi); + } else if (!first_routine && oi->type == OPEN_INFO_HEURISTIC) { + g_array_append_val(open_info_arr, *oi); + } else { + g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi); + } + + open_routines = (struct open_info *)(void*) open_info_arr->data; + set_heuristic_routine(); } -void wtap_register_open_info(const struct open_info *oi) { +/* De-registers a file reader by removign it from the GArray based on its name. + * This function must NOT be called during wtap_open_offline(), since it changes the array. + * Note: this function will error if it doesn't find the given name; if you want to handle + * that condition more gracefully, call wtap_has_open_info() first. + */ +void wtap_deregister_open_info(const gchar *name) { + guint i; init_open_routines(); - g_array_append_val(open_info_arr, oi); + if (!name) { + g_error("Missing open_info name to de-register"); + return; + } + + for (i = 0; i < open_info_arr->len - 1; i++) { + if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) { + open_info_arr = g_array_remove_index(open_info_arr, i); + set_heuristic_routine(); + return; + } + } - open_routines = (struct open_info *) open_info_arr->data; + g_error("deregister_open_info: name not found"); +} + +/* Determines if a open routine short name already exists + */ +gboolean wtap_has_open_info(const gchar *name) { + guint i; + init_open_routines(); + + if (!name) { + g_error("No name given to wtap_has_open_info!"); + return FALSE; + } + + + for (i = 0; i < open_info_arr->len - 1; i++) { + if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) { + return TRUE; + } + } + + return FALSE; } /* @@ -527,6 +624,11 @@ static char *get_file_extension(const char *pathname) return extensionp; } +/* TODO: this is called every time a file is checked for matching heuristic, + * which means just clicking on a file in the open dialog may call this thing + * twice... for *each* open_routine. That's silly, since this info never changes. + * It would be better to create this list in the lookup array on initialization. + */ static gboolean heuristic_uses_extension(unsigned int i, const char *extension) { gchar **extensions_set, **extensionp; @@ -686,6 +788,7 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char wth->subtype_close = NULL; wth->tsprecision = WTAP_FILE_TSPREC_USEC; wth->priv = NULL; + wth->wslua_data = NULL; if (wth->random_fh) { wth->fast_seek = g_ptr_array_new(); @@ -694,7 +797,8 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char file_set_random_access(wth->random_fh, TRUE, wth->fast_seek); } - if (type != 0 && type <= open_info_arr->len + 1) { + /* 'type' is 1 greater than the array index */ + if (type != 0 && type <= open_info_arr->len) { int result; if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { @@ -703,6 +807,12 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char return NULL; } + /* Set wth with wslua data if any - this is how we pass the data + * to the file reader, kinda like the priv member but not free'd later. + * It's ok for this to copy a NULL. + */ + wth->wslua_data = open_routines[type - 1].wslua_data; + result = (*open_routines[type - 1].open_routine)(wth, err, err_info); switch (result) { @@ -730,14 +840,18 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char to start reading at the beginning. Initialize the data offset while we're at it. */ - if (open_routines[i].type != OPEN_INFO_MAGIC) continue; - if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { /* I/O error - give up */ wtap_close(wth); return NULL; } + /* Set wth with wslua data if any - this is how we pass the data + * to the file reader, kinda like the priv member but not free'd later. + * It's ok for this to copy a NULL. + */ + wth->wslua_data = open_routines[i].wslua_data; + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { case -1: @@ -755,14 +869,13 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char } } + /* Does this file's name have an extension? */ extension = get_file_extension(filename); if (extension != NULL) { /* Yes - try the heuristic types that use that extension first. */ - for (i = 0; i < open_info_arr->len - 1; i++) { - if (open_routines[i].type != OPEN_INFO_HEURISTIC) continue; + for (i = heuristic_open_routine_idx; i < open_info_arr->len - 1; i++) { /* Does this type use that extension? */ - if (heuristic_uses_extension(i, extension)) { /* Yes. */ if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { @@ -772,6 +885,11 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char return NULL; } + /* Set wth with wslua data if any - this is how we pass the data + * to the file reader, kind of like priv but not free'd later. + */ + wth->wslua_data = open_routines[i].wslua_data; + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { @@ -794,8 +912,7 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char } /* Now try the ones that don't use it. */ - for (i = 0; i < open_info_arr->len - 1; i++) { - if (open_routines[i].type != OPEN_INFO_HEURISTIC) continue; + for (i = heuristic_open_routine_idx; i < open_info_arr->len - 1; i++) { /* Does this type use that extension? */ if (!heuristic_uses_extension(i, extension)) { /* No. */ @@ -806,6 +923,11 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char return NULL; } + /* Set wth with wslua data if any - this is how we pass the data + * to the file reader, kind of like priv but not free'd later. + */ + wth->wslua_data = open_routines[i].wslua_data; + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { @@ -829,8 +951,7 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char g_free(extension); } else { /* No - try all the heuristics types in order. */ - for (i = 0; i < open_info_arr->len - 1; i++) { - if (open_routines[i].type != OPEN_INFO_HEURISTIC) continue; + for (i = heuristic_open_routine_idx; i < open_info_arr->len - 1; i++) { if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { /* I/O error - give up */ @@ -838,6 +959,11 @@ wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char return NULL; } + /* Set wth with wslua data if any - this is how we pass the data + * to the file reader, kind of like priv but not free'd later. + */ + wth->wslua_data = open_routines[i].wslua_data; + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { case -1: @@ -963,338 +1089,338 @@ static const struct file_type_subtype_info dump_open_table_base[] = { /* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */ { NULL, NULL, NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAP */ /* Gianluca Varenni suggests that we add "deprecated" to the description. */ { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp", FALSE, FALSE, 0, - libpcap_dump_can_write_encap, libpcap_dump_open }, + libpcap_dump_can_write_encap, libpcap_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAPNG */ { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar", FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET, - pcapng_dump_can_write_encap, pcapng_dump_open }, + pcapng_dump_can_write_encap, pcapng_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */ { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp", FALSE, FALSE, 0, - libpcap_dump_can_write_encap, libpcap_dump_open }, + libpcap_dump_can_write_encap, libpcap_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */ { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */ { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp", FALSE, FALSE, 0, - libpcap_dump_can_write_encap, libpcap_dump_open }, + libpcap_dump_can_write_encap, libpcap_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */ { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp", FALSE, FALSE, 0, - libpcap_dump_can_write_encap, libpcap_dump_open }, + libpcap_dump_can_write_encap, libpcap_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */ { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp", FALSE, FALSE, 0, - libpcap_dump_can_write_encap, libpcap_dump_open }, + libpcap_dump_can_write_encap, libpcap_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */ { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp", FALSE, FALSE, 0, - libpcap_dump_can_write_encap, libpcap_dump_open }, + libpcap_dump_can_write_encap, libpcap_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */ { "InfoVista 5View capture", "5views", "5vw", NULL, TRUE, FALSE, 0, - _5views_dump_can_write_encap, _5views_dump_open }, + _5views_dump_can_write_encap, _5views_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0 */ { "AIX iptrace 1.0", "iptrace_1", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */ { "AIX iptrace 2.0", "iptrace_2", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_BER */ { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */ { "Bluetooth HCI dump", "hcidump", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */ { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL, FALSE, FALSE, 0, - catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open }, + catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_OLD */ { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL, TRUE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */ { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL, TRUE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_COSINE */ { "CoSine IPSX L2 capture", "cosine", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */ { "CSIDS IPLog", "csids", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */ { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL}, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_ERF */ { "Endace ERF capture", "erf", "erf", NULL, FALSE, FALSE, 0, - erf_dump_can_write_encap, erf_dump_open }, + erf_dump_can_write_encap, erf_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_EYESDN */ { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL, FALSE, FALSE, 0, - eyesdn_dump_can_write_encap, eyesdn_dump_open }, + eyesdn_dump_can_write_encap, eyesdn_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETTL */ { "HP-UX nettl trace", "nettl", "trc0", "trc1", FALSE, FALSE, 0, - nettl_dump_can_write_encap, nettl_dump_open }, + nettl_dump_can_write_encap, nettl_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_ISERIES */ { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */ { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */ { "I4B ISDN trace", "i4btrace", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */ { "Lucent/Ascend access server trace", "ascend", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */ { "Microsoft NetMon 1.x", "netmon1", "cap", NULL, TRUE, FALSE, 0, - netmon_dump_can_write_encap_1_x, netmon_dump_open }, + netmon_dump_can_write_encap_1_x, netmon_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x */ { "Microsoft NetMon 2.x", "netmon2", "cap", NULL, TRUE, FALSE, 0, - netmon_dump_can_write_encap_2_x, netmon_dump_open }, + netmon_dump_can_write_encap_2_x, netmon_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED */ { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc", FALSE, FALSE, 0, - ngsniffer_dump_can_write_encap, ngsniffer_dump_open }, + ngsniffer_dump_can_write_encap, ngsniffer_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED */ { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */ { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL, TRUE, FALSE, 0, - netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 }, + netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_2_00x */ { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz", TRUE, FALSE, 0, - netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 }, + netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS */ { "Network Instruments Observer", "niobserver", "bfr", NULL, FALSE, FALSE, 0, - network_instruments_dump_can_write_encap, network_instruments_dump_open }, + network_instruments_dump_can_write_encap, network_instruments_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */ { "Novell LANalyzer","lanalyzer", "tr1", NULL, TRUE, FALSE, 0, - lanalyzer_dump_can_write_encap, lanalyzer_dump_open }, + lanalyzer_dump_can_write_encap, lanalyzer_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */ { "pppd log (pppdump format)", "pppd", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */ { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */ { "Sun snoop", "snoop", "snoop", "cap", FALSE, FALSE, 0, - snoop_dump_can_write_encap, snoop_dump_open }, + snoop_dump_can_write_encap, snoop_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */ { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_VMS */ { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL}, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_K12 */ { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL, TRUE, FALSE, 0, - k12_dump_can_write_encap, k12_dump_open }, + k12_dump_can_write_encap, k12_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */ { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */ { "Visual Networks traffic capture", "visual", NULL, NULL, TRUE, FALSE, 0, - visual_dump_can_write_encap, visual_dump_open }, + visual_dump_can_write_encap, visual_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V56 */ { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */ { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */ { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_MPEG */ { "MPEG", "mpeg", "mpeg", "mpg;mp3", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT */ { "K12 text file", "k12text", "txt", NULL, FALSE, FALSE, 0, - k12text_dump_can_write_encap, k12text_dump_open }, + k12text_dump_can_write_encap, k12text_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */ { "NetScreen snoop text file", "netscreen", "txt", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */ { "TamoSoft CommView", "commview", "ncf", NULL, FALSE, FALSE, 0, - commview_dump_can_write_encap, commview_dump_open }, + commview_dump_can_write_encap, commview_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */ { "Symbian OS btsnoop", "btsnoop", "log", NULL, FALSE, FALSE, 0, - btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 }, + btsnoop_dump_can_write_encap, btsnoop_dump_open_h4, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_TNEF */ { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */ { "Gammu DCT3 trace", "dct3trace", "xml", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */ { "PacketLogger", "pklg", "pklg", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */ { "Daintree SNA", "dsna", "dcf", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */ { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL, TRUE, FALSE, 0, - nstrace_10_dump_can_write_encap, nstrace_dump_open }, + nstrace_10_dump_can_write_encap, nstrace_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0 */ { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL, TRUE, FALSE, 0, - nstrace_20_dump_can_write_encap, nstrace_dump_open }, + nstrace_20_dump_can_write_encap, nstrace_dump_open, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */ { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */ { "IPFIX File Format", "ipfix", "pfx", "ipfix", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_ENCAP_MIME */ { "MIME File Format", "mime", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */ { "Aethra .aps file", "aethra", "aps", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */ { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg", FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */ { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */ { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */ { "CAM Inspector file", "camins", "camins", NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */ { "STANAG 4607 Format", "stanag4607", NULL, NULL, FALSE, FALSE, 0, - NULL, NULL }, + NULL, NULL, NULL }, /* WTAP_FILE_NETSCALER_3_0 */ { "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL, TRUE, FALSE, 0, - nstrace_30_dump_can_write_encap, nstrace_dump_open } + nstrace_30_dump_can_write_encap, nstrace_dump_open, NULL } }; @@ -1315,14 +1441,77 @@ static void init_file_types_subtypes(void) { dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data; } -int wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi) { +/* if subtype is WTAP_FILE_TYPE_SUBTYPE_UNKNOWN, then create a new subtype as well as register it, else replace the + existing entry in that spot */ +int wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const int subtype) { + struct file_type_subtype_info* finfo = NULL; init_file_types_subtypes(); - g_array_append_val(dump_open_table_arr,*fi); + if (!fi || !fi->name || !fi->short_name || subtype > wtap_num_file_types_subtypes) { + g_error("no file type info or invalid file type to register"); + return subtype; + } - dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data; + /* do we want a new registration? */ + if (subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) { + /* register a new one; first verify there isn't one named this already */ + if (wtap_short_string_to_file_type_subtype(fi->short_name) > -1 ) { + g_error("file type short name already exists"); + return subtype; + } + + g_array_append_val(dump_open_table_arr,*fi); + + dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data; + + return wtap_num_file_types_subtypes++; + } - return wtap_num_file_types_subtypes++; + /* re-register an existing one - verify the short names do match (sanity check really) */ + if (!dump_open_table[subtype].short_name || strcmp(dump_open_table[subtype].short_name,fi->short_name) != 0) { + g_error("invalid file type name given to register"); + return subtype; + } + + /* yes, we're going to cast to change its const-ness */ + finfo = (struct file_type_subtype_info*)(&dump_open_table[subtype]); + /*finfo->name = fi->name;*/ + /*finfo->short_name = fi->short_name;*/ + finfo->default_file_extension = fi->default_file_extension; + finfo->additional_file_extensions = fi->additional_file_extensions; + finfo->writing_must_seek = fi->writing_must_seek; + finfo->has_name_resolution = fi->has_name_resolution; + finfo->supported_comment_types = fi->supported_comment_types; + finfo->can_write_encap = fi->can_write_encap; + finfo->dump_open = fi->dump_open; + finfo->wslua_info = fi->wslua_info; + + return subtype; +} + +/* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry. + */ +void wtap_deregister_file_type_subtype(const int subtype) { + struct file_type_subtype_info* finfo = NULL; + + if (subtype < 0 || subtype >= wtap_num_file_types_subtypes) { + g_error("invalid file type to de-register"); + return; + } + + /* yes, we're going to cast to change its const-ness */ + finfo = (struct file_type_subtype_info*)(&dump_open_table[subtype]); + /* unfortunately, it's not safe to null-out the name or short_name; bunch of other code doesn't guard aainst that, afaict */ + /*finfo->name = NULL;*/ + /*finfo->short_name = NULL;*/ + finfo->default_file_extension = NULL; + finfo->additional_file_extensions = NULL; + finfo->writing_must_seek = FALSE; + finfo->has_name_resolution = FALSE; + finfo->supported_comment_types = 0; + finfo->can_write_encap = NULL; + finfo->dump_open = NULL; + finfo->wslua_info = NULL; } int wtap_get_num_file_types_subtypes(void) @@ -1352,12 +1541,27 @@ wtap_dump_file_encap_type(const GArray *file_encaps) static gboolean wtap_dump_can_write_encap(int filetype, int encap) { + int result = 0; + if (filetype < 0 || filetype >= wtap_num_file_types_subtypes || dump_open_table[filetype].can_write_encap == NULL) return FALSE; - if ((*dump_open_table[filetype].can_write_encap)(encap) != 0) - return FALSE; + result = (*dump_open_table[filetype].can_write_encap)(encap); + + if (result != 0) { + /* if the err said to check wslua's can_write_encap, try that */ + if (result == WTAP_ERR_CHECK_WSLUA + && dump_open_table[filetype].wslua_info != NULL + && dump_open_table[filetype].wslua_info->wslua_can_write_encap != NULL) { + + result = (*dump_open_table[filetype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[filetype].wslua_info->wslua_data); + + } + + if (result != 0) + return FALSE; + } return TRUE; } @@ -1898,6 +2102,15 @@ static gboolean wtap_dump_open_check(int file_type_subtype, int encap, gboolean /* OK, we know how to write that type; can we write the specified encapsulation type? */ *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap); + /* if the err said to check wslua's can_write_encap, try that */ + if (*err == WTAP_ERR_CHECK_WSLUA + && dump_open_table[file_type_subtype].wslua_info != NULL + && dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) { + + *err = (*dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[file_type_subtype].wslua_info->wslua_data); + + } + if (*err != 0) return FALSE; @@ -1907,10 +2120,6 @@ static gboolean wtap_dump_open_check(int file_type_subtype, int encap, gboolean return FALSE; } - *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap); - if (*err != 0) - return FALSE; - /* All systems go! */ return TRUE; } @@ -1930,6 +2139,7 @@ static wtap_dumper* wtap_dump_alloc_wdh(int file_type_subtype, int encap, int sn wdh->snaplen = snaplen; wdh->encap = encap; wdh->compressed = compressed; + wdh->wslua_data = NULL; return wdh; } @@ -1959,6 +2169,12 @@ static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, g return FALSE; } + /* Set wdh with wslua data if any - this is how we pass the data + * to the file writer. + */ + if (dump_open_table[file_type_subtype].wslua_info) + wdh->wslua_data = dump_open_table[file_type_subtype].wslua_info->wslua_data; + /* Now try to open the file for writing. */ if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) { return FALSE; diff --git a/wiretap/file_wrappers.c b/wiretap/file_wrappers.c index 1bfccf0570..0f30493ee6 100644 --- a/wiretap/file_wrappers.c +++ b/wiretap/file_wrappers.c @@ -1207,6 +1207,53 @@ file_read(void *buf, unsigned int len, FILE_T file) return (int)got; } +/* + * XXX - this *peeks* at next byte, not a character. + */ +int +file_peekc(FILE_T file) +{ + int ret = 0; + + /* check that we're reading and that there's no error */ + if (file->err) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (file->have) { + return *(file->next); + } + + /* process a skip request */ + if (file->seek_pending) { + file->seek_pending = FALSE; + if (gz_skip(file, file->skip) == -1) + return -1; + } + /* if we processed a skip request, there may be data in the buffer, + * or an error could have occured; likewise if we didn't do seek but + * now call fill_out_buffer, the errors can occur. So we do this while + * loop to check before and after - this is basically the logic from + * file_read() but only for peeking not consuming a byte + */ + while (1) { + if (file->have) { + return *(file->next); + } + else if (file->err) { + return -1; + } + else if (file->eof && file->avail_in == 0) { + return -1; + } + else if (fill_out_buffer(file) == -1) { + return -1; + } + } + /* it's actually impossible to get here */ + return ret; +} + /* * XXX - this gets a byte, not a character. */ diff --git a/wiretap/file_wrappers.h b/wiretap/file_wrappers.h index c32d380180..7f3cdc4205 100644 --- a/wiretap/file_wrappers.h +++ b/wiretap/file_wrappers.h @@ -22,7 +22,7 @@ #define __WTAP_FILE_WRAPPERS_H__ #include -#include +#include "wtap.h" #include #include "ws_symbol_export.h" @@ -34,8 +34,9 @@ extern gboolean file_skip(FILE_T file, gint64 delta, int *err); WS_DLL_PUBLIC gint64 file_tell(FILE_T stream); extern gint64 file_tell_raw(FILE_T stream); extern int file_fstat(FILE_T stream, ws_statb64 *statb, int *err); -extern gboolean file_iscompressed(FILE_T stream); +WS_DLL_PUBLIC gboolean file_iscompressed(FILE_T stream); WS_DLL_PUBLIC int file_read(void *buf, unsigned int count, FILE_T file); +WS_DLL_PUBLIC int file_peekc(FILE_T stream); WS_DLL_PUBLIC int file_getc(FILE_T stream); WS_DLL_PUBLIC char *file_gets(char *buf, int len, FILE_T stream); WS_DLL_PUBLIC int file_eof(FILE_T stream); diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h index 8c186b40ec..1d47f25423 100644 --- a/wiretap/wtap-int.h +++ b/wiretap/wtap-int.h @@ -58,7 +58,8 @@ struct wtap { guint number_of_interfaces; /**< The number of interfaces a capture was made on, number of IDB:s in a pcapng file or equivalent(?)*/ GArray *interface_data; /**< An array holding the interface data from pcapng IDB:s or equivalent(?)*/ - void *priv; + void *priv; /* this one holds per-file state and is free'd automatically by wtap_close() */ + void *wslua_data; /* this one holds wslua state info and is not free'd */ subtype_read_func subtype_read; subtype_seek_read_func subtype_seek_read; @@ -97,7 +98,8 @@ struct wtap_dumper { gboolean compressed; gint64 bytes_dumped; - void *priv; + void *priv; /* this one holds per-file state and is free'd automatically by wtap_dump_close() */ + void *wslua_data; /* this one holds wslua state info and is not free'd */ subtype_write_func subtype_write; subtype_close_func subtype_close; @@ -111,10 +113,10 @@ struct wtap_dumper { GArray *interface_data; /**< An array holding the interface data from pcapng IDB:s or equivalent(?) NULL if not present.*/ }; -gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, +WS_DLL_PUBLIC gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err); -gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err); -gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err); +WS_DLL_PUBLIC gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err); +WS_DLL_PUBLIC gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err); extern gint wtap_num_file_types; @@ -280,6 +282,7 @@ GSList *wtap_get_compressed_file_extensions(void); * header, so if we get an EOF trying to read the packet data, the file * has been cut short, even if the read didn't read any data at all.) */ +WS_DLL_PUBLIC gboolean wtap_read_packet_bytes(FILE_T fh, Buffer *buf, guint length, int *err, gchar **err_info); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index f61b51f111..d0bc4747cb 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1134,6 +1134,22 @@ typedef struct wtap_dumper wtap_dumper; typedef struct wtap_reader *FILE_T; +/* Similar to the wtap_open_routine_info for open routines, the following + * wtap_wslua_file_info struct is used by wslua code for Lua-based file writers. + * + * This concept is necessary because when wslua goes to invoke the + * registered dump/write_open routine callback in Lua, it needs the ref number representing + * the hooked function inside Lua. This will be stored in the thing pointed to + * by the void* data here. This 'data' pointer will be copied into the + * wtap_dumper struct's 'void* data' member when calling the dump_open function, + * which is how wslua finally retrieves it. Unlike wtap_dumper's 'priv' member, its + * 'data' member is not free'd in wtap_dump_close(). + */ +typedef struct wtap_wslua_file_info { + int (*wslua_can_write_encap)(int, void*); /* a can_write_encap func for wslua uses */ + void* wslua_data; /* holds the wslua data */ +} wtap_wslua_file_info_t; + /* * For registering extensions used for capture file formats. * @@ -1218,6 +1234,7 @@ struct open_info { int type; wtap_open_routine_t open_routine; const char *extensions; + void* wslua_data; /* should be NULL for C-code file readers */ }; WS_DLL_PUBLIC struct open_info *open_routines; @@ -1264,6 +1281,10 @@ struct file_type_subtype_info { /* the function to open the capture file for writing */ /* should be NULL is this file type don't have write support */ int (*dump_open)(wtap_dumper *, int *); + + /* if can_write_encap returned WTAP_ERR_CHECK_WSLUA, then this is used instead */ + /* this should be NULL for everyone except Lua-based file writers */ + wtap_wslua_file_info_t *wslua_info; }; #define WTAP_TYPE_AUTO 0 @@ -1488,18 +1509,21 @@ WS_DLL_PUBLIC void register_all_wiretap_modules(void); WS_DLL_PUBLIC void wtap_register_file_type_extension(const struct file_extension_info *ei); -#if 0 + WS_DLL_PUBLIC -void wtap_register_magic_number_open_routine(wtap_open_routine_t open_routine); +void wtap_register_open_info(const struct open_info *oi, const gboolean first_routine); WS_DLL_PUBLIC -void wtap_register_heuristic_open_info(const struct heuristic_open_info *oi); -#endif +gboolean wtap_has_open_info(const gchar *name); WS_DLL_PUBLIC -void wtap_register_open_info(const struct open_info *oi); +void wtap_deregister_open_info(const gchar *name); + WS_DLL_PUBLIC unsigned int open_info_name_to_type(const char *name); WS_DLL_PUBLIC -int wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi); +int wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const int subtype); +WS_DLL_PUBLIC +void wtap_deregister_file_type_subtype(const int file_type_subtype); + WS_DLL_PUBLIC int wtap_register_encap_type(const char* name, const char* short_name); @@ -1582,6 +1606,10 @@ int wtap_register_encap_type(const char* name, const char* short_name); /** Packet being written is larger than we support; do not use when reading, use WTAP_ERR_BAD_FILE instead */ +#define WTAP_ERR_CHECK_WSLUA -25 + /** Not really an error: the file type being checked is from a Lua + plugin, so that the code will call wslua_can_write_encap() instead if it gets this */ + #ifdef __cplusplus } #endif /* __cplusplus */ -- cgit v1.2.3