Revert "UNUSED enc_key_id_{equal,hash}"
[wireshark-sm.git] / wiretap / file_access.c
blob3cb187c3fd7c2ca474de4d8afa3677eca2c4cf28
1 /* file_access.c
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
9 #include "config.h"
10 #define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP
11 #include "wtap-int.h"
13 #include <string.h>
14 #include <stdlib.h>
16 #include <errno.h>
18 #include <wsutil/file_util.h>
19 #include <wsutil/tempfile.h>
20 #ifdef HAVE_PLUGINS
21 #include <wsutil/plugins.h>
22 #endif
23 #include <wsutil/ws_assert.h>
25 #include "wtap_modules.h"
26 #include "file_wrappers.h"
27 #include "required_file_handlers.h"
28 #include <wsutil/buffer.h>
29 #include <wsutil/str_util.h>
31 #include "lanalyzer.h"
32 #include "ngsniffer.h"
33 #include "radcom.h"
34 #include "ascendtext.h"
35 #include "nettl.h"
36 #include "libpcap.h"
37 #include "snoop.h"
38 #include "iptrace.h"
39 #include "iseries.h"
40 #include "netmon.h"
41 #include "netxray.h"
42 #include "toshiba.h"
43 #include "eyesdn.h"
44 #include "i4btrace.h"
45 #include "csids.h"
46 #include "pppdump.h"
47 #include "peekclassic.h"
48 #include "peektagged.h"
49 #include "vms.h"
50 #include "dbs-etherwatch.h"
51 #include "visual.h"
52 #include "cosine.h"
53 #include "5views.h"
54 #include "erf.h"
55 #include "hcidump.h"
56 #include "logcat.h"
57 #include "logcat_text.h"
58 #include "json.h"
59 #include "observer.h"
60 #include "k12.h"
61 #include "ber.h"
62 #include "catapult_dct2000.h"
63 #include "mp4.h"
64 #include "mp2t.h"
65 #include "mpeg.h"
66 #include "netscreen.h"
67 #include "commview.h"
68 #include "pcapng.h"
69 #include "aethra.h"
70 #include "btsnoop.h"
71 #include "tnef.h"
72 #include "dct3trace.h"
73 #include "packetlogger.h"
74 #include "daintree-sna.h"
75 #include "netscaler.h"
76 #include "mime_file.h"
77 #include "ipfix.h"
78 #include "vwr.h"
79 #include "camins.h"
80 #include "stanag4607.h"
81 #include "capsa.h"
82 #include "nettrace_3gpp_32_423.h"
83 #include "mplog.h"
84 #include "dpa400.h"
85 #include "rfc7468.h"
86 #include "ruby_marshal.h"
87 #include "systemd_journal.h"
88 #include "log3gpp.h"
89 #include "candump.h"
90 #include "busmaster.h"
91 #include "cllog.h"
92 #include "blf.h"
93 #include "etl.h"
94 #include "eri_enb_log.h"
95 #include "autosar_dlt.h"
96 #include "rtpdump.h"
97 #include "ems.h"
100 * Add an extension, and all compressed versions thereof if requested,
101 * to a GSList of extensions.
103 static GSList *
104 add_extensions(GSList *extensions, const char *extension,
105 GSList *compression_type_extensions)
108 * Add the specified extension.
110 extensions = g_slist_prepend(extensions, g_strdup(extension));
113 * Add whatever compressed versions we were supplied.
115 for (GSList *compression_type_extension = compression_type_extensions;
116 compression_type_extension != NULL;
117 compression_type_extension = g_slist_next(compression_type_extension)) {
118 extensions = g_slist_prepend(extensions,
119 ws_strdup_printf("%s.%s", extension,
120 (const char *)compression_type_extension->data));
123 return extensions;
127 * File types that can be identified by file extensions.
129 * These are used in file open dialogs to offer choices of extensions
130 * for which to filter. Note that the first field can list more than
131 * one type of file, because, for example, ".cap" is a popular
132 * extension used by a number of capture file types.
134 * File types that *don't* have a file extension used for them should
135 * *not* be placed here; if there's nothing to put in the last field
136 * of the structure, don't put an entry here, not even one with an
137 * empty string for the extensions list.
139 * All added file types, regardless of extension or lack thereof,
140 * must also be added open_info_base[] below.
142 static const struct file_extension_info file_type_extensions_base[] = {
143 { "Wireshark/tcpdump/... - pcap", true, "pcap;cap;dmp" },
144 { "Wireshark/... - pcapng", true, "pcapng;scap;ntar" },
145 { "Network Monitor, Surveyor, NetScaler", true, "cap" },
146 { "Sun snoop", true, "snoop" },
147 { "Microsoft ETL", true, "etl" },
148 { "InfoVista 5View capture", true, "5vw" },
149 { "Sniffer (DOS)", true, "cap;enc;trc;fdc;syc" },
150 { "Cinco NetXRay, Sniffer (Windows)", true, "cap;caz" },
151 { "Endace ERF capture", true, "erf" },
152 { "EyeSDN USB S0/E1 ISDN trace format", true, "trc" },
153 { "HP-UX nettl trace", true, "trc0;trc1" },
154 { "Viavi Observer", true, "bfr" },
155 { "Colasoft Capsa", true, "cscpkt" },
156 { "Novell LANalyzer", true, "tr1" },
157 { "Tektronix K12xx 32-bit .rf5 format", true, "rf5" },
158 { "Savvius *Peek", true, "pkt;tpc;apc;wpz" },
159 { "Catapult DCT2000 trace (.out format)", true, "out" },
160 { "Micropross mplog", true, "mplog" },
161 { "TamoSoft CommView NCF", true, "ncf" },
162 { "TamoSoft CommView NCFX", true, "ncfx" },
163 { "Symbian OS btsnoop", true, "log" },
164 { "XML files (including Gammu DCT3 traces)", true, "xml" },
165 { "macOS PacketLogger", true, "pklg" },
166 { "Daintree SNA", true, "dcf" },
167 { "IPFIX File Format", true, "pfx;ipfix" },
168 { "Aethra .aps file", true, "aps" },
169 { "MPEG2 transport stream", true, "mp2t;ts;m2ts;mpg" },
170 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", true, "vwr" },
171 { "CAM Inspector file", true, "camins" },
172 { "BLF file", true, "blf" },
173 { "AUTOSAR DLT file", true, "dlt" },
174 { "MPEG files", false, "mpeg;mpg;mp3" },
175 { "Transport-Neutral Encapsulation Format", false, "tnef" },
176 { "JPEG/JFIF files", false, "jpg;jpeg;jfif" },
177 { "JavaScript Object Notation file", false, "json" },
178 { "MP4 file", false, "mp4" },
179 { "RTPDump file", false, "rtp;rtpdump" },
180 { "EMS file", false, "ems" },
183 #define N_FILE_TYPE_EXTENSIONS array_length(file_type_extensions_base)
185 static const struct file_extension_info* file_type_extensions;
187 static GArray* file_type_extensions_arr;
189 /* initialize the extensions array if it has not been initialized yet */
190 static void
191 init_file_type_extensions(void)
194 if (file_type_extensions_arr) return;
196 file_type_extensions_arr = g_array_new(false,true,sizeof(struct file_extension_info));
198 g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
200 file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
203 void
204 wtap_register_file_type_extension(const struct file_extension_info *ei)
206 init_file_type_extensions();
208 g_array_append_val(file_type_extensions_arr,*ei);
210 file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
214 wtap_get_num_file_type_extensions(void)
216 return file_type_extensions_arr->len;
219 const char *
220 wtap_get_file_extension_type_name(int extension_type)
222 return file_type_extensions[extension_type].name;
225 static GSList *
226 add_extensions_for_file_extensions_type(int extension_type, GSList *extensions,
227 GSList *compression_type_extensions)
229 char **extensions_set, **extensionp, *extension;
232 * Split the extension-list string into a set of extensions.
234 extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
235 ";", 0);
238 * Add each of those extensions to the list.
240 for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
241 extension = *extensionp;
244 * Add the extension, and all compressed variants
245 * of it.
247 extensions = add_extensions(extensions, extension,
248 compression_type_extensions);
251 g_strfreev(extensions_set);
252 return extensions;
255 /* Return a list of file extensions that are used by the specified file
256 * extension type.
258 * All strings in the list are allocated with g_malloc() and must be freed
259 * with g_free().
261 GSList *
262 wtap_get_file_extension_type_extensions(unsigned extension_type)
264 GSList *extensions, *compression_type_extensions;
266 if (extension_type >= file_type_extensions_arr->len)
267 return NULL; /* not a valid extension type */
269 extensions = NULL; /* empty list, to start with */
272 * Get compression-type extensions, if any.
274 compression_type_extensions = wtap_get_all_compression_type_extensions_list();
277 * Add all this file extension type's extensions, with compressed
278 * variants.
280 extensions = add_extensions_for_file_extensions_type(extension_type,
281 extensions, compression_type_extensions);
283 g_slist_free(compression_type_extensions);
285 return extensions;
289 * The open_file_* routines must return:
291 * WTAP_OPEN_ERROR on an I/O error;
293 * WTAP_OPEN_MINE if the file they're reading is one of the types
294 * it handles;
296 * WTAP_OPEN_NOT_MINE if the file they're reading isn't the type
297 * they're checking for.
299 * If the routine handles this type of file, it must set the "file_type"
300 * field in the "struct wtap" to the type of the file.
302 * Note that the routine does *not* have to free the private data pointer on
303 * error. The caller takes care of that by calling wtap_close on error.
304 * (See https://gitlab.com/wireshark/wireshark/-/issues/8518)
306 * However, the caller *does* have to free the private data pointer when
307 * returning WTAP_OPEN_NOT_MINE, since the next file type will be called
308 * and will likely just overwrite the pointer.
310 * The names are used in file open dialogs to select, for files that
311 * don't have magic numbers and that could potentially be files of
312 * more than one type based on the heuristics, a particular file
313 * type to interpret it as, if the file name has no extension, the
314 * extension isn't sufficient to determine the appropriate file type,
315 * or the extension is wrong.
317 * NOTE: when adding file formats to this list you may also want to add them
318 * to the following files so that the various desktop environments will
319 * know that Wireshark can open the file:
320 * 1) resources/freedesktop/org.wireshark.Wireshark-mime.xml (for freedesktop.org environments)
321 * 2) packaging/macosx/WiresharkInfo.plist.in (for macOS)
323 * If your file format has a commonly-used extension (e.g., ".pcap") then you
324 * should probably also add it to file_type_extensions_base[] (in this file),
325 * to the list of "<glob pattern=...>" entries for this file format in
326 * resources/freedesktop/org.wireshark.Wireshark-mime.xml, to the
327 * CFBundleTypeExtensions array for this file format in
328 * packaging/macosx/WiresharkInfo.plist, and to the PushFileExtensions macro
329 * in packaging/nsis/wireshark-common.nsh and the File Associations in
330 * packaging/wix/ComponentGroups.wxi (for Windows).
332 static const struct open_info open_info_base[] = {
333 /* Open routines that look for magic numbers */
334 { "Wireshark/tcpdump/... - pcap", OPEN_INFO_MAGIC, libpcap_open, NULL, NULL, NULL },
335 { "Wireshark/... - pcapng", OPEN_INFO_MAGIC, pcapng_open, NULL, NULL, NULL },
336 { "Sniffer (DOS)", OPEN_INFO_MAGIC, ngsniffer_open, NULL, NULL, NULL },
337 { "Snoop, Shomiti/Finisar Surveyor", OPEN_INFO_MAGIC, snoop_open, NULL, NULL, NULL },
338 { "AIX iptrace", OPEN_INFO_MAGIC, iptrace_open, NULL, NULL, NULL },
339 { "Microsoft Network Monitor", OPEN_INFO_MAGIC, netmon_open, NULL, NULL, NULL },
340 { "Cinco NetXray/Sniffer (Windows)", OPEN_INFO_MAGIC, netxray_open, NULL, NULL, NULL },
341 { "RADCOM WAN/LAN analyzer", OPEN_INFO_MAGIC, radcom_open, NULL, NULL, NULL },
342 { "HP-UX nettl trace", OPEN_INFO_MAGIC, nettl_open, NULL, NULL, NULL },
343 { "Visual Networks traffic capture", OPEN_INFO_MAGIC, visual_open, NULL, NULL, NULL },
344 { "InfoVista 5View capture", OPEN_INFO_MAGIC, _5views_open, NULL, NULL, NULL },
345 { "Viavi Observer", OPEN_INFO_MAGIC, observer_open, NULL, NULL, NULL },
346 { "Savvius tagged", OPEN_INFO_MAGIC, peektagged_open, NULL, NULL, NULL },
347 { "Colasoft Capsa", OPEN_INFO_MAGIC, capsa_open, NULL, NULL, NULL },
348 { "DBS Etherwatch (VMS)", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL, NULL, NULL },
349 { "Tektronix K12xx 32-bit .rf5 format", OPEN_INFO_MAGIC, k12_open, NULL, NULL, NULL },
350 { "Catapult DCT2000 trace (.out format)", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL, NULL, NULL },
351 { "Aethra .aps file", OPEN_INFO_MAGIC, aethra_open, NULL, NULL, NULL },
352 { "Symbian OS btsnoop", OPEN_INFO_MAGIC, btsnoop_open, "log", NULL, NULL },
353 { "EyeSDN USB S0/E1 ISDN trace format", OPEN_INFO_MAGIC, eyesdn_open, NULL, NULL, NULL },
354 { "Transport-Neutral Encapsulation Format", OPEN_INFO_MAGIC, tnef_open, NULL, NULL, NULL },
355 /* 3GPP TS 32.423 Trace must come before MIME Files as it's XML based*/
356 { "3GPP TS 32.423 Trace format", OPEN_INFO_MAGIC, nettrace_3gpp_32_423_file_open, NULL, NULL, NULL },
357 /* Gammu DCT3 trace must come before MIME files as it's XML based*/
358 { "Gammu DCT3 trace", OPEN_INFO_MAGIC, dct3trace_open, NULL, NULL, NULL },
359 { "BLF Logfile", OPEN_INFO_MAGIC, blf_open, NULL, NULL, NULL },
360 { "AUTOSAR DLT Logfile", OPEN_INFO_MAGIC, autosar_dlt_open, NULL, NULL, NULL },
361 { "RTPDump files", OPEN_INFO_MAGIC, rtpdump_open, NULL, NULL, NULL },
362 { "MIME Files Format", OPEN_INFO_MAGIC, mime_file_open, NULL, NULL, NULL },
363 { "Micropross mplog", OPEN_INFO_MAGIC, mplog_open, NULL, NULL, NULL },
364 { "Unigraf DPA-400 capture", OPEN_INFO_MAGIC, dpa400_open, NULL, NULL, NULL },
365 { "RFC 7468 files", OPEN_INFO_MAGIC, rfc7468_open, NULL, NULL, NULL },
367 /* Open routines that have no magic numbers and require heuristics. */
368 { "Microsoft ETL", OPEN_INFO_HEURISTIC, etl_open, "etl", NULL, NULL },
369 { "Novell LANalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1", NULL, NULL },
371 * PacketLogger must come before MPEG, because its files
372 * are sometimes grabbed by mpeg_open.
374 { "macOS PacketLogger", OPEN_INFO_HEURISTIC, packetlogger_open, "pklg", NULL, NULL },
375 /* Some MPEG files have magic numbers, others just have heuristics. */
376 { "MPEG", OPEN_INFO_HEURISTIC, mpeg_open, "mpeg;mpg;mp3", NULL, NULL },
377 { "Daintree SNA", OPEN_INFO_HEURISTIC, daintree_sna_open, "dcf", NULL, NULL },
378 { "STANAG 4607 Format", OPEN_INFO_HEURISTIC, stanag4607_open, NULL, NULL, NULL },
379 { "ASN.1 Basic Encoding Rules", OPEN_INFO_HEURISTIC, ber_open, NULL, NULL, NULL },
381 * I put NetScreen *before* erf, because there were some
382 * false positives with my test-files (Sake Blok, July 2007)
384 * I put VWR *after* ERF, because there were some cases where
385 * ERF files were misidentified as vwr files (Stephen
386 * Donnelly, August 2013; see bug 9054)
388 * I put VWR *after* Peek Classic, CommView, iSeries text,
389 * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler,
390 * because there were some cases where files of those types were
391 * misidentified as vwr files (Guy Harris, December 2013)
393 { "NetScreen snoop text file", OPEN_INFO_HEURISTIC, netscreen_open, "txt", NULL, NULL },
394 { "Endace ERF capture", OPEN_INFO_HEURISTIC, erf_open, "erf", NULL, NULL },
395 { "IPFIX File Format", OPEN_INFO_HEURISTIC, ipfix_open, "pfx;ipfix",NULL, NULL },
396 { "K12 text file", OPEN_INFO_HEURISTIC, k12text_open, "txt", NULL, NULL },
397 { "Savvius classic", OPEN_INFO_HEURISTIC, peekclassic_open, "pkt;tpc;apc;wpz", NULL, NULL },
398 { "pppd log (pppdump format)", OPEN_INFO_HEURISTIC, pppdump_open, NULL, NULL, NULL },
399 { "IBM iSeries comm. trace", OPEN_INFO_HEURISTIC, iseries_open, "txt", NULL, NULL },
400 { "I4B ISDN trace", OPEN_INFO_HEURISTIC, i4btrace_open, NULL, NULL, NULL },
401 { "MPEG2 transport stream", OPEN_INFO_HEURISTIC, mp2t_open, "mp2t;ts;mpg", NULL, NULL },
402 { "CSIDS IPLog", OPEN_INFO_HEURISTIC, csids_open, NULL, NULL, NULL },
403 { "TCPIPtrace (VMS)", OPEN_INFO_HEURISTIC, vms_open, "txt", NULL, NULL },
404 { "CoSine IPSX L2 capture", OPEN_INFO_HEURISTIC, cosine_open, "txt", NULL, NULL },
405 { "Bluetooth HCI dump", OPEN_INFO_HEURISTIC, hcidump_open, NULL, NULL, NULL },
406 { "TamoSoft CommView NCF", OPEN_INFO_HEURISTIC, commview_ncf_open, "ncf", NULL, NULL },
407 { "TamoSoft CommView NCFX", OPEN_INFO_HEURISTIC, commview_ncfx_open, "ncfx", NULL, NULL },
408 { "NetScaler", OPEN_INFO_HEURISTIC, nstrace_open, "cap", NULL, NULL },
409 { "Android Logcat Binary format", OPEN_INFO_HEURISTIC, logcat_open, "logcat", NULL, NULL },
410 { "Android Logcat Text formats", OPEN_INFO_HEURISTIC, logcat_text_open, "txt", NULL, NULL },
411 { "Candump log", OPEN_INFO_HEURISTIC, candump_open, NULL, NULL, NULL },
412 { "Busmaster log", OPEN_INFO_HEURISTIC, busmaster_open, NULL, NULL, NULL },
413 { "CSS Electronics CLX000 CAN log", OPEN_INFO_MAGIC, cllog_open, "txt", NULL, NULL },
414 { "Ericsson eNode-B raw log", OPEN_INFO_MAGIC, eri_enb_log_open, NULL, NULL, NULL },
415 { "Systemd Journal", OPEN_INFO_HEURISTIC, systemd_journal_open, "log;jnl;journal", NULL, NULL },
417 /* ASCII trace files from Telnet sessions. */
418 { "Lucent/Ascend access server trace", OPEN_INFO_HEURISTIC, ascend_open, "txt", NULL, NULL },
419 { "Toshiba Compact ISDN Router snoop", OPEN_INFO_HEURISTIC, toshiba_open, "txt", NULL, NULL },
421 { "EGNOS Message Server (EMS) file", OPEN_INFO_HEURISTIC, ems_open, "ems", NULL, NULL },
423 /* Extremely weak heuristics - put them at the end. */
424 { "Ixia IxVeriWave .vwr Raw Capture", OPEN_INFO_HEURISTIC, vwr_open, "vwr", NULL, NULL },
425 { "CAM Inspector file", OPEN_INFO_HEURISTIC, camins_open, "camins", NULL, NULL },
426 { "JavaScript Object Notation", OPEN_INFO_HEURISTIC, json_open, "json", NULL, NULL },
427 { "Ruby Marshal Object", OPEN_INFO_HEURISTIC, ruby_marshal_open, "", NULL, NULL },
428 { "3gpp phone log", OPEN_INFO_MAGIC, log3gpp_open, "log", NULL, NULL },
429 { "MP4 media file", OPEN_INFO_MAGIC, mp4_open, "mp4", NULL, NULL },
433 /* this is only used to build the dynamic array on load, do NOT use this
434 * for anything else, because the size of the actual array will change if
435 * Lua scripts register a new file reader.
437 #define N_OPEN_INFO_ROUTINES array_length(open_info_base)
439 static GArray *open_info_arr;
441 /* this always points to the top of the created array */
442 struct open_info *open_routines;
444 /* this points to the first OPEN_INFO_HEURISTIC type in the array */
445 static unsigned heuristic_open_routine_idx;
447 static void
448 set_heuristic_routine(void)
450 unsigned i;
451 ws_assert(open_info_arr != NULL);
453 for (i = 0; i < open_info_arr->len; i++) {
454 if (open_routines[i].type == OPEN_INFO_HEURISTIC) {
455 heuristic_open_routine_idx = i;
456 break;
458 /* sanity check */
459 ws_assert(open_routines[i].type == OPEN_INFO_MAGIC);
462 ws_assert(heuristic_open_routine_idx > 0);
465 void
466 init_open_routines(void)
468 unsigned int i;
469 struct open_info *i_open;
471 if (open_info_arr)
472 return;
474 open_info_arr = g_array_new(true,true,sizeof(struct open_info));
476 g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES);
478 open_routines = (struct open_info *)(void*) open_info_arr->data;
480 /* Populate the extensions_set list now */
481 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
482 if (i_open->extensions != NULL)
483 i_open->extensions_set = g_strsplit(i_open->extensions, ";", 0);
486 set_heuristic_routine();
490 * Registers a new file reader - currently only called by wslua code for
491 * Lua readers and by compiled file reader plugins.
493 * If first_routine is true, the reader added before other readers of its
494 * type (magic or heuristic). This should be done only in cases where
495 * this reader's open test must be performed early, to avoid false
496 * positives for other readers' tests treating files for this reader
497 * as being for another reader.
499 * XXX - given that there is no guarantee that registration routines will
500 * be called in a given order, all this really does is divide readers for
501 * a given type (magic or heuristic) into two categories, with open routines
502 * for readers in the first category (first_routine true) all being called
503 * before readers in the second category; it does not guarantee a particular
504 * total order for open routines.
506 * Checks for an existing reader of the same name and errors if it finds one;
507 * if you want to handle that condition more gracefully, call
508 * wtap_has_open_info() first.
510 void
511 wtap_register_open_info(struct open_info *oi, const bool first_routine)
513 if (!oi || !oi->name) {
514 ws_error("No open_info name given to register");
515 return;
518 /* verify name doesn't already exist */
519 if (wtap_has_open_info(oi->name)) {
520 ws_error("Name given to register_open_info already exists");
521 return;
524 if (oi->extensions != NULL)
525 oi->extensions_set = g_strsplit(oi->extensions, ";", 0);
527 /* if it's magic and first, prepend it; if it's heuristic and not first,
528 append it; if it's anything else, stick it in the middle */
529 if (first_routine && oi->type == OPEN_INFO_MAGIC) {
530 g_array_prepend_val(open_info_arr, *oi);
531 } else if (!first_routine && oi->type == OPEN_INFO_HEURISTIC) {
532 g_array_append_val(open_info_arr, *oi);
533 } else {
534 g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi);
537 open_routines = (struct open_info *)(void*) open_info_arr->data;
538 set_heuristic_routine();
541 /* De-registers a file reader by removing it from the GArray based on its name.
542 * This function must NOT be called during wtap_open_offline(), since it changes the array.
543 * Note: this function will error if it doesn't find the given name; if you want to handle
544 * that condition more gracefully, call wtap_has_open_info() first.
546 void
547 wtap_deregister_open_info(const char *name)
549 unsigned i;
551 if (!name) {
552 ws_error("Missing open_info name to de-register");
553 return;
556 for (i = 0; i < open_info_arr->len; i++) {
557 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
558 g_strfreev(open_routines[i].extensions_set);
559 open_info_arr = g_array_remove_index(open_info_arr, i);
560 set_heuristic_routine();
561 return;
565 ws_error("deregister_open_info: name not found");
568 /* Determines if a open routine short name already exists
570 bool
571 wtap_has_open_info(const char *name)
573 unsigned i;
575 if (!name) {
576 ws_error("No name given to wtap_has_open_info!");
577 return false;
581 for (i = 0; i < open_info_arr->len; i++) {
582 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
583 return true;
587 return false;
590 bool
591 wtap_uses_lua_filehandler(const wtap* wth)
593 if (wth && wth->wslua_data != NULL) {
595 * Currently, wslua_data is set if and only if using a Lua
596 * file handler.
598 return true;
601 return false;
605 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
606 * define them either.)
608 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
610 #ifndef S_ISREG
611 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
612 #endif
613 #ifndef S_IFIFO
614 #define S_IFIFO _S_IFIFO
615 #endif
616 #ifndef S_ISFIFO
617 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
618 #endif
619 #ifndef S_ISDIR
620 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
621 #endif
623 /* returns the 'type' number to use for wtap_open_offline based on the
624 * passed-in name (the name in the open_info struct). It returns WTAP_TYPE_AUTO
625 * on failure, which is the number 0. The 'type' number is the entry's index+1,
626 * because that's what wtap_open_offline() expects it to be.
628 unsigned int
629 open_info_name_to_type(const char *name)
631 unsigned int i;
633 if (!name)
634 return WTAP_TYPE_AUTO;
636 for (i = 0; i < open_info_arr->len; i++) {
637 if (open_routines[i].name != NULL &&
638 strcmp(name, open_routines[i].name) == 0)
639 return i+1;
642 return WTAP_TYPE_AUTO; /* no such file type */
645 static char *
646 get_file_extension(const char *pathname)
648 char *filename;
649 char **components;
650 size_t ncomponents;
651 char *extensionp;
654 * Is the pathname empty?
656 if (strcmp(pathname, "") == 0)
657 return NULL; /* no extension */
660 * Find the last component of the pathname.
662 filename = g_path_get_basename(pathname);
665 * Does it have an extension?
667 if (strchr(filename, '.') == NULL) {
668 g_free(filename);
669 return NULL; /* no extension whatsoever */
673 * Yes. Fold it to lowercase, since open_routines[] has
674 * its extensions in lowercase.
676 ascii_strdown_inplace(filename);
679 * Split it into components separated by ".".
681 components = g_strsplit(filename, ".", 0);
682 g_free(filename);
685 * Count the components.
687 for (ncomponents = 0; components[ncomponents] != NULL; ncomponents++)
690 if (ncomponents == 0) {
691 g_strfreev(components);
692 return NULL; /* no components */
694 if (ncomponents == 1) {
695 g_strfreev(components);
696 return NULL; /* only one component, with no "." */
700 * Get compression-type extensions, if any.
702 GSList *compression_type_extensions = wtap_get_all_compression_type_extensions_list();
705 * Is the last component one of the extensions used for compressed
706 * files?
708 extensionp = components[ncomponents - 1];
709 for (GSList *compression_type_extension = compression_type_extensions;
710 compression_type_extension != NULL;
711 compression_type_extension = g_slist_next(compression_type_extension)) {
712 if (strcmp(extensionp, (const char *)compression_type_extension->data) == 0) {
714 * Yes, so it's one of the compressed-file extensions.
715 * Is there an extension before that?
717 if (ncomponents == 2) {
718 g_slist_free(compression_type_extensions);
719 g_strfreev(components);
720 return NULL; /* no, only two components */
724 * Yes, return that extension.
726 g_slist_free(compression_type_extensions);
727 extensionp = g_strdup(components[ncomponents - 2]);
728 g_strfreev(components);
729 return extensionp;
733 g_slist_free(compression_type_extensions);
736 * The extension isn't one of the compressed-file extensions;
737 * return it.
739 extensionp = g_strdup(extensionp);
740 g_strfreev(components);
741 return extensionp;
745 * Check if file extension is used in this heuristic
747 static bool
748 heuristic_uses_extension(unsigned int i, const char *extension)
750 char **extensionp;
753 * Does this file type *have* any extensions?
755 if (open_routines[i].extensions == NULL)
756 return false; /* no */
759 * Check each of them against the specified extension.
761 for (extensionp = open_routines[i].extensions_set; *extensionp != NULL;
762 extensionp++) {
763 if (strcmp(extension, *extensionp) == 0) {
764 return true; /* it's one of them */
768 return false; /* it's not one of them */
772 * Attempt to open the file corresponding to "wth" using the file format
773 * handler in "candidate".
775 * Returns WTAP_OPEN_MINE upon success, WTAP_OPEN_NOT_MINE if the file is not
776 * in a suitable format for "candidate", or WTAP_OPEN_ERROR if a failure
777 * occurred while reading the input.
779 static int
780 try_one_open(wtap *wth, const struct open_info *candidate, int *err, char **err_info)
782 /* Seek back to the beginning of the file; the open routine for the
783 * previous file type may have left the file position somewhere other
784 * than the beginning, and the open routine for this file type will
785 * probably want to start reading at the beginning.
787 * Initialize the data offset while we're at it.
789 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
790 /* Error - give up */
791 return WTAP_OPEN_ERROR;
794 /* Set wth with wslua data if any - this is how we pass the data to the
795 * file reader, kinda like the priv member but not free'd later.
796 * It's ok for this to copy a NULL.
798 wth->wslua_data = candidate->wslua_data;
800 return candidate->open_routine(wth, err, err_info);
804 * Attempt to open the file corresponding to "wth". If "type" is supplied
805 * (i.e. other than WTAP_TYPE_AUTO), that will be the only type attempted.
806 * Otherwise, heuristic detection of the file format will be performed,
807 * possibly guided by the extension part of "filename".
809 * Returns WTAP_OPEN_MINE upon success, WTAP_OPEN_NOT_MINE if it was not
810 * possible to determine a suitable format for the file, or WTAP_OPEN_ERROR if
811 * a failure occurred while reading the input.
813 static int
814 try_open(wtap *wth, unsigned int type, int *err, char **err_info)
816 int result = WTAP_OPEN_NOT_MINE;
817 unsigned i;
818 char *extension;
820 /* 'type' is 1-based. */
821 if (type != WTAP_TYPE_AUTO && type <= open_info_arr->len) {
822 /* Try only the specified type. */
823 return try_one_open(wth, &open_routines[type - 1], err, err_info);
826 /* First, all file types that support magic numbers. */
827 for (i = 0; i < heuristic_open_routine_idx && result == WTAP_OPEN_NOT_MINE; i++) {
828 result = try_one_open(wth, &open_routines[i], err, err_info);
831 if (result != WTAP_OPEN_NOT_MINE) {
832 return result;
835 /* Does this file's name have an extension? */
836 extension = get_file_extension(wth->pathname);
837 if (extension != NULL) {
838 unsigned pass;
841 * Yes, the filename has an extension.
843 * The heuristic types fall into one of three categories, which
844 * we attempt in order by scanning for each category in turn.
846 * First pass selects the heuristic types that list this file's
847 * extension, as these are most likely to be the correct choice
848 * for this file.
850 * Second pass selects heuristic types which have no
851 * extensions. We try those before the ones that have
852 * extensions that *don't* match this file's extension, on the
853 * theory that files of those types generally have one of the
854 * type's extensions, and, as this file *doesn't* have one of
855 * those extensions, it's probably *not* one of those files.
857 * Third pass selects heuristic types which support extensions
858 * but where none of them matches this file's extension.
860 * We need only continue searching until we find a match or an
861 * error occurs.
864 for (pass = 0; pass < 3 && result == WTAP_OPEN_NOT_MINE; pass++) {
865 for (i = heuristic_open_routine_idx; i < open_info_arr->len && result == WTAP_OPEN_NOT_MINE; i++) {
866 if ( (pass == 0 && heuristic_uses_extension(i, extension))
867 || (pass == 1 && open_routines[i].extensions == NULL)
868 || (pass == 2 && open_routines[i].extensions != NULL
869 && !heuristic_uses_extension(i, extension))) {
870 result = try_one_open(wth, &open_routines[i], err, err_info);
875 g_free(extension);
876 } else {
877 /* No extension. Try all the heuristic types in order. */
878 for (i = heuristic_open_routine_idx; i < open_info_arr->len && result == WTAP_OPEN_NOT_MINE; i++) {
879 result = try_one_open(wth, &open_routines[i], err, err_info);
883 return result;
886 /* Opens a file and prepares a wtap struct.
887 * If "do_random" is true, it opens the file twice; the second open
888 * allows the application to do random-access I/O without moving
889 * the seek offset for sequential I/O, which is used by Wireshark
890 * so that it can do sequential I/O to a capture file that's being
891 * written to as new packets arrive independently of random I/O done
892 * to display protocol trees for packets when they're selected.
894 wtap *
895 wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_info,
896 bool do_random)
898 int fd;
899 ws_statb64 statb;
900 bool ispipe = false;
901 wtap *wth;
902 bool use_stdin = false;
903 wtap_block_t shb;
905 *err = 0;
906 *err_info = NULL;
908 /* open standard input if filename is '-' */
909 if (strcmp(filename, "-") == 0)
910 use_stdin = true;
912 /* First, make sure the file is valid */
913 if (use_stdin) {
914 if (ws_fstat64(0, &statb) < 0) {
915 *err = errno;
916 return NULL;
918 } else {
919 if (ws_stat64(filename, &statb) < 0) {
920 *err = errno;
921 return NULL;
924 if (S_ISFIFO(statb.st_mode)) {
926 * Opens of FIFOs are allowed only when not opening
927 * for random access.
929 * Currently, we do seeking when trying to find out
930 * the file type, but our I/O routines do some amount
931 * of buffering, and do backward seeks within the buffer
932 * if possible, so at least some file types can be
933 * opened from pipes, so we don't completely disallow opens
934 * of pipes.
936 if (do_random) {
937 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
938 return NULL;
940 ispipe = true;
941 } else if (S_ISDIR(statb.st_mode)) {
943 * Return different errors for "this is a directory"
944 * and "this is some random special file type", so
945 * the user can get a potentially more helpful error.
947 *err = EISDIR;
948 return NULL;
949 } else if (! S_ISREG(statb.st_mode)) {
950 *err = WTAP_ERR_NOT_REGULAR_FILE;
951 return NULL;
955 * We need two independent descriptors for random access, so
956 * they have different file positions. If we're opening the
957 * standard input, we can only dup it to get additional
958 * descriptors, so we can't have two independent descriptors,
959 * and thus can't do random access.
961 if (use_stdin && do_random) {
962 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
963 return NULL;
966 errno = ENOMEM;
967 wth = g_new0(wtap, 1);
969 /* Open the file */
970 errno = WTAP_ERR_CANT_OPEN;
971 if (use_stdin) {
973 * We dup FD 0, so that we don't have to worry about
974 * a file_close of wth->fh closing the standard
975 * input of the process.
977 fd = ws_dup(0);
978 if (fd < 0) {
979 *err = errno;
980 g_free(wth);
981 return NULL;
983 #ifdef _WIN32
984 if (_setmode(fd, O_BINARY) == -1) {
985 /* "Shouldn't happen" */
986 *err = errno;
987 g_free(wth);
988 return NULL;
990 #endif
991 if (!(wth->fh = file_fdopen(fd))) {
992 *err = errno;
993 ws_close(fd);
994 g_free(wth);
995 return NULL;
997 } else {
998 if (!(wth->fh = file_open(filename))) {
999 *err = errno;
1000 g_free(wth);
1001 return NULL;
1005 if (do_random) {
1006 if (!(wth->random_fh = file_open(filename))) {
1007 *err = errno;
1008 file_close(wth->fh);
1009 g_free(wth);
1010 return NULL;
1012 } else
1013 wth->random_fh = NULL;
1015 /* initialization */
1016 wth->ispipe = ispipe;
1017 wth->file_encap = WTAP_ENCAP_UNKNOWN;
1018 wth->subtype_sequential_close = NULL;
1019 wth->subtype_close = NULL;
1020 wth->file_tsprec = WTAP_TSPREC_USEC;
1021 wth->pathname = g_strdup(filename);
1022 wth->priv = NULL;
1023 wth->wslua_data = NULL;
1024 wth->shb_hdrs = g_array_new(false, false, sizeof(wtap_block_t));
1025 shb = wtap_block_create(WTAP_BLOCK_SECTION);
1026 if (shb)
1027 g_array_append_val(wth->shb_hdrs, shb);
1029 /* Initialize the array containing a list of interfaces. pcapng_open and
1030 * erf_open needs this (and libpcap_open for ERF encapsulation types).
1031 * Always initing it here saves checking for a NULL ptr later. */
1032 wth->interface_data = g_array_new(false, false, sizeof(wtap_block_t));
1034 * Next interface data that wtap_get_next_interface_description()
1035 * will return.
1037 wth->next_interface_data = 0;
1039 wth->shb_iface_to_global = g_array_new(false, false, sizeof(unsigned));
1040 g_array_append_val(wth->shb_iface_to_global, wth->interface_data->len);
1042 if (wth->random_fh) {
1043 wth->fast_seek = g_ptr_array_new();
1045 file_set_random_access(wth->fh, false, wth->fast_seek);
1046 file_set_random_access(wth->random_fh, true, wth->fast_seek);
1049 /* Find a file format handler which can read the file. */
1050 switch (try_open(wth, type, err, err_info)) {
1051 case WTAP_OPEN_NOT_MINE:
1052 /* Well, it's not one of the types of file we know about. */
1053 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
1054 /* FALLTHROUGH */
1056 case WTAP_OPEN_ERROR:
1057 wtap_close(wth);
1058 wth = NULL;
1061 return wth;
1065 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
1066 * to reopen that file and assign the new file descriptor(s) to the sequential
1067 * stream and, if do_random is true, to the random stream. Used on Windows
1068 * after the rename of a file we had open was done or if the rename of a
1069 * file on top of a file we had open failed.
1071 * This is only required by Wireshark, not TShark, and, at the point that
1072 * Wireshark is doing this, the sequential stream is closed, and the
1073 * random stream is open, so this refuses to open pipes, and only
1074 * reopens the random stream.
1076 bool
1077 wtap_fdreopen(wtap *wth, const char *filename, int *err)
1079 ws_statb64 statb;
1082 * We need two independent descriptors for random access, so
1083 * they have different file positions. If we're opening the
1084 * standard input, we can only dup it to get additional
1085 * descriptors, so we can't have two independent descriptors,
1086 * and thus can't do random access.
1088 if (strcmp(filename, "-") == 0) {
1089 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
1090 return false;
1093 /* First, make sure the file is valid */
1094 if (ws_stat64(filename, &statb) < 0) {
1095 *err = errno;
1096 return false;
1098 if (S_ISFIFO(statb.st_mode)) {
1100 * Opens of FIFOs are not allowed; see above.
1102 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
1103 return false;
1104 } else if (S_ISDIR(statb.st_mode)) {
1106 * Return different errors for "this is a directory"
1107 * and "this is some random special file type", so
1108 * the user can get a potentially more helpful error.
1110 *err = EISDIR;
1111 return false;
1112 } else if (! S_ISREG(statb.st_mode)) {
1113 *err = WTAP_ERR_NOT_REGULAR_FILE;
1114 return false;
1117 /* Open the file */
1118 errno = WTAP_ERR_CANT_OPEN;
1119 if (!file_fdreopen(wth->random_fh, filename)) {
1120 *err = errno;
1121 return false;
1123 if (strcmp(filename, wth->pathname) != 0) {
1124 g_free(wth->pathname);
1125 wth->pathname = g_strdup(filename);
1127 return true;
1130 /* Table of the file types and subtypes for which we have support. */
1133 * Pointer to the GArray holding the registered file types.
1135 static GArray* file_type_subtype_table_arr;
1138 * Pointer to the table of registered file types in that GArray.
1140 static const struct file_type_subtype_info* file_type_subtype_table;
1143 * Number of elements in the table for builtin file types/subtypes.
1145 static unsigned wtap_num_builtin_file_types_subtypes;
1148 * Required builtin types.
1150 int pcap_file_type_subtype = -1;
1151 int pcap_nsec_file_type_subtype = -1;
1152 int pcapng_file_type_subtype = -1;
1155 * Table for mapping old file type/subtype names to new ones for
1156 * backwards compatibility.
1158 static GHashTable *type_subtype_name_map;
1161 * Initialize the table of file types/subtypes with all the builtin
1162 * types/subtypes.
1164 void
1165 wtap_init_file_type_subtypes(void)
1167 /* Don't do this twice. */
1168 ws_assert(file_type_subtype_table_arr == NULL);
1171 * Estimate the number of file types/subtypes as twice the
1172 * number of modules; that's probably an overestimate, as
1173 * the average number of file types/subtypes registered by
1174 * a module is > 1 but probably < 2, but that shouldn't
1175 * waste too much memory.
1177 * Add on 7 more for pcapng, pcap, nanosecond pcap, and the
1178 * extra modified flavors of pcap.
1180 file_type_subtype_table_arr = g_array_sized_new(false, true,
1181 sizeof(struct file_type_subtype_info), wtap_module_count*2 + 7);
1182 file_type_subtype_table = (const struct file_type_subtype_info*)(void *)file_type_subtype_table_arr->data;
1185 * Initialize the hash table for mapping old file type/subtype
1186 * names to the corresponding new names.
1188 type_subtype_name_map = g_hash_table_new_full(g_str_hash,
1189 g_str_equal, g_free, g_free);
1191 /* No entries yet, so no builtin entries yet. */
1192 wtap_num_builtin_file_types_subtypes = 0;
1195 * Register the builtin entries that aren't in the table.
1196 * First, do the required ones; register pcapng first, then
1197 * pcap, so, at the beginning of the table, we have pcapng,
1198 * pcap, nanosecond pcap, and the weird modified pcaps, so
1199 * searches for file types that can write a file format
1200 * start with pcapng, pcap, and nanosecond pcap.
1202 register_pcapng();
1203 register_pcap();
1205 /* Now register the ones found by the build process */
1206 for (unsigned i = 0; i < wtap_module_count; i++)
1207 wtap_module_reg[i].cb_func();
1209 /* Update the number of builtin entries. */
1210 wtap_num_builtin_file_types_subtypes = file_type_subtype_table_arr->len;
1214 * Attempt to register a new file type/subtype; fails if a type/subtype
1215 * with that name is already registered.
1218 wtap_register_file_type_subtype(const struct file_type_subtype_info* fi)
1220 struct file_type_subtype_info* finfo;
1221 unsigned file_type_subtype;
1224 * Check for required fields (description and name).
1226 if (!fi || !fi->description || !fi->name) {
1227 ws_warning("no file type info");
1228 return -1;
1232 * There must be at least one block type that this file
1233 * type/subtype supports.
1235 if (fi->num_supported_blocks == 0 || fi->supported_blocks == NULL) {
1236 ws_warning("no blocks supported by file type \"%s\"", fi->name);
1237 return -1;
1241 * Is this type already registered?
1243 if (wtap_name_to_file_type_subtype(fi->name) != -1) {
1245 * Yes. You don't get to replace an existing handler.
1247 ws_warning("file type \"%s\" is already registered", fi->name);
1248 return -1;
1252 * Is there a freed entry in the array, due to a file type
1253 * being de-registered?
1255 * Skip the built-in entries, as they're never deregistered.
1257 for (file_type_subtype = wtap_num_builtin_file_types_subtypes;
1258 file_type_subtype < file_type_subtype_table_arr->len;
1259 file_type_subtype++) {
1260 if (file_type_subtype_table[file_type_subtype].name == NULL) {
1262 * We found such an entry.
1264 * Get the pointer from the GArray, so that we get a
1265 * non-const pointer.
1267 finfo = &g_array_index(file_type_subtype_table_arr, struct file_type_subtype_info, file_type_subtype);
1270 * Fill in the entry with the new values.
1272 *finfo = *fi;
1274 return (int)file_type_subtype;
1279 * There aren't any free slots, so add a new entry.
1280 * Get the number of current number of entries, which will
1281 * be the index of the new entry, then append this entry
1282 * to the end of the array, change file_type_subtype_table
1283 * in case the array had to get reallocated, and return
1284 * the index of the new entry.
1286 file_type_subtype = file_type_subtype_table_arr->len;
1287 g_array_append_val(file_type_subtype_table_arr, *fi);
1288 file_type_subtype_table = (const struct file_type_subtype_info*)(void *)file_type_subtype_table_arr->data;
1289 return file_type_subtype;
1292 /* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1294 void
1295 wtap_deregister_file_type_subtype(const int subtype)
1297 struct file_type_subtype_info* finfo;
1299 if (subtype < 0 || subtype >= (int)file_type_subtype_table_arr->len) {
1300 ws_error("invalid file type to de-register");
1301 return;
1303 if ((unsigned)subtype < wtap_num_builtin_file_types_subtypes) {
1304 ws_error("built-in file types cannot be de-registered");
1305 return;
1309 * Get the pointer from the GArray, so that we get a non-const
1310 * pointer.
1312 finfo = &g_array_index(file_type_subtype_table_arr, struct file_type_subtype_info, subtype);
1314 * Clear out this entry.
1316 finfo->description = NULL;
1317 finfo->name = NULL;
1318 finfo->default_file_extension = NULL;
1319 finfo->additional_file_extensions = NULL;
1320 finfo->writing_must_seek = false;
1321 finfo->num_supported_blocks = 0;
1322 finfo->supported_blocks = NULL;
1323 finfo->can_write_encap = NULL;
1324 finfo->dump_open = NULL;
1325 finfo->wslua_info = NULL;
1329 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1330 * type that would be needed to write out a file with those types. If
1331 * there's only one type, it's that type, otherwise it's
1332 * WTAP_ENCAP_PER_PACKET.
1335 wtap_dump_required_file_encap_type(const GArray *file_encaps)
1337 int encap;
1339 encap = WTAP_ENCAP_PER_PACKET;
1340 if (file_encaps->len == 1) {
1341 /* OK, use the one-and-only encapsulation type. */
1342 encap = g_array_index(file_encaps, int, 0);
1344 return encap;
1347 bool
1348 wtap_dump_can_write_encap(int file_type_subtype, int encap)
1350 int result = 0;
1352 if (file_type_subtype < 0 ||
1353 file_type_subtype >= (int)file_type_subtype_table_arr->len ||
1354 file_type_subtype_table[file_type_subtype].can_write_encap == NULL)
1355 return false;
1357 result = (*file_type_subtype_table[file_type_subtype].can_write_encap)(encap);
1359 if (result != 0) {
1360 /* if the err said to check wslua's can_write_encap, try that */
1361 if (result == WTAP_ERR_CHECK_WSLUA
1362 && file_type_subtype_table[file_type_subtype].wslua_info != NULL
1363 && file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
1365 result = (*file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, file_type_subtype_table[file_type_subtype].wslua_info->wslua_data);
1369 if (result != 0)
1370 return false;
1373 return true;
1377 * Return true if a capture with a given GArray of encapsulation types
1378 * and a given bitset of comment types can be written in a specified
1379 * format, and false if it can't.
1381 static bool
1382 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1383 uint32_t required_comment_types)
1385 unsigned i;
1388 * Can we write in this format?
1390 if (!wtap_dump_can_open(ft)) {
1391 /* No. */
1392 return false;
1396 * Yes. Can we write out all the required comments in this
1397 * format?
1399 if (required_comment_types & WTAP_COMMENT_PER_SECTION) {
1400 if (wtap_file_type_subtype_supports_option(ft,
1401 WTAP_BLOCK_SECTION, OPT_COMMENT) == OPTION_NOT_SUPPORTED) {
1402 /* Not section comments. */
1403 return false;
1406 if (required_comment_types & WTAP_COMMENT_PER_INTERFACE) {
1407 if (wtap_file_type_subtype_supports_option(ft,
1408 WTAP_BLOCK_IF_ID_AND_INFO, OPT_COMMENT) == OPTION_NOT_SUPPORTED) {
1409 /* Not interface comments. */
1410 return false;
1413 if (required_comment_types & WTAP_COMMENT_PER_PACKET) {
1414 if (wtap_file_type_subtype_supports_option(ft,
1415 WTAP_BLOCK_PACKET, OPT_COMMENT) == OPTION_NOT_SUPPORTED) {
1416 /* Not packet comments. */
1417 return false;
1422 * Yes. Is the required per-file encapsulation type supported?
1423 * This might be WTAP_ENCAP_PER_PACKET.
1425 if (!wtap_dump_can_write_encap(ft, wtap_dump_required_file_encap_type(file_encaps))) {
1426 /* No. */
1427 return false;
1431 * Yes. Are all the individual encapsulation types supported?
1433 for (i = 0; i < file_encaps->len; i++) {
1434 if (!wtap_dump_can_write_encap(ft,
1435 g_array_index(file_encaps, int, i))) {
1436 /* No - one of them isn't. */
1437 return false;
1441 /* Yes - we're OK. */
1442 return true;
1446 * Return true if we can write a file with the given GArray of
1447 * encapsulation types and the given bitmask of comment types.
1449 bool
1450 wtap_dump_can_write(const GArray *file_encaps, uint32_t required_comment_types)
1452 int ft;
1454 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1455 /* To save a file with Wiretap, Wiretap has to handle that format,
1456 * and its code to handle that format must be able to write a file
1457 * with this file's encapsulation types.
1459 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1460 /* OK, we can write it out in this type. */
1461 return true;
1465 /* No, we couldn't save it in any format. */
1466 return false;
1470 * Sort by file type/subtype name.
1472 static int
1473 compare_file_type_subtypes_by_name(const void *a, const void *b)
1475 int file_type_subtype_a = *(const int *)a;
1476 int file_type_subtype_b = *(const int *)b;
1478 return strcmp(wtap_file_type_subtype_name(file_type_subtype_a),
1479 wtap_file_type_subtype_name(file_type_subtype_b));
1483 * Sort by file type/subtype description.
1485 static int
1486 compare_file_type_subtypes_by_description(const void *a, const void *b)
1488 int file_type_subtype_a = *(const int *)a;
1489 int file_type_subtype_b = *(const int *)b;
1491 return strcmp(wtap_file_type_subtype_description(file_type_subtype_a),
1492 wtap_file_type_subtype_description(file_type_subtype_b));
1496 * Get a GArray of file type/subtype values for file types/subtypes
1497 * that can be used to save a file of a given type/subtype with a given
1498 * GArray of encapsulation types and the given bitmask of comment types.
1500 GArray *
1501 wtap_get_savable_file_types_subtypes_for_file(int file_type_subtype,
1502 const GArray *file_encaps, uint32_t required_comment_types,
1503 ft_sort_order sort_order)
1505 GArray *savable_file_types_subtypes;
1506 int ft;
1507 int default_file_type_subtype = -1;
1508 int other_file_type_subtype = -1;
1510 /* Can we save this file in its own file type/subtype? */
1511 if (wtap_dump_can_write_format(file_type_subtype, file_encaps,
1512 required_comment_types)) {
1513 /* Yes - make that the default file type/subtype. */
1514 default_file_type_subtype = file_type_subtype;
1515 } else if (wtap_dump_can_write_format(pcap_file_type_subtype,
1516 file_encaps,
1517 required_comment_types)) {
1519 * No, but we can write it as a pcap file; make that
1520 * the default file type/subtype.
1522 default_file_type_subtype = pcap_file_type_subtype;
1523 } else if (wtap_dump_can_write_format(pcapng_file_type_subtype,
1524 file_encaps,
1525 required_comment_types)) {
1527 * No, but we can write it as a pcapng file; make that
1528 * the default file type/subtype.
1530 default_file_type_subtype = pcapng_file_type_subtype;
1531 } else {
1532 /* OK, find the first file type/subtype we *can* save it as. */
1533 default_file_type_subtype = -1;
1534 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1535 if (wtap_dump_can_write_format(ft, file_encaps,
1536 required_comment_types)) {
1537 /* OK, got it. */
1538 default_file_type_subtype = ft;
1539 break;
1544 if (default_file_type_subtype == -1) {
1545 /* We don't support writing this file as any file type/subtype. */
1546 return NULL;
1550 * If the default is pcap, put pcapng right after it if we can
1551 * also write it in pcapng format; otherwise, if the default is
1552 * pcapng, put pcap right after it if we can also write it in
1553 * pcap format.
1555 if (default_file_type_subtype == pcap_file_type_subtype) {
1556 if (wtap_dump_can_write_format(pcapng_file_type_subtype,
1557 file_encaps,
1558 required_comment_types))
1559 other_file_type_subtype = pcapng_file_type_subtype;
1560 } else if (default_file_type_subtype == pcapng_file_type_subtype) {
1561 if (wtap_dump_can_write_format(pcap_file_type_subtype,
1562 file_encaps,
1563 required_comment_types))
1564 other_file_type_subtype = pcap_file_type_subtype;
1567 /* Allocate the array. */
1568 savable_file_types_subtypes = g_array_new(false, false,
1569 sizeof (int));
1572 * First, add the types we don't want to force to the
1573 * beginning of the list.
1575 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1576 if (ft == default_file_type_subtype ||
1577 ft == other_file_type_subtype)
1578 continue; /* we will done this one later */
1579 if (wtap_dump_can_write_format(ft, file_encaps,
1580 required_comment_types)) {
1581 /* OK, we can write it out in this type. */
1582 g_array_append_val(savable_file_types_subtypes, ft);
1586 /* Now, sort the list. */
1587 g_array_sort(savable_file_types_subtypes,
1588 (sort_order == FT_SORT_BY_NAME) ? compare_file_type_subtypes_by_name :
1589 compare_file_type_subtypes_by_description);
1592 * If we have a type/subtype to put above the default one,
1593 * do so.
1595 * We put this type at the beginning before putting the
1596 * default there, so the default is at the top.
1598 if (other_file_type_subtype != -1)
1599 g_array_prepend_val(savable_file_types_subtypes,
1600 other_file_type_subtype);
1602 /* Put the default file type/subtype first in the list. */
1603 g_array_prepend_val(savable_file_types_subtypes,
1604 default_file_type_subtype);
1606 return savable_file_types_subtypes;
1610 * Get a GArray of all writable file type/subtype values.
1612 GArray *
1613 wtap_get_writable_file_types_subtypes(ft_sort_order sort_order)
1615 GArray *writable_file_types_subtypes;
1616 int ft;
1619 * Allocate the array.
1620 * Pre-allocate room enough for all types.
1621 * XXX - that's overkill; just scan the table to find all the
1622 * writable types and count them.
1624 writable_file_types_subtypes = g_array_sized_new(false, false,
1625 sizeof (int), file_type_subtype_table_arr->len);
1628 * First, add the types we don't want to force to the
1629 * beginning of the list.
1631 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1632 if (ft == pcap_file_type_subtype ||
1633 ft == pcapng_file_type_subtype)
1634 continue; /* we've already done these two */
1635 if (wtap_dump_can_open(ft)) {
1636 /* OK, we can write this type. */
1637 g_array_append_val(writable_file_types_subtypes, ft);
1641 /* Now, sort the list. */
1642 g_array_sort(writable_file_types_subtypes,
1643 (sort_order == FT_SORT_BY_NAME) ? compare_file_type_subtypes_by_name :
1644 compare_file_type_subtypes_by_description);
1647 * Now, put pcap and pcapng at the beginning, as they're
1648 * our "native" formats. Put pcapng there first, and
1649 * pcap before it.
1651 if (pcapng_file_type_subtype != -1 &&
1652 wtap_dump_can_open(pcapng_file_type_subtype)) {
1654 * We can write pcapng. (If we can't, that's a huge
1655 * mistake.)
1657 g_array_prepend_val(writable_file_types_subtypes,
1658 pcapng_file_type_subtype);
1660 if (pcap_file_type_subtype != -1 &&
1661 wtap_dump_can_open(pcap_file_type_subtype)) {
1663 * We can write pcap. (If we can't, that's a huge
1664 * mistake.)
1666 g_array_prepend_val(writable_file_types_subtypes,
1667 pcap_file_type_subtype);
1670 return writable_file_types_subtypes;
1674 * String describing the file type/subtype.
1676 const char *
1677 wtap_file_type_subtype_description(int file_type_subtype)
1679 if (file_type_subtype < 0 ||
1680 file_type_subtype >= (int)file_type_subtype_table_arr->len)
1681 return NULL;
1682 else
1683 return file_type_subtype_table[file_type_subtype].description;
1687 * Name to use in, say, a command-line flag specifying the type/subtype.
1689 const char *
1690 wtap_file_type_subtype_name(int file_type_subtype)
1692 if (file_type_subtype < 0 ||
1693 file_type_subtype >= (int)file_type_subtype_table_arr->len)
1694 return NULL;
1695 else
1696 return file_type_subtype_table[file_type_subtype].name;
1700 * Register a backwards-compatibility name.
1702 void
1703 wtap_register_compatibility_file_subtype_name(const char *old_name,
1704 const char *new_name)
1706 g_hash_table_insert(type_subtype_name_map, g_strdup(old_name),
1707 g_strdup(new_name));
1711 * Translate a name to a capture file type/subtype.
1714 wtap_name_to_file_type_subtype(const char *name)
1716 char *new_name;
1717 int file_type_subtype;
1720 * Is this name a backwards-compatibility name?
1722 new_name = (char *)g_hash_table_lookup(type_subtype_name_map,
1723 (void *)name);
1724 if (new_name != NULL) {
1726 * Yes, and new_name is the name to which it should
1727 * be mapped.
1729 name = new_name;
1731 for (file_type_subtype = 0;
1732 file_type_subtype < (int)file_type_subtype_table_arr->len;
1733 file_type_subtype++) {
1734 if (file_type_subtype_table[file_type_subtype].name != NULL &&
1735 strcmp(name, file_type_subtype_table[file_type_subtype].name) == 0)
1736 return file_type_subtype;
1739 return -1; /* no such file type, or we can't write it */
1743 * Provide the file type/subtype for pcap.
1746 wtap_pcap_file_type_subtype(void)
1749 * Make sure pcap was registered as a file type/subtype;
1750 * it's one of our "native" formats.
1752 ws_assert(pcap_file_type_subtype != -1);
1753 return pcap_file_type_subtype;
1757 * Provide the file type/subtype for nanosecond-resolution pcap.
1760 wtap_pcap_nsec_file_type_subtype(void)
1763 * Make sure nanosecond-resolution pcap was registered
1764 * as a file type/subtype; it's one of our "native" formats.
1766 ws_assert(pcap_nsec_file_type_subtype != -1);
1767 return pcap_nsec_file_type_subtype;
1771 * Provide the file type/subtype for pcapng.
1774 wtap_pcapng_file_type_subtype(void)
1777 * Make sure pcapng was registered as a file type/subtype;
1778 * it's one of our "native" formats.
1780 ws_assert(pcapng_file_type_subtype != -1);
1781 return pcapng_file_type_subtype;
1785 * Determine if a file type/subtype can write a block of the given type.
1787 block_support_t
1788 wtap_file_type_subtype_supports_block(int file_type_subtype,
1789 wtap_block_type_t type)
1791 size_t num_supported_blocks;
1792 const struct supported_block_type *supported_blocks;
1794 if (file_type_subtype < 0 ||
1795 file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1797 * There's no such file type, so it can't support any
1798 * blocks.
1800 return BLOCK_NOT_SUPPORTED;
1803 num_supported_blocks = file_type_subtype_table[file_type_subtype].num_supported_blocks;
1804 supported_blocks = file_type_subtype_table[file_type_subtype].supported_blocks;
1806 for (size_t block_idx = 0; block_idx < num_supported_blocks;
1807 block_idx++) {
1808 if (supported_blocks[block_idx].type == type)
1809 return supported_blocks[block_idx].support;
1813 * Not found, which means not supported.
1815 return BLOCK_NOT_SUPPORTED;
1819 * Determine if a file type/subtype, when writing a block of the given type,
1820 * can support adding the given option to the block.
1822 option_support_t
1823 wtap_file_type_subtype_supports_option(int file_type_subtype,
1824 wtap_block_type_t type, unsigned option)
1826 size_t num_supported_blocks;
1827 const struct supported_block_type *supported_blocks;
1829 if (file_type_subtype < 0 ||
1830 file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1832 * There's no such file type, so it can't support any
1833 * blocks, and thus can't support any options.
1835 return OPTION_NOT_SUPPORTED;
1838 num_supported_blocks = file_type_subtype_table[file_type_subtype].num_supported_blocks;
1839 supported_blocks = file_type_subtype_table[file_type_subtype].supported_blocks;
1841 for (size_t block_idx = 0; block_idx < num_supported_blocks;
1842 block_idx++) {
1843 if (supported_blocks[block_idx].type == type) {
1845 * OK, that block is known.
1846 * Is it supported?
1848 if (supported_blocks[block_idx].support == BLOCK_NOT_SUPPORTED) {
1850 * No, so clearly the option isn't
1851 * supported in that block.
1853 return OPTION_NOT_SUPPORTED;
1857 * Yes, so check the options.
1859 size_t num_supported_options;
1860 const struct supported_option_type *supported_options;
1862 num_supported_options = supported_blocks[block_idx].num_supported_options;
1863 supported_options = supported_blocks[block_idx].supported_options;
1864 for (size_t opt_idx = 0; opt_idx < num_supported_options;
1865 opt_idx++) {
1866 if (supported_options[opt_idx].opt == option)
1867 return supported_options[opt_idx].support;
1871 * Not found, which means not supported.
1873 return OPTION_NOT_SUPPORTED;
1878 * The block type wasn't found, which means it's not supported,
1879 * which means the option isn't supported in that block.
1881 return OPTION_NOT_SUPPORTED;
1884 static GSList *
1885 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
1886 GSList *compression_type_extensions)
1888 char **extensions_set, **extensionp;
1889 char *extension;
1891 if (file_type_subtype < 0 ||
1892 file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1894 * There's no such file type, so it has no extensions
1895 * to add.
1897 return extensions;
1901 * Add the default extension, and all of the compressed variants
1902 * from the list of compressed-file extensions, if there is a
1903 * default extension.
1905 if (file_type_subtype_table[file_type_subtype].default_file_extension != NULL) {
1906 extensions = add_extensions(extensions,
1907 file_type_subtype_table[file_type_subtype].default_file_extension,
1908 compression_type_extensions);
1911 if (file_type_subtype_table[file_type_subtype].additional_file_extensions != NULL) {
1913 * We have additional extensions; add them.
1915 * First, split the extension-list string into a set of
1916 * extensions.
1918 extensions_set = g_strsplit(file_type_subtype_table[file_type_subtype].additional_file_extensions,
1919 ";", 0);
1922 * Add each of those extensions to the list.
1924 for (extensionp = extensions_set; *extensionp != NULL;
1925 extensionp++) {
1926 extension = *extensionp;
1929 * Add the extension, and all compressed variants
1930 * of it if requested.
1932 extensions = add_extensions(extensions, extension,
1933 compression_type_extensions);
1936 g_strfreev(extensions_set);
1938 return extensions;
1941 /* Return a list of file extensions that are used by the specified file
1942 * type/subtype.
1944 * If include_compressed is true, the list will include compressed
1945 * extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1946 * gzipped files.
1948 * All strings in the list are allocated with g_malloc() and must be freed
1949 * with g_free().
1951 GSList *
1952 wtap_get_file_extensions_list(int file_type_subtype, bool include_compressed)
1954 GSList *extensions, *compression_type_extensions;
1956 if (file_type_subtype < 0 ||
1957 file_type_subtype >= (int)file_type_subtype_table_arr->len)
1958 return NULL; /* not a valid file type */
1960 if (file_type_subtype_table[file_type_subtype].default_file_extension == NULL)
1961 return NULL; /* valid, but no extensions known */
1963 extensions = NULL; /* empty list, to start with */
1966 * Add all this file type's extensions, with compressed
1967 * variants if include_compressed is true.
1969 if (include_compressed) {
1971 * Get compression-type extensions, if any.
1973 compression_type_extensions = wtap_get_all_compression_type_extensions_list();
1974 } else {
1976 * We don't want the compressed file extensions.
1978 compression_type_extensions = NULL;
1980 extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
1981 compression_type_extensions);
1983 g_slist_free(compression_type_extensions);
1985 return extensions;
1988 /* Return a list of all extensions that are used by all capture file
1989 * types, including compressed extensions, e.g. not just "pcap" but
1990 * also "pcap.gz" if we can read gzipped files.
1992 * "Capture files" means "include file types that correspond to
1993 * collections of network packets, but not file types that
1994 * store data that just happens to be transported over protocols
1995 * such as HTTP but that aren't collections of network packets",
1996 * so that it could be used for "All Capture Files" without picking
1997 * up JPEG files or files such as that - those aren't capture files,
1998 * and we *do* have them listed in the long list of individual file
1999 * types, so omitting them from "All Capture Files" is the right
2000 * thing to do.
2002 * All strings in the list are allocated with g_malloc() and must be freed
2003 * with g_free().
2005 * This is used to generate a list of extensions to look for if the user
2006 * chooses "All Capture Files" in a file open dialog.
2008 GSList *
2009 wtap_get_all_capture_file_extensions_list(void)
2011 GSList *extensions, *compression_type_extensions;
2012 unsigned int i;
2014 init_file_type_extensions();
2016 extensions = NULL; /* empty list, to start with */
2019 * Get compression-type extensions, if any.
2021 compression_type_extensions = wtap_get_all_compression_type_extensions_list();
2023 for (i = 0; i < file_type_extensions_arr->len; i++) {
2025 * Is this a capture file, rather than one of the
2026 * other random file types we can read?
2028 if (file_type_extensions[i].is_capture_file) {
2030 * Yes. Add all this file extension type's
2031 * extensions, with compressed variants.
2033 extensions = add_extensions_for_file_extensions_type(i,
2034 extensions, compression_type_extensions);
2038 g_slist_free(compression_type_extensions);
2040 return extensions;
2043 /* Return a list of all extensions that are used by all file types that
2044 * we can read, including compressed extensions, e.g. not just "pcap" but
2045 * also "pcap.gz" if we can read gzipped files.
2047 * "File type" means "include file types that correspond to collections
2048 * of network packets, as well as file types that store data that just
2049 * happens to be transported over protocols such as HTTP but that aren't
2050 * collections of network packets, and plain text files".
2052 * All strings in the list are allocated with g_malloc() and must be freed
2053 * with g_free().
2055 * This is used to get the "base name" for a file, by stripping off
2056 * compressed-file extensions and extensions that correspond to file
2057 * types that we know about.
2059 GSList *
2060 wtap_get_all_file_extensions_list(void)
2062 GSList *extensions, *compression_type_extensions;
2064 extensions = NULL; /* empty list, to start with */
2067 * Get compression-type extensions, if any.
2069 compression_type_extensions = wtap_get_all_compression_type_extensions_list();
2071 for (int ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
2072 extensions = add_extensions_for_file_type_subtype(ft, extensions,
2073 compression_type_extensions);
2076 g_slist_free(compression_type_extensions);
2078 return extensions;
2082 * Free a list returned by wtap_get_file_extension_type_extensions(),
2083 * wtap_get_all_capture_file_extensions_list, wtap_get_file_extensions_list(),
2084 * or wtap_get_all_file_extensions_list().
2086 void
2087 wtap_free_extensions_list(GSList *extensions)
2089 GSList *extension;
2091 for (extension = extensions; extension != NULL;
2092 extension = g_slist_next(extension)) {
2093 g_free(extension->data);
2095 g_slist_free(extensions);
2099 * Return the default file extension to use with the specified file type
2100 * and subtype; that's just the extension, without any ".".
2102 const char *
2103 wtap_default_file_extension(int file_type_subtype)
2105 if (file_type_subtype < 0 ||
2106 file_type_subtype >= (int)file_type_subtype_table_arr->len)
2107 return NULL;
2108 else
2109 return file_type_subtype_table[file_type_subtype].default_file_extension;
2113 * Return whether we know how to write the specified file type.
2115 bool
2116 wtap_dump_can_open(int file_type_subtype)
2118 if (file_type_subtype < 0 ||
2119 file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2120 file_type_subtype_table[file_type_subtype].dump_open == NULL)
2121 return false;
2123 return true;
2127 * Return whether we know how to write a compressed file of the specified
2128 * file type.
2130 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H)
2131 bool
2132 wtap_dump_can_compress(int file_type_subtype)
2135 * If this is an unknown file type, or if we have to
2136 * seek when writing out a file with this file type,
2137 * return false.
2139 if (file_type_subtype < 0 ||
2140 file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2141 file_type_subtype_table[file_type_subtype].writing_must_seek)
2142 return false;
2144 return true;
2146 #else
2147 bool
2148 wtap_dump_can_compress(int file_type_subtype _U_)
2150 return false;
2152 #endif
2154 static bool wtap_dump_open_finish(wtap_dumper *wdh, int *err,
2155 char **err_info);
2157 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
2158 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
2159 static int wtap_dump_file_close(wtap_dumper *wdh);
2161 static wtap_dumper *
2162 wtap_dump_init_dumper(int file_type_subtype, wtap_compression_type compression_type,
2163 const wtap_dump_params *params, int *err)
2165 wtap_dumper *wdh;
2166 wtap_block_t descr, file_int_data;
2167 wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
2168 GArray *interfaces = params->idb_inf ? params->idb_inf->interface_data : NULL;
2170 /* Can we write files of this file type/subtype?
2172 * This will fail if file_type_subtype isn't a valid
2173 * file type/subtype value, so, if it doesn't fail,
2174 * we know file_type_subtype is within the bounds of
2175 * the table of file types/subtypes.
2177 if (!wtap_dump_can_open(file_type_subtype)) {
2178 /* Invalid type, or type we don't know how to write. */
2179 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2180 return NULL;
2183 /* OK, we know how to write that file type/subtype; can we write
2184 * the specified encapsulation type in that file type/subtype?
2186 *err = (*file_type_subtype_table[file_type_subtype].can_write_encap)(params->encap);
2187 /* if the err said to check wslua's can_write_encap, try that */
2188 if (*err == WTAP_ERR_CHECK_WSLUA
2189 && file_type_subtype_table[file_type_subtype].wslua_info != NULL
2190 && file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
2192 *err = (*file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap)(params->encap, file_type_subtype_table[file_type_subtype].wslua_info->wslua_data);
2195 if (*err != 0) {
2196 /* No, we can't. */
2197 return NULL;
2200 /* Check whether we can open a capture file with that file type
2201 * and that encapsulation, and, if the compression type isn't
2202 * "uncompressed", whether we can write a *compressed* file
2203 * of that file type.
2204 * If we're doing compression, can this file type/subtype be
2205 written in compressed form?
2207 * (The particular type doesn't matter - if the file can't
2208 * be written 100% sequentially, we can't compress it,
2209 * because we can't go back and overwrite something we've
2210 * already written.
2212 if (compression_type != WTAP_UNCOMPRESSED &&
2213 !wtap_dump_can_compress(file_type_subtype)) {
2214 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
2215 return NULL;
2218 /* Allocate a data structure for the output stream. */
2219 wdh = g_new0(wtap_dumper, 1);
2220 if (wdh == NULL) {
2221 *err = errno;
2222 return NULL;
2225 wdh->file_type_subtype = file_type_subtype;
2226 wdh->snaplen = params->snaplen;
2227 wdh->file_encap = params->encap;
2228 wdh->compression_type = compression_type;
2229 wdh->wslua_data = NULL;
2230 wdh->shb_iface_to_global = params->shb_iface_to_global;
2231 wdh->interface_data = g_array_new(false, false, sizeof(wtap_block_t));
2233 /* Set Section Header Block data */
2234 wdh->shb_hdrs = params->shb_hdrs;
2235 /* Set Name Resolution Block data */
2236 wdh->nrbs_growing = params->nrbs_growing;
2237 /* Set Interface Description Block data */
2238 if (interfaces && interfaces->len) {
2239 if (!params->dont_copy_idbs) { /* XXX */
2240 unsigned itf_count;
2242 /* Note: this memory is owned by wtap_dumper and will become
2243 * invalid after wtap_dump_close. */
2244 for (itf_count = 0; itf_count < interfaces->len; itf_count++) {
2245 file_int_data = g_array_index(interfaces, wtap_block_t, itf_count);
2246 file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
2247 descr = wtap_block_make_copy(file_int_data);
2248 if ((params->encap != WTAP_ENCAP_PER_PACKET) && (params->encap != file_int_data_mand->wtap_encap)) {
2249 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2250 descr_mand->wtap_encap = params->encap;
2252 g_array_append_val(wdh->interface_data, descr);
2255 } else if (params->encap != WTAP_ENCAP_NONE && params->encap != WTAP_ENCAP_PER_PACKET) {
2256 /* Generate a fake IDB if we don't have one, unless the
2257 * file encapsulation is none. (WTAP_ENCAP_NONE either
2258 * means that there are no interfaces, or they will be
2259 * provided later when reading the file in single-pass mode.)
2261 * For WTAP_ENCAP_PER_PACKET, we'll have to generate IDBs
2262 * from packet records as they come in. (pcapng does this now.)
2264 * XXX File types should provide their own IDBs (possibly
2265 * fake ones generated by wtap_add_generated_idb()), in
2266 * order to support being used as inputs for mergecap where
2267 * pcapng is the output.
2269 descr = wtap_dump_params_generate_idb(params);
2270 g_array_append_val(wdh->interface_data, descr);
2272 /* Set Decryption Secrets Blocks */
2273 wdh->dsbs_initial = params->dsbs_initial;
2274 wdh->dsbs_growing = params->dsbs_growing;
2275 /* Set Sysdig meta events */
2276 wdh->mevs_growing = params->mevs_growing;
2277 return wdh;
2280 wtap_dumper *
2281 wtap_dump_open(const char *filename, int file_type_subtype,
2282 wtap_compression_type compression_type, const wtap_dump_params *params,
2283 int *err, char **err_info)
2285 wtap_dumper *wdh;
2286 WFILE_T fh;
2288 *err = 0;
2289 *err_info = NULL;
2291 /* Allocate and initialize a data structure for the output stream. */
2292 wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2293 err);
2294 if (wdh == NULL)
2295 return NULL;
2297 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2298 to a generic "the open failed" error. */
2299 errno = WTAP_ERR_CANT_OPEN;
2300 fh = wtap_dump_file_open(wdh, filename);
2301 if (fh == NULL) {
2302 *err = errno;
2303 g_free(wdh);
2304 return NULL; /* can't create file */
2306 wdh->fh = fh;
2308 if (!wtap_dump_open_finish(wdh, err, err_info)) {
2309 /* Get rid of the file we created; we couldn't finish
2310 opening it. */
2311 wtap_dump_file_close(wdh);
2312 ws_unlink(filename);
2313 g_free(wdh);
2314 return NULL;
2316 return wdh;
2319 wtap_dumper *
2320 wtap_dump_open_tempfile(const char *tmpdir, char **filenamep, const char *pfx,
2321 int file_type_subtype, wtap_compression_type compression_type,
2322 const wtap_dump_params *params, int *err, char **err_info)
2324 int fd;
2325 const char *ext;
2326 char sfx[16];
2327 wtap_dumper *wdh;
2328 WFILE_T fh;
2330 /* No path name for the temporary file yet. */
2331 *filenamep = NULL;
2333 *err = 0;
2334 *err_info = NULL;
2336 /* Allocate and initialize a data structure for the output stream. */
2337 wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2338 err);
2339 if (wdh == NULL)
2340 return NULL;
2342 /* Choose an appropriate suffix for the file */
2343 ext = wtap_default_file_extension(file_type_subtype);
2344 if (ext == NULL)
2345 ext = "tmp";
2346 sfx[0] = '.';
2347 sfx[1] = '\0';
2348 (void) g_strlcat(sfx, ext, 16);
2350 /* Choose a random name for the file */
2351 fd = create_tempfile(tmpdir, filenamep, pfx, sfx, NULL);
2352 if (fd == -1) {
2353 *err = WTAP_ERR_CANT_OPEN;
2354 g_free(wdh);
2355 return NULL; /* can't create file */
2358 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2359 to a generic "the open failed" error. */
2360 errno = WTAP_ERR_CANT_OPEN;
2361 fh = wtap_dump_file_fdopen(wdh, fd);
2362 if (fh == NULL) {
2363 *err = errno;
2364 ws_close(fd);
2365 g_free(wdh);
2366 return NULL; /* can't create file */
2368 wdh->fh = fh;
2370 if (!wtap_dump_open_finish(wdh, err, err_info)) {
2371 /* Get rid of the file we created; we couldn't finish
2372 opening it. */
2373 wtap_dump_file_close(wdh);
2374 ws_unlink(*filenamep);
2375 g_free(wdh);
2376 return NULL;
2378 return wdh;
2381 wtap_dumper *
2382 wtap_dump_fdopen(int fd, int file_type_subtype, wtap_compression_type compression_type,
2383 const wtap_dump_params *params, int *err, char **err_info)
2385 wtap_dumper *wdh;
2386 WFILE_T fh;
2388 *err = 0;
2389 *err_info = NULL;
2391 /* Allocate and initialize a data structure for the output stream. */
2392 wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2393 err);
2394 if (wdh == NULL)
2395 return NULL;
2397 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2398 to a generic "the open failed" error. */
2399 errno = WTAP_ERR_CANT_OPEN;
2400 fh = wtap_dump_file_fdopen(wdh, fd);
2401 if (fh == NULL) {
2402 *err = errno;
2403 g_free(wdh);
2404 return NULL; /* can't create standard I/O stream */
2406 wdh->fh = fh;
2408 if (!wtap_dump_open_finish(wdh, err, err_info)) {
2409 wtap_dump_file_close(wdh);
2410 g_free(wdh);
2411 return NULL;
2413 return wdh;
2416 wtap_dumper *
2417 wtap_dump_open_stdout(int file_type_subtype, wtap_compression_type compression_type,
2418 const wtap_dump_params *params, int *err, char **err_info)
2420 int new_fd;
2421 wtap_dumper *wdh;
2424 * Duplicate the file descriptor, so that we can close the
2425 * wtap_dumper handle the same way we close any other
2426 * wtap_dumper handle, without closing the standard output.
2428 new_fd = ws_dup(1);
2429 if (new_fd == -1) {
2430 /* dup failed */
2431 *err = errno;
2432 return NULL;
2434 #ifdef _WIN32
2436 * Put the new descriptor into binary mode.
2438 * XXX - even if the file format we're writing is a text
2439 * format?
2441 if (_setmode(new_fd, O_BINARY) == -1) {
2442 /* "Should not happen" */
2443 *err = errno;
2444 ws_close(new_fd);
2445 return NULL;
2447 #endif
2449 wdh = wtap_dump_fdopen(new_fd, file_type_subtype, compression_type,
2450 params, err, err_info);
2451 if (wdh == NULL) {
2452 /* Failed; close the new FD */
2453 ws_close(new_fd);
2454 return NULL;
2456 return wdh;
2459 static bool
2460 wtap_dump_open_finish(wtap_dumper *wdh, int *err, char **err_info)
2462 int fd;
2463 bool cant_seek;
2465 /* Can we do a seek on the file descriptor?
2466 If not, note that fact. */
2467 if (wdh->compression_type != WTAP_UNCOMPRESSED) {
2468 cant_seek = true;
2469 } else {
2470 fd = ws_fileno((FILE *)wdh->fh);
2471 if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
2472 cant_seek = true;
2473 else {
2474 /* Undo the seek. */
2475 ws_lseek64(fd, 0, SEEK_SET);
2476 cant_seek = false;
2480 /* If this file type requires seeking, and we can't seek, fail. */
2481 if (file_type_subtype_table[wdh->file_type_subtype].writing_must_seek && cant_seek) {
2482 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
2483 return false;
2486 /* Set wdh with wslua data if any - this is how we pass the data
2487 * to the file writer.
2489 if (file_type_subtype_table[wdh->file_type_subtype].wslua_info)
2490 wdh->wslua_data = file_type_subtype_table[wdh->file_type_subtype].wslua_info->wslua_data;
2492 /* Now try to open the file for writing. */
2493 if (!(*file_type_subtype_table[wdh->file_type_subtype].dump_open)(wdh, err,
2494 err_info)) {
2495 return false;
2498 return true; /* success! */
2501 bool
2502 wtap_dump_add_idb(wtap_dumper *wdh, wtap_block_t idb, int *err,
2503 char **err_info)
2505 if (wdh->subtype_add_idb == NULL) {
2506 /* Not supported. */
2507 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
2508 *err_info = g_strdup("Adding IDBs isn't supported by this file type");
2509 return false;
2511 *err = 0;
2512 *err_info = NULL;
2513 return (wdh->subtype_add_idb)(wdh, idb, err, err_info);
2516 bool
2517 wtap_dump(wtap_dumper *wdh, const wtap_rec *rec,
2518 const uint8_t *pd, int *err, char **err_info)
2520 *err = 0;
2521 *err_info = NULL;
2522 return (wdh->subtype_write)(wdh, rec, pd, err, err_info);
2525 bool
2526 wtap_dump_flush(wtap_dumper *wdh, int *err)
2528 switch (wdh->compression_type) {
2529 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2530 case WTAP_GZIP_COMPRESSED:
2531 if (gzwfile_flush((GZWFILE_T)wdh->fh) == -1) {
2532 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2533 return false;
2535 break;
2536 #endif
2537 #ifdef HAVE_LZ4FRAME_H
2538 case WTAP_LZ4_COMPRESSED:
2539 if (lz4wfile_flush((LZ4WFILE_T)wdh->fh) == -1) {
2540 *err = lz4wfile_geterr((LZ4WFILE_T)wdh->fh);
2541 return false;
2543 break;
2544 #endif /* HAVE_LZ4FRAME_H */
2545 default:
2546 if (fflush((FILE *)wdh->fh) == EOF) {
2547 *err = errno;
2548 return false;
2551 return true;
2554 bool
2555 wtap_dump_close(wtap_dumper *wdh, bool *needs_reload,
2556 int *err, char **err_info)
2558 bool ret = true;
2560 *err = 0;
2561 *err_info = NULL;
2562 if (wdh->subtype_finish != NULL) {
2563 /* There's a finish routine for this dump stream. */
2564 if (!(wdh->subtype_finish)(wdh, err, err_info))
2565 ret = false;
2567 errno = WTAP_ERR_CANT_CLOSE;
2568 if (wtap_dump_file_close(wdh) == EOF) {
2569 if (ret) {
2570 /* The per-format finish function succeeded,
2571 but the stream close didn't. Save the
2572 reason why, if our caller asked for it. */
2573 if (err != NULL)
2574 *err = errno;
2576 ret = false;
2578 if (needs_reload != NULL)
2579 *needs_reload = wdh->needs_reload;
2580 g_free(wdh->priv);
2581 wtap_block_array_free(wdh->interface_data);
2582 wtap_block_array_unref(wdh->dsbs_initial);
2583 g_free(wdh);
2584 return ret;
2588 wtap_dump_file_type_subtype(wtap_dumper *wdh)
2590 return wdh->file_type_subtype;
2593 int64_t
2594 wtap_get_bytes_dumped(wtap_dumper *wdh)
2596 return wdh->bytes_dumped;
2599 void
2600 wtap_set_bytes_dumped(wtap_dumper *wdh, int64_t bytes_dumped)
2602 wdh->bytes_dumped = bytes_dumped;
2605 bool
2606 wtap_addrinfo_list_empty(addrinfo_lists_t *addrinfo_lists)
2608 return (addrinfo_lists == NULL) ||
2609 ((addrinfo_lists->ipv4_addr_list == NULL) &&
2610 (addrinfo_lists->ipv6_addr_list == NULL));
2613 bool
2614 wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2616 if (!wdh || wdh->file_type_subtype < 0 ||
2617 wdh->file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2618 wtap_file_type_subtype_supports_block(wdh->file_type_subtype, WTAP_BLOCK_NAME_RESOLUTION) == BLOCK_NOT_SUPPORTED)
2619 return false;
2620 wdh->addrinfo_lists = addrinfo_lists;
2621 return true;
2624 void
2625 wtap_dump_discard_name_resolution(wtap_dumper *wdh)
2627 /* As below for DSBs. */
2628 if (wdh->nrbs_growing) {
2630 * Pretend we've written all of them.
2632 wdh->nrbs_growing_written = wdh->nrbs_growing->len;
2636 void
2637 wtap_dump_discard_decryption_secrets(wtap_dumper *wdh)
2640 * This doesn't free the data, as it might be pointed to
2641 * from other structures; it merely marks all of them as
2642 * having been written to the file, so that they don't
2643 * get written by wtap_dump().
2645 * XXX - our APIs for dealing with some metadata, such as
2646 * resolved names, decryption secrets, and interface
2647 * statistics is not very well oriented towards one-pass
2648 * programs; this needs to be cleaned up. See bug 15502.
2650 if (wdh->dsbs_growing) {
2652 * Pretend we've written all of them.
2654 wdh->dsbs_growing_written = wdh->dsbs_growing->len;
2658 void
2659 wtap_dump_discard_sysdig_meta_events(wtap_dumper *wdh)
2661 /* As above for DSBs. */
2662 if (wdh->mevs_growing) {
2664 * Pretend we've written all of them.
2666 wdh->mevs_growing_written = wdh->mevs_growing->len;
2670 /* internally open a file for writing (compressed or not) */
2671 static WFILE_T
2672 wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
2674 switch (wdh->compression_type) {
2675 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2676 case WTAP_GZIP_COMPRESSED:
2677 return gzwfile_open(filename);
2678 #endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
2679 #ifdef HAVE_LZ4FRAME_H
2680 case WTAP_LZ4_COMPRESSED:
2681 return lz4wfile_open(filename);
2682 #endif /* HAVE_LZ4FRAME_H */
2683 default:
2684 return ws_fopen(filename, "wb");
2688 /* internally open a file for writing (compressed or not) */
2689 static WFILE_T
2690 wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
2692 switch (wdh->compression_type) {
2693 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2694 case WTAP_GZIP_COMPRESSED:
2695 return gzwfile_fdopen(fd);
2696 #endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
2697 #ifdef HAVE_LZ4FRAME_H
2698 case WTAP_LZ4_COMPRESSED:
2699 return lz4wfile_fdopen(fd);
2700 #endif /* HAVE_LZ4FRAME_H */
2701 default:
2702 return ws_fdopen(fd, "wb");
2706 /* internally writing raw bytes (compressed or not). Updates wdh->bytes_dumped on success */
2707 bool
2708 wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2710 size_t nwritten;
2712 switch (wdh->compression_type) {
2713 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2714 case WTAP_GZIP_COMPRESSED:
2715 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2717 * gzwfile_write() returns 0 on error.
2719 if (nwritten == 0) {
2720 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2721 return false;
2723 break;
2724 #endif
2725 #ifdef HAVE_LZ4FRAME_H
2726 case WTAP_LZ4_COMPRESSED:
2727 nwritten = lz4wfile_write((LZ4WFILE_T)wdh->fh, buf, bufsize);
2729 * lz4wfile_write() returns 0 on error.
2731 if (nwritten == 0) {
2732 *err = lz4wfile_geterr((LZ4WFILE_T)wdh->fh);
2733 return false;
2735 break;
2736 #endif /* HAVE_LZ4FRAME_H */
2737 default:
2738 errno = WTAP_ERR_CANT_WRITE;
2739 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2741 * At least according to the macOS man page,
2742 * this can return a short count on an error.
2744 if (nwritten != bufsize) {
2745 if (ferror((FILE *)wdh->fh))
2746 *err = errno;
2747 else
2748 *err = WTAP_ERR_SHORT_WRITE;
2749 return false;
2752 wdh->bytes_dumped += bufsize;
2753 return true;
2756 /* internally close a file for writing (compressed or not) */
2757 static int
2758 wtap_dump_file_close(wtap_dumper *wdh)
2760 switch (wdh->compression_type) {
2761 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2762 case WTAP_GZIP_COMPRESSED:
2763 return gzwfile_close((GZWFILE_T)wdh->fh);
2764 #endif
2765 #ifdef HAVE_LZ4FRAME_H
2766 case WTAP_LZ4_COMPRESSED:
2767 return lz4wfile_close((LZ4WFILE_T)wdh->fh);
2768 #endif /* HAVE_LZ4FRAME_H */
2769 default:
2770 return fclose((FILE *)wdh->fh);
2774 int64_t
2775 wtap_dump_file_seek(wtap_dumper *wdh, int64_t offset, int whence, int *err)
2777 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H)
2778 if (wdh->compression_type != WTAP_UNCOMPRESSED) {
2779 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2780 return -1;
2781 } else
2782 #endif
2784 if (-1 == ws_fseek64((FILE *)wdh->fh, offset, whence)) {
2785 *err = errno;
2786 return -1;
2787 } else
2789 return 0;
2794 int64_t
2795 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2797 int64_t rval;
2798 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H)
2799 if (wdh->compression_type != WTAP_UNCOMPRESSED) {
2800 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2801 return -1;
2802 } else
2803 #endif
2805 if (-1 == (rval = ws_ftell64((FILE *)wdh->fh))) {
2806 *err = errno;
2807 return -1;
2808 } else
2810 return rval;
2815 void
2816 cleanup_open_routines(void)
2818 unsigned i;
2819 struct open_info *i_open;
2821 if (open_routines != NULL && open_info_arr) {
2822 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
2823 if (i_open->extensions != NULL)
2824 g_strfreev(i_open->extensions_set);
2827 g_array_free(open_info_arr, true);
2828 open_info_arr = NULL;
2833 * Allow built-in file handlers (but *not* plugin file handlers!) to
2834 * register a "backwards-compatibility" name and file type value, to
2835 * put in the Lua wtap_filetypes table.
2837 * This is only to be used as long as we have that table; new Lua
2838 * code should use wtap_name_to_file_type_subtype() to look up
2839 * file types by their name, just as C code should.
2841 * The backwards-ccmpatibility names are the old WTAP_FILE_TYPE_SUBTYPE_
2842 * #define name, with WTAP_FILE_TYPE_SUBTYPE_ removed.
2845 static GArray *backwards_compatibility_lua_names;
2847 void
2848 // NOLINTNEXTLINE(misc-no-recursion)
2849 wtap_register_backwards_compatibility_lua_name(const char *name, int ft)
2851 struct backwards_compatibiliity_lua_name entry;
2854 * Create the table if it doesn't already exist.
2855 * Use the same size as we do for the file type/subtype table.
2857 if (backwards_compatibility_lua_names == NULL) {
2858 backwards_compatibility_lua_names = g_array_sized_new(false,
2859 true, sizeof(struct backwards_compatibiliity_lua_name),
2860 wtap_module_count*2);
2863 * Extra backwards compatibility hack - add entries
2864 * for time stamp precision values(!), as well as
2865 * for "UNKNOWN" and types that don't yet register
2866 * themselves.
2868 * If new WS_TSPREC_ value are added, don't bother
2869 * adding them to this table; any Lua program that
2870 * would use them should use the wtap_tsprecs type.
2872 * (Recursion: see "recursion".)
2874 wtap_register_backwards_compatibility_lua_name("TSPREC_SEC",
2875 WTAP_TSPREC_SEC);
2876 wtap_register_backwards_compatibility_lua_name("TSPREC_DSEC",
2877 WTAP_TSPREC_100_MSEC);
2878 wtap_register_backwards_compatibility_lua_name("TSPREC_CSEC",
2879 WTAP_TSPREC_10_MSEC);
2880 wtap_register_backwards_compatibility_lua_name("TSPREC_MSEC",
2881 WTAP_TSPREC_MSEC);
2882 wtap_register_backwards_compatibility_lua_name("TSPREC_USEC",
2883 WTAP_TSPREC_USEC);
2884 wtap_register_backwards_compatibility_lua_name("TSPREC_NSEC",
2885 WTAP_TSPREC_NSEC);
2886 wtap_register_backwards_compatibility_lua_name("UNKNOWN",
2887 WTAP_FILE_TYPE_SUBTYPE_UNKNOWN);
2889 entry.name = name;
2890 entry.ft = ft;
2891 g_array_append_val(backwards_compatibility_lua_names, entry);
2894 const GArray *
2895 get_backwards_compatibility_lua_table(void)
2897 return backwards_compatibility_lua_names;
2901 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2903 * Local variables:
2904 * c-basic-offset: 8
2905 * tab-width: 8
2906 * indent-tabs-mode: t
2907 * End:
2909 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2910 * :indentSize=8:tabSize=8:noTabs=false: