Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/wiretap/file_access.c
Line
Count
Source
1
/* file_access.c
2
 *
3
 * Wiretap Library
4
 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5
 *
6
 * SPDX-License-Identifier: GPL-2.0-or-later
7
 */
8
9
#include "config.h"
10
0
#define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP
11
#include "wtap-int.h"
12
13
#include <assert.h>
14
15
#include <string.h>
16
#include <stdlib.h>
17
18
#include <errno.h>
19
20
#include <wsutil/file_util.h>
21
#include <wsutil/file_compressed.h>
22
#include <wsutil/tempfile.h>
23
#ifdef HAVE_PLUGINS
24
#include <wsutil/plugins.h>
25
#endif
26
#include <wsutil/ws_assert.h>
27
28
#include "wtap_module.h"
29
#include "wtap_modules.h"
30
#include "file_wrappers.h"
31
#include "required_file_handlers.h"
32
#include <wsutil/array.h>
33
#include <wsutil/buffer.h>
34
#include <wsutil/str_util.h>
35
36
#include "lanalyzer.h"
37
#include "ngsniffer.h"
38
#include "radcom.h"
39
#include "ascendtext.h"
40
#include "nettl.h"
41
#include "libpcap.h"
42
#include "snoop.h"
43
#include "iptrace.h"
44
#include "iseries.h"
45
#include "netmon.h"
46
#include "netxray.h"
47
#include "toshiba.h"
48
#include "eyesdn.h"
49
#include "i4btrace.h"
50
#include "csids.h"
51
#include "pppdump.h"
52
#include "peekclassic.h"
53
#include "peektagged.h"
54
#include "vms.h"
55
#include "dbs-etherwatch.h"
56
#include "visual.h"
57
#include "cosine.h"
58
#include "5views.h"
59
#include "erf.h"
60
#include "hcidump.h"
61
#include "logcat.h"
62
#include "logcat_text.h"
63
#include "json.h"
64
#include "json_log.h"
65
#include "mmodule.h"
66
#include "observer.h"
67
#include "k12.h"
68
#include "ber.h"
69
#include "catapult_dct2000.h"
70
#include "mp4.h"
71
#include "mp2t.h"
72
#include "mpeg.h"
73
#include "netscreen.h"
74
#include "commview.h"
75
#include "pcapng.h"
76
#include "aethra.h"
77
#include "btsnoop.h"
78
#include "tnef.h"
79
#include "dct3trace.h"
80
#include "packetlogger.h"
81
#include "daintree-sna.h"
82
#include "netscaler.h"
83
#include "mime_file.h"
84
#include "ipfix.h"
85
#include "vwr.h"
86
#include "camins.h"
87
#include "stanag4607.h"
88
#include "capsa.h"
89
#include "nettrace_3gpp_32_423.h"
90
#include "mplog.h"
91
#include "dpa400.h"
92
#include "rfc7468.h"
93
#include "ruby_marshal.h"
94
#include "systemd_journal.h"
95
#include "log3gpp.h"
96
#include "candump.h"
97
#include "busmaster.h"
98
#include "cllog.h"
99
#include "blf.h"
100
#include "eri_enb_log.h"
101
#include "autosar_dlt.h"
102
#include "rtpdump.h"
103
#include "ems.h"
104
#include "ttl.h"
105
#include "peak-trc.h"
106
#include "netlog.h"
107
#include "procmon.h"
108
109
/*
110
 * Add an extension, and all compressed versions thereof if requested,
111
 * to a GSList of extensions.
112
 */
113
static GSList *
114
add_extensions(GSList *extensions, const char *extension,
115
    GSList *compression_type_extensions)
116
0
{
117
  /*
118
   * Add the specified extension.
119
   */
120
0
  extensions = g_slist_prepend(extensions, g_strdup(extension));
121
122
  /*
123
   * Add whatever compressed versions we were supplied.
124
   */
125
0
  for (GSList *compression_type_extension = compression_type_extensions;
126
0
      compression_type_extension != NULL;
127
0
      compression_type_extension = g_slist_next(compression_type_extension)) {
128
0
    extensions = g_slist_prepend(extensions,
129
0
        ws_strdup_printf("%s.%s", extension,
130
0
            (const char *)compression_type_extension->data));
131
0
  }
132
133
0
  return extensions;
134
0
}
135
136
static const struct file_extension_info* file_type_extensions;
137
138
static GArray* file_type_extensions_arr;
139
140
void
141
wtap_init_file_type_extensions(const struct file_extension_info* file_extensions, unsigned num_extensions)
142
14
{
143
14
  file_type_extensions_arr = g_array_new(false,true,sizeof(struct file_extension_info));
144
145
14
  g_array_append_vals(file_type_extensions_arr, file_extensions, num_extensions);
146
147
14
  file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
148
14
}
149
150
void
151
wtap_register_file_type_extension(const struct file_extension_info *ei)
152
0
{
153
0
  g_array_append_val(file_type_extensions_arr,*ei);
154
155
0
  file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
156
0
}
157
158
int
159
wtap_get_num_file_type_extensions(void)
160
0
{
161
0
  return file_type_extensions_arr->len;
162
0
}
163
164
const char *
165
wtap_get_file_extension_type_name(int extension_type)
166
0
{
167
0
  return file_type_extensions[extension_type].name;
168
0
}
169
170
static GSList *
171
add_extensions_for_file_extensions_type(int extension_type, GSList *extensions,
172
    GSList *compression_type_extensions)
173
0
{
174
0
  char **extensions_set, **extensionp, *extension;
175
176
  /*
177
   * Split the extension-list string into a set of extensions.
178
   */
179
0
  extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
180
0
      ";", 0);
181
182
  /*
183
   * Add each of those extensions to the list.
184
   */
185
0
  for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
186
0
    extension = *extensionp;
187
188
    /*
189
     * Add the extension, and all compressed variants
190
     * of it.
191
     */
192
0
    extensions = add_extensions(extensions, extension,
193
0
        compression_type_extensions);
194
0
  }
195
196
0
  g_strfreev(extensions_set);
197
0
  return extensions;
198
0
}
199
200
/* Return a list of file extensions that are used by the specified file
201
 * extension type.
202
 *
203
 * All strings in the list are allocated with g_malloc() and must be freed
204
 * with g_free().
205
 */
206
GSList *
207
wtap_get_file_extension_type_extensions(unsigned extension_type)
208
0
{
209
0
  GSList *extensions, *compression_type_extensions;
210
211
0
  if (extension_type >= file_type_extensions_arr->len)
212
0
    return NULL; /* not a valid extension type */
213
214
0
  extensions = NULL; /* empty list, to start with */
215
216
  /*
217
   * Get compression-type extensions, if any.
218
   */
219
0
  compression_type_extensions = ws_get_all_compression_type_extensions_list();
220
221
  /*
222
   * Add all this file extension type's extensions, with compressed
223
   * variants.
224
   */
225
0
  extensions = add_extensions_for_file_extensions_type(extension_type,
226
0
      extensions, compression_type_extensions);
227
228
0
  g_slist_free(compression_type_extensions);
229
230
0
  return g_slist_reverse(extensions);
231
0
}
232
233
/*
234
 * The open_file_* routines must return:
235
 *
236
 *  WTAP_OPEN_ERROR on an I/O error;
237
 *
238
 *  WTAP_OPEN_MINE if the file they're reading is one of the types
239
 *      it handles;
240
 *
241
 *  WTAP_OPEN_NOT_MINE if the file they're reading isn't the type
242
 *      they're checking for.
243
 *
244
 * If the routine handles this type of file, it must set the "file_type"
245
 * field in the "struct wtap" to the type of the file.
246
 *
247
 * Note that the routine does *not* have to free the private data pointer on
248
 * error. The caller takes care of that by calling wtap_close on error.
249
 * (See https://gitlab.com/wireshark/wireshark/-/issues/8518)
250
 *
251
 * However, the caller *does* have to free the private data pointer when
252
 * returning WTAP_OPEN_NOT_MINE, since the next file type will be called
253
 * and will likely just overwrite the pointer.
254
 *
255
 * The names are used in file open dialogs to select, for files that
256
 * don't have magic numbers and that could potentially be files of
257
 * more than one type based on the heuristics, a particular file
258
 * type to interpret it as, if the file name has no extension, the
259
 * extension isn't sufficient to determine the appropriate file type,
260
 * or the extension is wrong.
261
 *
262
 * NOTE: when adding file formats to this list you may also want to add them
263
 * to the following files so that the various desktop environments will
264
 * know that Wireshark can open the file:
265
 *  1) resources/freedesktop/org.wireshark.Wireshark-mime.xml (for freedesktop.org environments)
266
 *  2) packaging/macosx/WiresharkInfo.plist.in (for macOS)
267
 *
268
 * If your file format has a commonly-used extension (e.g., ".pcap") then you
269
 * should probably also add it to file_type_extensions_base[] (in this file),
270
 * to the list of "<glob pattern=...>" entries for this file format in
271
 * resources/freedesktop/org.wireshark.Wireshark-mime.xml, to the
272
 * CFBundleTypeExtensions array for this file format in
273
 * packaging/macosx/WiresharkInfo.plist, and to the PushFileExtensions macro
274
 * in packaging/nsis/wireshark-common.nsh and the File Associations in
275
 * packaging/wix/ComponentGroups.wxi (for Windows).
276
 */
277
static const struct open_info open_info_base[] = {
278
  /* Open routines that look for magic numbers */
279
  { "Wireshark/tcpdump/... - pcap",           OPEN_INFO_MAGIC,     libpcap_open,             NULL,   NULL, NULL },
280
  { "Wireshark/... - pcapng",                 OPEN_INFO_MAGIC,     pcapng_open,              NULL, NULL, NULL },
281
  { "Sniffer (DOS)",                          OPEN_INFO_MAGIC,     ngsniffer_open,           NULL,       NULL, NULL },
282
  { "Snoop, Shomiti/Finisar Surveyor",        OPEN_INFO_MAGIC,     snoop_open,               NULL,       NULL, NULL },
283
  { "AIX iptrace",                            OPEN_INFO_MAGIC,     iptrace_open,             NULL,       NULL, NULL },
284
  { "Microsoft Network Monitor",              OPEN_INFO_MAGIC,     netmon_open,              NULL,       NULL, NULL },
285
  { "Cinco NetXray/Sniffer (Windows)",        OPEN_INFO_MAGIC,     netxray_open,             NULL,       NULL, NULL },
286
  { "RADCOM WAN/LAN analyzer",                OPEN_INFO_MAGIC,     radcom_open,              NULL,       NULL, NULL },
287
  { "HP-UX nettl trace",                      OPEN_INFO_MAGIC,     nettl_open,               NULL,       NULL, NULL },
288
  { "Visual Networks traffic capture",        OPEN_INFO_MAGIC,     visual_open,              NULL,       NULL, NULL },
289
  { "InfoVista 5View capture",                OPEN_INFO_MAGIC,     _5views_open,             NULL,       NULL, NULL },
290
  { "Viavi Observer",                         OPEN_INFO_MAGIC,     observer_open,            NULL,       NULL, NULL },
291
  { "Savvius tagged",                         OPEN_INFO_MAGIC,     peektagged_open,          NULL,       NULL, NULL },
292
  { "Colasoft Capsa",                         OPEN_INFO_MAGIC,     capsa_open,               NULL,       NULL, NULL },
293
  { "DBS Etherwatch (VMS)",                   OPEN_INFO_MAGIC,     dbs_etherwatch_open,      NULL,       NULL, NULL },
294
  { "Tektronix K12xx 32-bit .rf5 format",     OPEN_INFO_MAGIC,     k12_open,                 NULL,       NULL, NULL },
295
  { "Catapult DCT2000 trace (.out format)",   OPEN_INFO_MAGIC,     catapult_dct2000_open,    NULL,       NULL, NULL },
296
  { "Aethra .aps file",                       OPEN_INFO_MAGIC,     aethra_open,              NULL,       NULL, NULL },
297
  { "Symbian OS btsnoop",                     OPEN_INFO_MAGIC,     btsnoop_open,             "log",      NULL, NULL },
298
  { "EyeSDN USB S0/E1 ISDN trace format",     OPEN_INFO_MAGIC,     eyesdn_open,              NULL,       NULL, NULL },
299
  { "Transport-Neutral Encapsulation Format", OPEN_INFO_MAGIC,     tnef_open,                NULL,       NULL, NULL },
300
  /* 3GPP TS 32.423 Trace must come before MIME Files as it's XML based*/
301
  { "3GPP TS 32.423 Trace format",            OPEN_INFO_MAGIC,     nettrace_3gpp_32_423_file_open, NULL, NULL, NULL },
302
  /* Gammu DCT3 trace must come before MIME files as it's XML based*/
303
  { "Gammu DCT3 trace",                       OPEN_INFO_MAGIC,     dct3trace_open,           NULL,       NULL, NULL },
304
  { "BLF Logfile",                            OPEN_INFO_MAGIC,     blf_open,                 NULL,     NULL, NULL },
305
  { "AUTOSAR DLT Logfile",                    OPEN_INFO_MAGIC,     autosar_dlt_open,         NULL,     NULL, NULL },
306
  { "TTL Logfile",                            OPEN_INFO_MAGIC,     ttl_open,                 NULL,     NULL, NULL },
307
  { "RTPDump files",                          OPEN_INFO_MAGIC,     rtpdump_open,             NULL, NULL, NULL },
308
  { "MIME Files Format",                      OPEN_INFO_MAGIC,     mime_file_open,           NULL,       NULL, NULL },
309
  { "Micropross mplog",                       OPEN_INFO_MAGIC,     mplog_open,               NULL,   NULL, NULL },
310
  { "Unigraf DPA-400 capture",                OPEN_INFO_MAGIC,     dpa400_open,              NULL,       NULL, NULL },
311
  { "RFC 7468 files",                         OPEN_INFO_MAGIC,     rfc7468_open,             NULL,  NULL, NULL },
312
  { "MS Procmon Files",                       OPEN_INFO_MAGIC,     procmon_open,             NULL,  NULL, NULL },
313
314
  /* Open routines that have no magic numbers and require heuristics. */
315
  { "Novell LANalyzer",                       OPEN_INFO_HEURISTIC, lanalyzer_open,           "tr1",      NULL, NULL },
316
  /*
317
   * PacketLogger must come before MPEG, because its files
318
   * are sometimes grabbed by mpeg_open.
319
   */
320
  { "macOS PacketLogger",                     OPEN_INFO_HEURISTIC, packetlogger_open,        "pklg",     NULL, NULL },
321
  /* Some MPEG files have magic numbers, others just have heuristics. */
322
  { "MPEG",                                   OPEN_INFO_HEURISTIC, mpeg_open,                "mpeg;mpg;mp3",  NULL, NULL },
323
  { "Daintree SNA",                           OPEN_INFO_HEURISTIC, daintree_sna_open,        "dcf",      NULL, NULL },
324
  { "STANAG 4607 Format",                     OPEN_INFO_HEURISTIC, stanag4607_open,          NULL,       NULL, NULL },
325
  { "ASN.1 Basic Encoding Rules",             OPEN_INFO_HEURISTIC, ber_open,                 NULL,       NULL, NULL },
326
  /*
327
   * I put NetScreen *before* erf, because there were some
328
   * false positives with my test-files (Sake Blok, July 2007)
329
   *
330
   * I put VWR *after* ERF, because there were some cases where
331
   * ERF files were misidentified as vwr files (Stephen
332
   * Donnelly, August 2013; see bug 9054)
333
   *
334
   * I put VWR *after* Peek Classic, CommView, iSeries text,
335
   * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler,
336
   * because there were some cases where files of those types were
337
   * misidentified as vwr files (Guy Harris, December 2013)
338
   */
339
  { "NetScreen snoop text file",              OPEN_INFO_HEURISTIC, netscreen_open,           "txt",      NULL, NULL },
340
  { "Endace ERF capture",                     OPEN_INFO_HEURISTIC, erf_open,                 "erf",      NULL, NULL },
341
  { "IPFIX File Format",                      OPEN_INFO_HEURISTIC, ipfix_open,               "pfx;ipfix",NULL, NULL },
342
  { "K12 text file",                          OPEN_INFO_HEURISTIC, k12text_open,             "txt",      NULL, NULL },
343
  { "Savvius classic",                        OPEN_INFO_HEURISTIC, peekclassic_open,         "pkt;tpc;apc;wpz", NULL, NULL },
344
  { "pppd log (pppdump format)",              OPEN_INFO_HEURISTIC, pppdump_open,             NULL,       NULL, NULL },
345
  { "IBM iSeries comm. trace",                OPEN_INFO_HEURISTIC, iseries_open,             "txt",      NULL, NULL },
346
  { "I4B ISDN trace",                         OPEN_INFO_HEURISTIC, i4btrace_open,            NULL,       NULL, NULL },
347
  { "MPEG2 transport stream",                 OPEN_INFO_HEURISTIC, mp2t_open,                "mp2t;ts;mpg",   NULL, NULL },
348
  { "CSIDS IPLog",                            OPEN_INFO_HEURISTIC, csids_open,               NULL,       NULL, NULL },
349
  { "TCPIPtrace (VMS)",                       OPEN_INFO_HEURISTIC, vms_open,                 "txt",      NULL, NULL },
350
  { "CoSine IPSX L2 capture",                 OPEN_INFO_HEURISTIC, cosine_open,              "txt",      NULL, NULL },
351
  { "Bluetooth HCI dump",                     OPEN_INFO_HEURISTIC, hcidump_open,             NULL,       NULL, NULL },
352
  { "TamoSoft CommView NCF",                  OPEN_INFO_HEURISTIC, commview_ncf_open,        "ncf",      NULL, NULL },
353
  { "TamoSoft CommView NCFX",                 OPEN_INFO_HEURISTIC, commview_ncfx_open,       "ncfx",      NULL, NULL },
354
  { "NetScaler",                              OPEN_INFO_HEURISTIC, nstrace_open,             "cap",      NULL, NULL },
355
  { "Android Logcat Binary format",           OPEN_INFO_HEURISTIC, logcat_open,              "logcat",   NULL, NULL },
356
  { "Android Logcat Text formats",            OPEN_INFO_HEURISTIC, logcat_text_open,         "txt",      NULL, NULL },
357
  { "Candump log",                            OPEN_INFO_HEURISTIC, candump_open,             NULL,       NULL, NULL },
358
  { "Busmaster log",                          OPEN_INFO_HEURISTIC, busmaster_open,           NULL,       NULL, NULL },
359
  { "CSS Electronics CLX000 CAN log",         OPEN_INFO_MAGIC,     cllog_open,               "txt",      NULL, NULL },
360
  { "Ericsson eNode-B raw log",               OPEN_INFO_MAGIC,     eri_enb_log_open,         NULL,       NULL, NULL },
361
  { "Systemd Journal",                        OPEN_INFO_HEURISTIC, systemd_journal_open,     "log;jnl;journal",      NULL, NULL },
362
  { "PEAK CAN TRC log",                       OPEN_INFO_HEURISTIC, peak_trc_open,            "trc",      NULL, NULL },
363
364
  /* ASCII trace files from Telnet sessions. */
365
  { "Lucent/Ascend access server trace",      OPEN_INFO_HEURISTIC, ascend_open,              "txt",      NULL, NULL },
366
  { "Toshiba Compact ISDN Router snoop",      OPEN_INFO_HEURISTIC, toshiba_open,             "txt",      NULL, NULL },
367
368
  { "EGNOS Message Server (EMS) file",        OPEN_INFO_HEURISTIC, ems_open,                 "ems",      NULL, NULL },
369
370
  /* NetLog needs to be before JSON because it is a specifically formatted JSON file */
371
  { "NetLog",                                 OPEN_INFO_HEURISTIC, netlog_open,              "json",     NULL, NULL },
372
  /* JSON Log needs to be before JSON because it handles a variety of JSON logs */
373
  { "JSON Log",                               OPEN_INFO_HEURISTIC, json_log_open,            "json;jsonl;log", NULL, NULL },
374
  { "JavaScript Object Notation",             OPEN_INFO_HEURISTIC, json_open,                "json",     NULL, NULL },
375
  { "Bachmann M-Module File",                 OPEN_INFO_HEURISTIC, mmodule_open,             "m",        NULL, NULL },
376
  { "Ruby Marshal Object",                    OPEN_INFO_HEURISTIC, ruby_marshal_open,        "",         NULL, NULL },
377
  { "3gpp phone log",                         OPEN_INFO_MAGIC,     log3gpp_open,             "log",      NULL, NULL },
378
  { "MP4 media file",                         OPEN_INFO_MAGIC,     mp4_open,                 "mp4",      NULL, NULL },
379
  /* Extremely weak heuristics - put them at the end. */
380
  { "Ixia IxVeriWave .vwr Raw Capture",       OPEN_INFO_HEURISTIC, vwr_open,                 "vwr",      NULL, NULL },
381
  { "CAM Inspector file",                     OPEN_INFO_HEURISTIC, camins_open,              "camins",   NULL, NULL },
382
};
383
384
/* this is only used to build the dynamic array on load, do NOT use this
385
 * for anything else, because the size of the actual array will change if
386
 * Lua scripts register a new file reader.
387
 */
388
14
#define N_OPEN_INFO_ROUTINES  array_length(open_info_base)
389
390
static GArray *open_info_arr;
391
392
/* this always points to the top of the created array */
393
struct open_info *open_routines;
394
395
/* this points to the first OPEN_INFO_HEURISTIC type in the array */
396
static unsigned heuristic_open_routine_idx;
397
398
static void
399
set_heuristic_routine(void)
400
14
{
401
14
  unsigned i;
402
14
  ws_assert(open_info_arr != NULL);
403
404
462
  for (i = 0; i < open_info_arr->len; i++) {
405
462
    if (open_routines[i].type == OPEN_INFO_HEURISTIC) {
406
14
      heuristic_open_routine_idx = i;
407
14
      break;
408
14
    }
409
    /* sanity check */
410
448
    ws_assert(open_routines[i].type == OPEN_INFO_MAGIC);
411
448
  }
412
413
14
  ws_assert(heuristic_open_routine_idx > 0);
414
14
}
415
416
void
417
init_open_routines(void)
418
14
{
419
14
  unsigned int i;
420
14
  struct open_info *i_open;
421
422
14
  if (open_info_arr)
423
0
    return;
424
425
14
  open_info_arr = g_array_new(true,true,sizeof(struct open_info));
426
427
14
  g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES);
428
429
14
  open_routines = (struct open_info *)(void*) open_info_arr->data;
430
431
  /* Populate the extensions_set list now */
432
1.05k
  for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
433
1.03k
    if (i_open->extensions != NULL)
434
476
      i_open->extensions_set = g_strsplit(i_open->extensions, ";", 0);
435
1.03k
  }
436
437
14
  set_heuristic_routine();
438
14
}
439
440
/*
441
 * Registers a new file reader - currently only called by wslua code for
442
 * Lua readers and by compiled file reader plugins.
443
 *
444
 * If first_routine is true, the reader added before other readers of its
445
 * type (magic or heuristic).  This should be done only in cases where
446
 * this reader's open test must be performed early, to avoid false
447
 * positives for other readers' tests treating files for this reader
448
 * as being for another reader.
449
 *
450
 * XXX - given that there is no guarantee that registration routines will
451
 * be called in a given order, all this really does is divide readers for
452
 * a given type (magic or heuristic) into two categories, with open routines
453
 * for readers in the first category (first_routine true) all being called
454
 * before readers in the second category; it does not guarantee a particular
455
 * total order for open routines.
456
 *
457
 * Checks for an existing reader of the same name and errors if it finds one;
458
 * if you want to handle that condition more gracefully, call
459
 * wtap_has_open_info() first.
460
 */
461
void
462
wtap_register_open_info(struct open_info *oi, const bool first_routine)
463
0
{
464
0
  if (!oi || !oi->name) {
465
0
    ws_error("No open_info name given to register");
466
0
    return;
467
0
  }
468
469
  /* verify name doesn't already exist */
470
0
  if (wtap_has_open_info(oi->name)) {
471
0
    ws_error("Name given to register_open_info already exists");
472
0
    return;
473
0
  }
474
475
0
  if (oi->extensions != NULL)
476
0
    oi->extensions_set = g_strsplit(oi->extensions, ";", 0);
477
478
  /* if it's magic and first, prepend it; if it's heuristic and not first,
479
     append it; if it's anything else, stick it in the middle */
480
0
  if (first_routine && oi->type == OPEN_INFO_MAGIC) {
481
0
    g_array_prepend_val(open_info_arr, *oi);
482
0
  } else if (!first_routine && oi->type == OPEN_INFO_HEURISTIC) {
483
0
    g_array_append_val(open_info_arr, *oi);
484
0
  } else {
485
0
    g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi);
486
0
  }
487
488
0
  open_routines = (struct open_info *)(void*) open_info_arr->data;
489
0
  set_heuristic_routine();
490
0
}
491
492
/* De-registers a file reader by removing it from the GArray based on its name.
493
 * This function must NOT be called during wtap_open_offline(), since it changes the array.
494
 * Note: this function will error if it doesn't find the given name; if you want to handle
495
 * that condition more gracefully, call wtap_has_open_info() first.
496
 */
497
void
498
wtap_deregister_open_info(const char *name)
499
0
{
500
0
  unsigned i;
501
502
0
  if (!name) {
503
0
    ws_error("Missing open_info name to de-register");
504
0
    return;
505
0
  }
506
507
0
  for (i = 0; i < open_info_arr->len; i++) {
508
0
    if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
509
0
      g_strfreev(open_routines[i].extensions_set);
510
0
      open_info_arr = g_array_remove_index(open_info_arr, i);
511
0
      set_heuristic_routine();
512
0
      return;
513
0
    }
514
0
  }
515
516
0
  ws_error("deregister_open_info: name not found");
517
0
}
518
519
/* Determines if a open routine short name already exists
520
 */
521
bool
522
wtap_has_open_info(const char *name)
523
0
{
524
0
  unsigned i;
525
526
0
  if (!name) {
527
0
    ws_error("No name given to wtap_has_open_info!");
528
0
    return false;
529
0
  }
530
531
532
0
  for (i = 0; i < open_info_arr->len; i++) {
533
0
    if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
534
0
      return true;
535
0
    }
536
0
  }
537
538
0
  return false;
539
0
}
540
541
bool
542
wtap_uses_lua_filehandler(const wtap* wth)
543
0
{
544
0
  if (wth && wth->wslua_data != NULL) {
545
    /*
546
     * Currently, wslua_data is set if and only if using a Lua
547
     * file handler.
548
     */
549
0
    return true;
550
0
  }
551
552
0
  return false;
553
0
}
554
555
/*
556
 * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
557
 * define them either.)
558
 *
559
 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
560
 */
561
#ifndef S_ISREG
562
#define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
563
#endif
564
#ifndef S_IFIFO
565
#define S_IFIFO _S_IFIFO
566
#endif
567
#ifndef S_ISFIFO
568
#define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
569
#endif
570
#ifndef S_ISDIR
571
#define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
572
#endif
573
574
/* returns the 'type' number to use for wtap_open_offline based on the
575
 * passed-in name (the name in the open_info struct). It returns WTAP_TYPE_AUTO
576
 * on failure, which is the number 0. The 'type' number is the entry's index+1,
577
 * because that's what wtap_open_offline() expects it to be.
578
 */
579
unsigned int
580
open_info_name_to_type(const char *name)
581
0
{
582
0
  unsigned int i;
583
584
0
  if (!name)
585
0
    return WTAP_TYPE_AUTO;
586
587
0
  for (i = 0; i < open_info_arr->len; i++) {
588
0
    if (open_routines[i].name != NULL &&
589
0
        strcmp(name, open_routines[i].name) == 0)
590
0
      return i+1;
591
0
  }
592
593
0
  return WTAP_TYPE_AUTO; /* no such file type */
594
0
}
595
596
static char *
597
get_file_extension(const char *pathname)
598
0
{
599
0
  char *filename;
600
0
  char **components;
601
0
  size_t ncomponents;
602
0
  char *extensionp;
603
604
  /*
605
   * Is the pathname empty?
606
   */
607
0
  if (strcmp(pathname, "") == 0)
608
0
    return NULL; /* no extension */
609
610
  /*
611
   * Find the last component of the pathname.
612
   */
613
0
  filename = g_path_get_basename(pathname);
614
615
  /*
616
   * Does it have an extension?
617
   */
618
0
  if (strchr(filename, '.') == NULL) {
619
0
    g_free(filename);
620
0
    return NULL; /* no extension whatsoever */
621
0
  }
622
623
  /*
624
   * Yes. Fold it to lowercase, since open_routines[] has
625
   * its extensions in lowercase.
626
   */
627
0
  ascii_strdown_inplace(filename);
628
629
  /*
630
   * Split it into components separated by ".".
631
   */
632
0
  components = g_strsplit(filename, ".", 0);
633
0
  g_free(filename);
634
635
  /*
636
   * Count the components.
637
   */
638
0
  for (ncomponents = 0; components[ncomponents] != NULL; ncomponents++)
639
0
    ;
640
641
0
  if (ncomponents == 0) {
642
0
    g_strfreev(components);
643
0
    return NULL; /* no components */
644
0
  }
645
0
  if (ncomponents == 1) {
646
0
    g_strfreev(components);
647
0
    return NULL; /* only one component, with no "." */
648
0
  }
649
650
  /*
651
   * Get compression-type extensions, if any.
652
   */
653
0
  GSList *compression_type_extensions = ws_get_all_compression_type_extensions_list();
654
655
  /*
656
   * Is the last component one of the extensions used for compressed
657
   * files?
658
   */
659
0
  extensionp = components[ncomponents - 1];
660
0
  for (GSList *compression_type_extension = compression_type_extensions;
661
0
      compression_type_extension != NULL;
662
0
      compression_type_extension = g_slist_next(compression_type_extension)) {
663
0
    if (strcmp(extensionp, (const char *)compression_type_extension->data) == 0) {
664
      /*
665
       * Yes, so it's one of the compressed-file extensions.
666
       * Is there an extension before that?
667
       */
668
0
      if (ncomponents == 2) {
669
0
        g_slist_free(compression_type_extensions);
670
0
        g_strfreev(components);
671
0
        return NULL; /* no, only two components */
672
0
      }
673
674
      /*
675
       * Yes, return that extension.
676
       */
677
0
      g_slist_free(compression_type_extensions);
678
0
      extensionp = g_strdup(components[ncomponents - 2]);
679
0
      g_strfreev(components);
680
0
      return extensionp;
681
0
    }
682
0
  }
683
684
0
  g_slist_free(compression_type_extensions);
685
686
  /*
687
   * The extension isn't one of the compressed-file extensions;
688
   * return it.
689
   */
690
0
  extensionp = g_strdup(extensionp);
691
0
  g_strfreev(components);
692
0
  return extensionp;
693
0
}
694
695
/*
696
 * Check if file extension is used in this heuristic
697
 */
698
static bool
699
heuristic_uses_extension(unsigned int i, const char *extension)
700
0
{
701
0
  char **extensionp;
702
703
  /*
704
   * Does this file type *have* any extensions?
705
   */
706
0
  if (open_routines[i].extensions == NULL)
707
0
    return false; /* no */
708
709
  /*
710
   * Check each of them against the specified extension.
711
   */
712
0
  for (extensionp = open_routines[i].extensions_set; *extensionp != NULL;
713
0
      extensionp++) {
714
0
    if (strcmp(extension, *extensionp) == 0) {
715
0
      return true; /* it's one of them */
716
0
    }
717
0
  }
718
719
0
  return false; /* it's not one of them */
720
0
}
721
722
/*
723
 * Attempt to open the file corresponding to "wth" using the file format
724
 * handler in "candidate".
725
 *
726
 * Returns WTAP_OPEN_MINE upon success, WTAP_OPEN_NOT_MINE if the file is not
727
 * in a suitable format for "candidate", or WTAP_OPEN_ERROR if a failure
728
 * occurred while reading the input.
729
 */
730
static int
731
try_one_open(wtap *wth, const struct open_info *candidate, int *err, char **err_info)
732
0
{
733
  /* Seek back to the beginning of the file; the open routine for the
734
   * previous file type may have left the file position somewhere other
735
   * than the beginning, and the open routine for this file type will
736
   * probably want to start reading at the beginning.
737
   *
738
   * Initialize the data offset while we're at it.
739
   */
740
0
  if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
741
    /* Error - give up */
742
0
    return WTAP_OPEN_ERROR;
743
0
  }
744
745
  /* Set wth with wslua data if any - this is how we pass the data to the
746
   * file reader, kinda like the priv member but not free'd later.
747
   * It's ok for this to copy a NULL.
748
   */
749
0
  wth->wslua_data = candidate->wslua_data;
750
751
0
  return candidate->open_routine(wth, err, err_info);
752
0
}
753
754
/*
755
 * Attempt to open the file corresponding to "wth".  If "type" is supplied
756
 * (i.e. other than WTAP_TYPE_AUTO), that will be the only type attempted.
757
 * Otherwise, heuristic detection of the file format will be performed,
758
 * possibly guided by the extension part of "filename".
759
 *
760
 * Returns WTAP_OPEN_MINE upon success, WTAP_OPEN_NOT_MINE if it was not
761
 * possible to determine a suitable format for the file, or WTAP_OPEN_ERROR if
762
 * a failure occurred while reading the input.
763
 */
764
static int
765
try_open(wtap *wth, unsigned int type, int *err, char **err_info)
766
0
{
767
0
  int result = WTAP_OPEN_NOT_MINE;
768
0
  unsigned i;
769
0
  char *extension;
770
771
  /* 'type' is 1-based. */
772
0
  if (type != WTAP_TYPE_AUTO && type <= open_info_arr->len) {
773
    /* Try only the specified type. */
774
0
    return try_one_open(wth, &open_routines[type - 1], err, err_info);
775
0
  }
776
777
  /* First, all file types that support magic numbers. */
778
0
  for (i = 0; i < heuristic_open_routine_idx && result == WTAP_OPEN_NOT_MINE; i++) {
779
0
    result = try_one_open(wth, &open_routines[i], err, err_info);
780
0
  }
781
782
0
  if (result != WTAP_OPEN_NOT_MINE) {
783
0
    return result;
784
0
  }
785
786
  /* Does this file's name have an extension? */
787
0
  extension = get_file_extension(wth->pathname);
788
0
  if (extension != NULL) {
789
0
    unsigned pass;
790
791
    /*
792
     * Yes, the filename has an extension.
793
     *
794
     * The heuristic types fall into one of three categories, which
795
     * we attempt in order by scanning for each category in turn.
796
     *
797
     * First pass selects the heuristic types that list this file's
798
     * extension, as these are most likely to be the correct choice
799
     * for this file.
800
     *
801
     * Second pass selects heuristic types which have no
802
     * extensions.  We try those before the ones that have
803
     * extensions that *don't* match this file's extension, on the
804
     * theory that files of those types generally have one of the
805
     * type's extensions, and, as this file *doesn't* have one of
806
     * those extensions, it's probably *not* one of those files.
807
     *
808
     * Third pass selects heuristic types which support extensions
809
     * but where none of them matches this file's extension.
810
     *
811
     * We need only continue searching until we find a match or an
812
     * error occurs.
813
     */
814
815
0
    for (pass = 0; pass < 3 && result == WTAP_OPEN_NOT_MINE; pass++) {
816
0
      for (i = heuristic_open_routine_idx; i < open_info_arr->len && result == WTAP_OPEN_NOT_MINE; i++) {
817
0
        if (   (pass == 0 && heuristic_uses_extension(i, extension))
818
0
            || (pass == 1 && open_routines[i].extensions == NULL)
819
0
            || (pass == 2 && open_routines[i].extensions != NULL
820
0
                          && !heuristic_uses_extension(i, extension))) {
821
0
          result = try_one_open(wth, &open_routines[i], err, err_info);
822
0
        }
823
0
      }
824
0
    }
825
826
0
    g_free(extension);
827
0
  } else {
828
    /* No extension.  Try all the heuristic types in order. */
829
0
    for (i = heuristic_open_routine_idx; i < open_info_arr->len && result == WTAP_OPEN_NOT_MINE; i++) {
830
0
      result = try_one_open(wth, &open_routines[i], err, err_info);
831
0
    }
832
0
  }
833
834
0
  return result;
835
0
}
836
837
/* Opens a file and prepares a wtap struct.
838
 * If "do_random" is true, it opens the file twice; the second open
839
 * allows the application to do random-access I/O without moving
840
 * the seek offset for sequential I/O, which is used by Wireshark
841
 * so that it can do sequential I/O to a capture file that's being
842
 * written to as new packets arrive independently of random I/O done
843
 * to display protocol trees for packets when they're selected.
844
 */
845
wtap *
846
wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_info,
847
      bool do_random, const char* app_env_var_prefix)
848
0
{
849
0
  int fd;
850
0
  ws_statb64 statb;
851
0
  bool ispipe = false;
852
0
  wtap  *wth;
853
0
  bool use_stdin = false;
854
0
  wtap_block_t shb;
855
856
0
  *err = 0;
857
0
  *err_info = NULL;
858
859
  /* open standard input if filename is '-' */
860
0
  if (strcmp(filename, "-") == 0)
861
0
    use_stdin = true;
862
863
  /* First, make sure the file is valid */
864
0
  if (use_stdin) {
865
0
    if (ws_fstat64(0, &statb) < 0) {
866
0
      *err = errno;
867
0
      return NULL;
868
0
    }
869
0
  } else {
870
0
    if (ws_stat64(filename, &statb) < 0) {
871
0
      *err = errno;
872
0
      return NULL;
873
0
    }
874
0
  }
875
0
  if (S_ISFIFO(statb.st_mode)) {
876
    /*
877
     * Opens of FIFOs are allowed only when not opening
878
     * for random access.
879
     *
880
     * Currently, we do seeking when trying to find out
881
     * the file type, but our I/O routines do some amount
882
     * of buffering, and do backward seeks within the buffer
883
     * if possible, so at least some file types can be
884
     * opened from pipes, so we don't completely disallow opens
885
     * of pipes.
886
     */
887
0
    if (do_random) {
888
0
      *err = WTAP_ERR_RANDOM_OPEN_PIPE;
889
0
      return NULL;
890
0
    }
891
0
    ispipe = true;
892
0
  } else if (S_ISDIR(statb.st_mode)) {
893
    /*
894
     * Return different errors for "this is a directory"
895
     * and "this is some random special file type", so
896
     * the user can get a potentially more helpful error.
897
     */
898
0
    *err = EISDIR;
899
0
    return NULL;
900
0
  } else if (! S_ISREG(statb.st_mode)) {
901
0
    *err = WTAP_ERR_NOT_REGULAR_FILE;
902
0
    return NULL;
903
0
  }
904
905
  /*
906
   * We need two independent descriptors for random access, so
907
   * they have different file positions.  If we're opening the
908
   * standard input, we can only dup it to get additional
909
   * descriptors, so we can't have two independent descriptors,
910
   * and thus can't do random access.
911
   */
912
0
  if (use_stdin && do_random) {
913
0
    *err = WTAP_ERR_RANDOM_OPEN_STDIN;
914
0
    return NULL;
915
0
  }
916
917
0
  errno = ENOMEM;
918
0
  wth = g_new0(wtap, 1);
919
920
  /* Open the file */
921
0
  errno = WTAP_ERR_CANT_OPEN;
922
0
  if (use_stdin) {
923
    /*
924
     * We dup FD 0, so that we don't have to worry about
925
     * a file_close of wth->fh closing the standard
926
     * input of the process.
927
     */
928
0
    fd = ws_dup(0);
929
0
    if (fd < 0) {
930
0
      *err = errno;
931
0
      g_free(wth);
932
0
      return NULL;
933
0
    }
934
#ifdef _WIN32
935
    if (_setmode(fd, O_BINARY) == -1) {
936
      /* "Shouldn't happen" */
937
      *err = errno;
938
      g_free(wth);
939
      return NULL;
940
    }
941
#endif
942
0
    if (!(wth->fh = file_fdopen(fd))) {
943
0
      *err = errno;
944
0
      ws_close(fd);
945
0
      g_free(wth);
946
0
      return NULL;
947
0
    }
948
0
  } else {
949
0
    if (!(wth->fh = file_open(filename))) {
950
0
      *err = errno;
951
0
      g_free(wth);
952
0
      return NULL;
953
0
    }
954
0
  }
955
956
0
  if (do_random) {
957
0
    if (!(wth->random_fh = file_open(filename))) {
958
0
      *err = errno;
959
0
      file_close(wth->fh);
960
0
      g_free(wth);
961
0
      return NULL;
962
0
    }
963
0
  } else
964
0
    wth->random_fh = NULL;
965
966
  /* initialization */
967
0
  wth->ispipe = ispipe;
968
0
  wth->file_encap = WTAP_ENCAP_UNKNOWN;
969
0
  wth->subtype_sequential_close = NULL;
970
0
  wth->subtype_close = NULL;
971
0
  wth->file_tsprec = WTAP_TSPREC_USEC;
972
0
  nstime_set_unset(&wth->file_start_ts);
973
0
  nstime_set_unset(&wth->file_end_ts);
974
0
  wth->pathname = g_strdup(filename);
975
0
  wth->priv = NULL;
976
0
  wth->wslua_data = NULL;
977
0
  wth->shb_hdrs = g_array_new(false, false, sizeof(wtap_block_t));
978
0
  wth->app_env_var_prefix = app_env_var_prefix;
979
0
  shb = wtap_block_create(WTAP_BLOCK_SECTION);
980
0
  if (shb)
981
0
    g_array_append_val(wth->shb_hdrs, shb);
982
983
  /* Initialize the array containing a list of interfaces. pcapng_open and
984
   * erf_open needs this (and libpcap_open for ERF encapsulation types).
985
   * Always initing it here saves checking for a NULL ptr later. */
986
0
  wth->interface_data = g_array_new(false, false, sizeof(wtap_block_t));
987
  /*
988
   * Next interface data that wtap_get_next_interface_description()
989
   * will return.
990
   */
991
0
  wth->next_interface_data = 0;
992
993
0
  wth->shb_iface_to_global = g_array_new(false, false, sizeof(unsigned));
994
0
  g_array_append_val(wth->shb_iface_to_global, wth->interface_data->len);
995
996
0
  if (wth->random_fh) {
997
0
    wth->fast_seek = g_ptr_array_new();
998
999
0
    file_set_random_access(wth->fh, false, wth->fast_seek);
1000
0
    file_set_random_access(wth->random_fh, true, wth->fast_seek);
1001
0
  }
1002
1003
  /* Find a file format handler which can read the file. */
1004
0
  switch (try_open(wth, type, err, err_info)) {
1005
0
  case WTAP_OPEN_NOT_MINE:
1006
    /* Well, it's not one of the types of file we know about. */
1007
0
    *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
1008
    /* FALLTHROUGH */
1009
1010
0
  case WTAP_OPEN_ERROR:
1011
0
    wtap_close(wth);
1012
0
    wth = NULL;
1013
0
  }
1014
1015
0
  return wth;
1016
0
}
1017
1018
/*
1019
 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
1020
 * to reopen that file and assign the new file descriptor(s) to the sequential
1021
 * stream and, if do_random is true, to the random stream.  Used on Windows
1022
 * after the rename of a file we had open was done or if the rename of a
1023
 * file on top of a file we had open failed.
1024
 *
1025
 * This is only required by Wireshark, not TShark, and, at the point that
1026
 * Wireshark is doing this, the sequential stream is closed, and the
1027
 * random stream is open, so this refuses to open pipes, and only
1028
 * reopens the random stream.
1029
 */
1030
bool
1031
wtap_fdreopen(wtap *wth, const char *filename, int *err)
1032
0
{
1033
0
  ws_statb64 statb;
1034
1035
  /*
1036
   * We need two independent descriptors for random access, so
1037
   * they have different file positions.  If we're opening the
1038
   * standard input, we can only dup it to get additional
1039
   * descriptors, so we can't have two independent descriptors,
1040
   * and thus can't do random access.
1041
   */
1042
0
  if (strcmp(filename, "-") == 0) {
1043
0
    *err = WTAP_ERR_RANDOM_OPEN_STDIN;
1044
0
    return false;
1045
0
  }
1046
1047
  /* First, make sure the file is valid */
1048
0
  if (ws_stat64(filename, &statb) < 0) {
1049
0
    *err = errno;
1050
0
    return false;
1051
0
  }
1052
0
  if (S_ISFIFO(statb.st_mode)) {
1053
    /*
1054
     * Opens of FIFOs are not allowed; see above.
1055
     */
1056
0
    *err = WTAP_ERR_RANDOM_OPEN_PIPE;
1057
0
    return false;
1058
0
  } else if (S_ISDIR(statb.st_mode)) {
1059
    /*
1060
     * Return different errors for "this is a directory"
1061
     * and "this is some random special file type", so
1062
     * the user can get a potentially more helpful error.
1063
     */
1064
0
    *err = EISDIR;
1065
0
    return false;
1066
0
  } else if (! S_ISREG(statb.st_mode)) {
1067
0
    *err = WTAP_ERR_NOT_REGULAR_FILE;
1068
0
    return false;
1069
0
  }
1070
1071
  /* Open the file */
1072
0
  errno = WTAP_ERR_CANT_OPEN;
1073
0
  if (!file_fdreopen(wth->random_fh, filename)) {
1074
0
    *err = errno;
1075
0
    return false;
1076
0
  }
1077
0
  if (strcmp(filename, wth->pathname) != 0) {
1078
0
    g_free(wth->pathname);
1079
0
    wth->pathname = g_strdup(filename);
1080
0
  }
1081
0
  return true;
1082
0
}
1083
1084
/* Table of the file types and subtypes for which we have support. */
1085
1086
/*
1087
 * Pointer to the GArray holding the registered file types.
1088
 */
1089
static GArray*  file_type_subtype_table_arr;
1090
1091
/*
1092
 * Pointer to the table of registered file types in that GArray.
1093
 */
1094
static const struct file_type_subtype_info* file_type_subtype_table;
1095
1096
/*
1097
 * Number of elements in the table for builtin file types/subtypes.
1098
 */
1099
static unsigned wtap_num_builtin_file_types_subtypes;
1100
1101
/*
1102
 * Required builtin types.
1103
 */
1104
int pcap_file_type_subtype = -1;
1105
int pcap_nsec_file_type_subtype = -1;
1106
int pcapng_file_type_subtype = -1;
1107
1108
/*
1109
 * Table for mapping old file type/subtype names to new ones for
1110
 * backwards compatibility.
1111
 */
1112
static GHashTable *type_subtype_name_map;
1113
1114
/*
1115
 * Initialize the table of file types/subtypes with all the builtin
1116
 * types/subtypes.
1117
 */
1118
void
1119
wtap_init_file_type_subtypes(const char* app_env_var_prefix)
1120
14
{
1121
  /* Don't do this twice. */
1122
14
  ws_assert(file_type_subtype_table_arr == NULL);
1123
1124
  /*
1125
   * Estimate the number of file types/subtypes as twice the
1126
   * number of modules; that's probably an overestimate, as
1127
   * the average number of file types/subtypes registered by
1128
   * a module is > 1 but probably < 2, but that shouldn't
1129
   * waste too much memory.
1130
   *
1131
   * Add on 7 more for pcapng, pcap, nanosecond pcap, and the
1132
   * extra modified flavors of pcap.
1133
   */
1134
14
  file_type_subtype_table_arr = g_array_sized_new(false, true,
1135
14
      sizeof(struct file_type_subtype_info), wtap_module_count*2 + 7);
1136
14
  file_type_subtype_table = (const struct file_type_subtype_info*)(void *)file_type_subtype_table_arr->data;
1137
1138
  /*
1139
   * Initialize the hash table for mapping old file type/subtype
1140
   * names to the corresponding new names.
1141
   */
1142
14
  type_subtype_name_map = g_hash_table_new_full(g_str_hash,
1143
14
      g_str_equal, g_free, g_free);
1144
1145
  /* No entries yet, so no builtin entries yet. */
1146
14
  wtap_num_builtin_file_types_subtypes = 0;
1147
1148
  /*
1149
   * Register the builtin entries that aren't in the table.
1150
   * First, do the required ones; register pcapng first, then
1151
   * pcap, so, at the beginning of the table, we have pcapng,
1152
   * pcap, nanosecond pcap, and the weird modified pcaps, so
1153
   * searches for file types that can write a file format
1154
   * start with pcapng, pcap, and nanosecond pcap.
1155
   */
1156
14
  register_pcapng(app_env_var_prefix);
1157
14
  register_pcap();
1158
1159
  /* Now register the ones found by the build process */
1160
1.05k
  for (unsigned i = 0; i < wtap_module_count; i++)
1161
1.03k
    wtap_module_reg[i].cb_func();
1162
1163
  /* Update the number of builtin entries. */
1164
14
  wtap_num_builtin_file_types_subtypes = file_type_subtype_table_arr->len;
1165
14
}
1166
1167
/*
1168
 * Attempt to register a new file type/subtype; fails if a type/subtype
1169
 * with that name is already registered.
1170
 */
1171
int
1172
wtap_register_file_type_subtype(const struct file_type_subtype_info* fi)
1173
1.41k
{
1174
1.41k
  struct file_type_subtype_info* finfo;
1175
1.41k
  unsigned file_type_subtype;
1176
1177
  /*
1178
   * Check for required fields (description and name).
1179
   */
1180
1.41k
  if (!fi || !fi->description || !fi->name) {
1181
0
    ws_warning("no file type info");
1182
0
    return -1;
1183
0
  }
1184
1185
  /*
1186
   * There must be at least one block type that this file
1187
   * type/subtype supports.
1188
   */
1189
1.41k
  if (fi->num_supported_blocks == 0 || fi->supported_blocks == NULL) {
1190
0
    ws_warning("no blocks supported by file type \"%s\"", fi->name);
1191
0
    return -1;
1192
0
  }
1193
1194
  /*
1195
   * Is this type already registered?
1196
   */
1197
1.41k
  if (wtap_name_to_file_type_subtype(fi->name) != -1) {
1198
    /*
1199
     * Yes.  You don't get to replace an existing handler.
1200
     */
1201
0
    ws_warning("file type \"%s\" is already registered", fi->name);
1202
0
    return -1;
1203
0
  }
1204
1205
  /*
1206
   * Is there a freed entry in the array, due to a file type
1207
   * being de-registered?
1208
   *
1209
   * Skip the built-in entries, as they're never deregistered.
1210
   */
1211
1.41k
  for (file_type_subtype = wtap_num_builtin_file_types_subtypes;
1212
72.1k
      file_type_subtype < file_type_subtype_table_arr->len;
1213
70.7k
      file_type_subtype++) {
1214
70.7k
    if (file_type_subtype_table[file_type_subtype].name == NULL) {
1215
      /*
1216
       * We found such an entry.
1217
       *
1218
       * Get the pointer from the GArray, so that we get a
1219
       * non-const pointer.
1220
       */
1221
0
      finfo = &g_array_index(file_type_subtype_table_arr, struct file_type_subtype_info, file_type_subtype);
1222
1223
      /*
1224
       * Fill in the entry with the new values.
1225
       */
1226
0
      *finfo = *fi;
1227
1228
0
      return (int)file_type_subtype;
1229
0
    }
1230
70.7k
  }
1231
1232
  /*
1233
   * There aren't any free slots, so add a new entry.
1234
   * Get the number of current number of entries, which will
1235
   * be the index of the new entry, then append this entry
1236
   * to the end of the array, change file_type_subtype_table
1237
   * in case the array had to get reallocated, and return
1238
   * the index of the new entry.
1239
   */
1240
1.41k
  file_type_subtype = file_type_subtype_table_arr->len;
1241
1.41k
  g_array_append_val(file_type_subtype_table_arr, *fi);
1242
1.41k
  file_type_subtype_table = (const struct file_type_subtype_info*)(void *)file_type_subtype_table_arr->data;
1243
1.41k
  return file_type_subtype;
1244
1.41k
}
1245
1246
/* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1247
 */
1248
void
1249
wtap_deregister_file_type_subtype(const int subtype)
1250
0
{
1251
0
  struct file_type_subtype_info* finfo;
1252
1253
0
  if (subtype < 0 || subtype >= (int)file_type_subtype_table_arr->len) {
1254
0
    ws_error("invalid file type to de-register");
1255
0
    return;
1256
0
  }
1257
0
  if ((unsigned)subtype < wtap_num_builtin_file_types_subtypes) {
1258
0
    ws_error("built-in file types cannot be de-registered");
1259
0
    return;
1260
0
  }
1261
1262
  /*
1263
   * Get the pointer from the GArray, so that we get a non-const
1264
   * pointer.
1265
   */
1266
0
  finfo = &g_array_index(file_type_subtype_table_arr, struct file_type_subtype_info, subtype);
1267
  /*
1268
   * Clear out this entry.
1269
   */
1270
0
  finfo->description = NULL;
1271
0
  finfo->name = NULL;
1272
0
  finfo->default_file_extension = NULL;
1273
0
  finfo->additional_file_extensions = NULL;
1274
0
  finfo->writing_must_seek = false;
1275
0
  finfo->num_supported_blocks = 0;
1276
0
  finfo->supported_blocks = NULL;
1277
0
  finfo->can_write_encap = NULL;
1278
0
  finfo->dump_open = NULL;
1279
0
  finfo->wslua_info = NULL;
1280
0
}
1281
1282
/*
1283
 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1284
 * type that would be needed to write out a file with those types.  If
1285
 * there's only one type, it's that type, otherwise it's
1286
 * WTAP_ENCAP_PER_PACKET.
1287
 */
1288
int
1289
wtap_dump_required_file_encap_type(const GArray *file_encaps)
1290
0
{
1291
0
  int encap;
1292
1293
0
  encap = WTAP_ENCAP_PER_PACKET;
1294
0
  if (file_encaps->len == 1) {
1295
    /* OK, use the one-and-only encapsulation type. */
1296
0
    encap = g_array_index(file_encaps, int, 0);
1297
0
  }
1298
0
  return encap;
1299
0
}
1300
1301
bool
1302
wtap_dump_can_write_encap(int file_type_subtype, int encap)
1303
0
{
1304
0
  int result = 0;
1305
1306
0
  if (file_type_subtype < 0 ||
1307
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len ||
1308
0
      file_type_subtype_table[file_type_subtype].can_write_encap == NULL)
1309
0
    return false;
1310
1311
0
  result = (*file_type_subtype_table[file_type_subtype].can_write_encap)(encap);
1312
1313
0
  if (result != 0) {
1314
    /* if the err said to check wslua's can_write_encap, try that */
1315
0
    if (result == WTAP_ERR_CHECK_WSLUA
1316
0
      && file_type_subtype_table[file_type_subtype].wslua_info != NULL
1317
0
      && file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
1318
1319
0
      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);
1320
1321
0
    }
1322
1323
0
    if (result != 0)
1324
0
      return false;
1325
0
  }
1326
1327
0
  return true;
1328
0
}
1329
1330
/*
1331
 * Return true if a capture with a given GArray of encapsulation types
1332
 * and a given bitset of comment types can be written in a specified
1333
 * format, and false if it can't.
1334
 */
1335
static bool
1336
wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1337
    uint32_t required_comment_types)
1338
0
{
1339
0
  unsigned i;
1340
1341
  /*
1342
   * Can we write in this format?
1343
   */
1344
0
  if (!wtap_dump_can_open(ft)) {
1345
    /* No. */
1346
0
    return false;
1347
0
  }
1348
1349
  /*
1350
   * Yes.  Can we write out all the required comments in this
1351
   * format?
1352
   */
1353
0
  if (required_comment_types & WTAP_COMMENT_PER_SECTION) {
1354
0
    if (wtap_file_type_subtype_supports_option(ft,
1355
0
        WTAP_BLOCK_SECTION, OPT_COMMENT) == OPTION_NOT_SUPPORTED) {
1356
      /* Not section comments. */
1357
0
      return false;
1358
0
    }
1359
0
  }
1360
0
  if (required_comment_types & WTAP_COMMENT_PER_INTERFACE) {
1361
0
    if (wtap_file_type_subtype_supports_option(ft,
1362
0
        WTAP_BLOCK_IF_ID_AND_INFO, OPT_COMMENT) == OPTION_NOT_SUPPORTED) {
1363
      /* Not interface comments. */
1364
0
      return false;
1365
0
    }
1366
0
  }
1367
0
  if (required_comment_types & WTAP_COMMENT_PER_PACKET) {
1368
0
    if (wtap_file_type_subtype_supports_option(ft,
1369
0
        WTAP_BLOCK_PACKET, OPT_COMMENT) == OPTION_NOT_SUPPORTED) {
1370
      /* Not packet comments. */
1371
0
      return false;
1372
0
    }
1373
0
  }
1374
1375
  /*
1376
   * Yes.  Is the required per-file encapsulation type supported?
1377
   * This might be WTAP_ENCAP_PER_PACKET.
1378
   */
1379
0
  if (!wtap_dump_can_write_encap(ft, wtap_dump_required_file_encap_type(file_encaps))) {
1380
    /* No. */
1381
0
    return false;
1382
0
  }
1383
1384
  /*
1385
   * Yes.  Are all the individual encapsulation types supported?
1386
   */
1387
0
  for (i = 0; i < file_encaps->len; i++) {
1388
0
    if (!wtap_dump_can_write_encap(ft,
1389
0
        g_array_index(file_encaps, int, i))) {
1390
      /* No - one of them isn't. */
1391
0
      return false;
1392
0
    }
1393
0
  }
1394
1395
  /* Yes - we're OK. */
1396
0
  return true;
1397
0
}
1398
1399
/*
1400
 * Return true if we can write a file with the given GArray of
1401
 * encapsulation types and the given bitmask of comment types.
1402
 */
1403
bool
1404
wtap_dump_can_write(const GArray *file_encaps, uint32_t required_comment_types)
1405
0
{
1406
0
  int ft;
1407
1408
0
  for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1409
    /* To save a file with Wiretap, Wiretap has to handle that format,
1410
     * and its code to handle that format must be able to write a file
1411
     * with this file's encapsulation types.
1412
     */
1413
0
    if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1414
      /* OK, we can write it out in this type. */
1415
0
      return true;
1416
0
    }
1417
0
  }
1418
1419
  /* No, we couldn't save it in any format. */
1420
0
  return false;
1421
0
}
1422
1423
/*
1424
 * Sort by file type/subtype name.
1425
 */
1426
static int
1427
compare_file_type_subtypes_by_name(const void *a, const void *b)
1428
0
{
1429
0
  int file_type_subtype_a = *(const int *)a;
1430
0
  int file_type_subtype_b = *(const int *)b;
1431
1432
0
  return strcmp(wtap_file_type_subtype_name(file_type_subtype_a),
1433
0
                wtap_file_type_subtype_name(file_type_subtype_b));
1434
0
}
1435
1436
/*
1437
 * Sort by file type/subtype description.
1438
 */
1439
static int
1440
compare_file_type_subtypes_by_description(const void *a, const void *b)
1441
0
{
1442
0
  int file_type_subtype_a = *(const int *)a;
1443
0
  int file_type_subtype_b = *(const int *)b;
1444
1445
0
  return strcmp(wtap_file_type_subtype_description(file_type_subtype_a),
1446
0
                wtap_file_type_subtype_description(file_type_subtype_b));
1447
0
}
1448
1449
/*
1450
 * Get a GArray of file type/subtype values for file types/subtypes
1451
 * that can be used to save a file of a given type/subtype with a given
1452
 * GArray of encapsulation types and the given bitmask of comment types.
1453
 */
1454
GArray *
1455
wtap_get_savable_file_types_subtypes_for_file(int file_type_subtype,
1456
    const GArray *file_encaps, uint32_t required_comment_types,
1457
    ft_sort_order sort_order)
1458
0
{
1459
0
  GArray *savable_file_types_subtypes;
1460
0
  int ft;
1461
0
  int default_file_type_subtype = -1;
1462
0
  int other_file_type_subtype = -1;
1463
1464
  /* Can we save this file in its own file type/subtype? */
1465
0
  if (wtap_dump_can_write_format(file_type_subtype, file_encaps,
1466
0
               required_comment_types)) {
1467
    /* Yes - make that the default file type/subtype. */
1468
0
    default_file_type_subtype = file_type_subtype;
1469
0
  } else if (wtap_dump_can_write_format(pcap_file_type_subtype,
1470
0
                file_encaps,
1471
0
                required_comment_types)) {
1472
    /*
1473
     * No, but we can write it as a pcap file; make that
1474
     * the default file type/subtype.
1475
     */
1476
0
    default_file_type_subtype = pcap_file_type_subtype;
1477
0
  } else if (wtap_dump_can_write_format(pcapng_file_type_subtype,
1478
0
                file_encaps,
1479
0
                required_comment_types)) {
1480
    /*
1481
     * No, but we can write it as a pcapng file; make that
1482
     * the default file type/subtype.
1483
     */
1484
0
    default_file_type_subtype = pcapng_file_type_subtype;
1485
0
  } else {
1486
    /* OK, find the first file type/subtype we *can* save it as. */
1487
0
    default_file_type_subtype = -1;
1488
0
    for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1489
0
      if (wtap_dump_can_write_format(ft, file_encaps,
1490
0
                   required_comment_types)) {
1491
        /* OK, got it. */
1492
0
        default_file_type_subtype = ft;
1493
0
        break;
1494
0
      }
1495
0
    }
1496
0
  }
1497
1498
0
  if (default_file_type_subtype == -1) {
1499
    /* We don't support writing this file as any file type/subtype. */
1500
0
    return NULL;
1501
0
  }
1502
1503
  /*
1504
   * If the default is pcap, put pcapng right after it if we can
1505
   * also write it in pcapng format; otherwise, if the default is
1506
   * pcapng, put pcap right after it if we can also write it in
1507
   * pcap format.
1508
   */
1509
0
  if (default_file_type_subtype == pcap_file_type_subtype) {
1510
0
    if (wtap_dump_can_write_format(pcapng_file_type_subtype,
1511
0
                                   file_encaps,
1512
0
                                   required_comment_types))
1513
0
      other_file_type_subtype = pcapng_file_type_subtype;
1514
0
  } else if (default_file_type_subtype == pcapng_file_type_subtype) {
1515
0
    if (wtap_dump_can_write_format(pcap_file_type_subtype,
1516
0
                                   file_encaps,
1517
0
                 required_comment_types))
1518
0
      other_file_type_subtype = pcap_file_type_subtype;
1519
0
  }
1520
1521
  /* Allocate the array. */
1522
0
  savable_file_types_subtypes = g_array_new(false, false,
1523
0
      sizeof (int));
1524
1525
  /*
1526
   * First, add the types we don't want to force to the
1527
   * beginning of the list.
1528
   */
1529
0
  for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1530
0
    if (ft == default_file_type_subtype ||
1531
0
        ft == other_file_type_subtype)
1532
0
      continue; /* we will done this one later */
1533
0
    if (wtap_dump_can_write_format(ft, file_encaps,
1534
0
                 required_comment_types)) {
1535
      /* OK, we can write it out in this type. */
1536
0
      g_array_append_val(savable_file_types_subtypes, ft);
1537
0
    }
1538
0
  }
1539
1540
  /* Now, sort the list. */
1541
0
  g_array_sort(savable_file_types_subtypes,
1542
0
      (sort_order == FT_SORT_BY_NAME) ? compare_file_type_subtypes_by_name :
1543
0
                                        compare_file_type_subtypes_by_description);
1544
1545
  /*
1546
   * If we have a type/subtype to put above the default one,
1547
   * do so.
1548
   *
1549
   * We put this type at the beginning before putting the
1550
   * default there, so the default is at the top.
1551
   */
1552
0
  if (other_file_type_subtype != -1)
1553
0
    g_array_prepend_val(savable_file_types_subtypes,
1554
0
        other_file_type_subtype);
1555
1556
  /* Put the default file type/subtype first in the list. */
1557
0
  g_array_prepend_val(savable_file_types_subtypes,
1558
0
      default_file_type_subtype);
1559
1560
0
  return savable_file_types_subtypes;
1561
0
}
1562
1563
/*
1564
 * Get a GArray of all writable file type/subtype values.
1565
 */
1566
GArray *
1567
wtap_get_writable_file_types_subtypes(ft_sort_order sort_order)
1568
0
{
1569
0
  GArray *writable_file_types_subtypes;
1570
0
  int ft;
1571
1572
  /*
1573
   * Allocate the array.
1574
   * Pre-allocate room enough for all types.
1575
   * XXX - that's overkill; just scan the table to find all the
1576
   * writable types and count them.
1577
   */
1578
0
  writable_file_types_subtypes = g_array_sized_new(false, false,
1579
0
      sizeof (int), file_type_subtype_table_arr->len);
1580
1581
  /*
1582
   * First, add the types we don't want to force to the
1583
   * beginning of the list.
1584
   */
1585
0
  for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1586
0
    if (ft == pcap_file_type_subtype ||
1587
0
        ft == pcapng_file_type_subtype)
1588
0
      continue; /* we've already done these two */
1589
0
    if (wtap_dump_can_open(ft)) {
1590
      /* OK, we can write this type. */
1591
0
      g_array_append_val(writable_file_types_subtypes, ft);
1592
0
    }
1593
0
  }
1594
1595
  /* Now, sort the list. */
1596
0
  g_array_sort(writable_file_types_subtypes,
1597
0
      (sort_order == FT_SORT_BY_NAME) ? compare_file_type_subtypes_by_name :
1598
0
                                        compare_file_type_subtypes_by_description);
1599
1600
  /*
1601
   * Now, put pcap and pcapng at the beginning, as they're
1602
   * our "native" formats.  Put pcapng there first, and
1603
   * pcap before it.
1604
   */
1605
0
  if (pcapng_file_type_subtype != -1 &&
1606
0
      wtap_dump_can_open(pcapng_file_type_subtype)) {
1607
    /*
1608
     * We can write pcapng.  (If we can't, that's a huge
1609
     * mistake.)
1610
     */
1611
0
    g_array_prepend_val(writable_file_types_subtypes,
1612
0
        pcapng_file_type_subtype);
1613
0
  }
1614
0
  if (pcap_file_type_subtype != -1 &&
1615
0
      wtap_dump_can_open(pcap_file_type_subtype)) {
1616
    /*
1617
     * We can write pcap.  (If we can't, that's a huge
1618
     * mistake.)
1619
     */
1620
0
    g_array_prepend_val(writable_file_types_subtypes,
1621
0
        pcap_file_type_subtype);
1622
0
  }
1623
1624
0
  return writable_file_types_subtypes;
1625
0
}
1626
1627
/*
1628
 * String describing the file type/subtype.
1629
 */
1630
const char *
1631
wtap_file_type_subtype_description(int file_type_subtype)
1632
0
{
1633
0
  if (file_type_subtype < 0 ||
1634
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len)
1635
0
    return NULL;
1636
0
  else
1637
0
    return file_type_subtype_table[file_type_subtype].description;
1638
0
}
1639
1640
/*
1641
 * Name to use in, say, a command-line flag specifying the type/subtype.
1642
 */
1643
const char *
1644
wtap_file_type_subtype_name(int file_type_subtype)
1645
0
{
1646
0
  if (file_type_subtype < 0 ||
1647
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len)
1648
0
    return NULL;
1649
0
  else
1650
0
    return file_type_subtype_table[file_type_subtype].name;
1651
0
}
1652
1653
/*
1654
 * Register a backwards-compatibility name.
1655
 */
1656
void
1657
wtap_register_compatibility_file_subtype_name(const char *old_name,
1658
    const char *new_name)
1659
112
{
1660
112
  g_hash_table_insert(type_subtype_name_map, g_strdup(old_name),
1661
112
      g_strdup(new_name));
1662
112
}
1663
1664
/*
1665
 * Translate a name to a capture file type/subtype.
1666
 */
1667
int
1668
wtap_name_to_file_type_subtype(const char *name)
1669
1.42k
{
1670
1.42k
  char *new_name;
1671
1.42k
  int file_type_subtype;
1672
1673
  /*
1674
   * Is this name a backwards-compatibility name?
1675
   */
1676
1.42k
  new_name = (char *)g_hash_table_lookup(type_subtype_name_map,
1677
1.42k
      (void *)name);
1678
1.42k
  if (new_name != NULL) {
1679
    /*
1680
     * Yes, and new_name is the name to which it should
1681
     * be mapped.
1682
     */
1683
0
    name = new_name;
1684
0
  }
1685
1.42k
  for (file_type_subtype = 0;
1686
72.5k
      file_type_subtype < (int)file_type_subtype_table_arr->len;
1687
71.1k
      file_type_subtype++) {
1688
71.1k
    if (file_type_subtype_table[file_type_subtype].name != NULL &&
1689
71.1k
        strcmp(name, file_type_subtype_table[file_type_subtype].name) == 0)
1690
14
      return file_type_subtype;
1691
71.1k
  }
1692
1693
1.41k
  return -1; /* no such file type, or we can't write it */
1694
1.42k
}
1695
1696
/*
1697
 * Provide the file type/subtype for pcap.
1698
 */
1699
int
1700
wtap_pcap_file_type_subtype(void)
1701
0
{
1702
  /*
1703
   * Make sure pcap was registered as a file type/subtype;
1704
   * it's one of our "native" formats.
1705
   */
1706
0
  ws_assert(pcap_file_type_subtype != -1);
1707
0
  return pcap_file_type_subtype;
1708
0
}
1709
1710
/*
1711
 * Provide the file type/subtype for nanosecond-resolution pcap.
1712
 */
1713
int
1714
wtap_pcap_nsec_file_type_subtype(void)
1715
0
{
1716
  /*
1717
   * Make sure nanosecond-resolution pcap was registered
1718
   * as a file type/subtype; it's one of our "native" formats.
1719
   */
1720
0
  ws_assert(pcap_nsec_file_type_subtype != -1);
1721
0
  return pcap_nsec_file_type_subtype;
1722
0
}
1723
1724
/*
1725
 * Provide the file type/subtype for pcapng.
1726
 */
1727
int
1728
wtap_pcapng_file_type_subtype(void)
1729
14
{
1730
  /*
1731
   * Make sure pcapng was registered as a file type/subtype;
1732
   * it's one of our "native" formats.
1733
   */
1734
14
  ws_assert(pcapng_file_type_subtype != -1);
1735
14
  return pcapng_file_type_subtype;
1736
14
}
1737
1738
/*
1739
 * Determine if a file type/subtype can write a block of the given type.
1740
 */
1741
block_support_t
1742
wtap_file_type_subtype_supports_block(int file_type_subtype,
1743
    wtap_block_type_t type)
1744
0
{
1745
0
  size_t num_supported_blocks;
1746
0
  const struct supported_block_type *supported_blocks;
1747
1748
0
  if (file_type_subtype < 0 ||
1749
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1750
    /*
1751
     * There's no such file type, so it can't support any
1752
     * blocks.
1753
     */
1754
0
    return BLOCK_NOT_SUPPORTED;
1755
0
  }
1756
1757
0
  num_supported_blocks = file_type_subtype_table[file_type_subtype].num_supported_blocks;
1758
0
  supported_blocks = file_type_subtype_table[file_type_subtype].supported_blocks;
1759
1760
0
  for (size_t block_idx = 0; block_idx < num_supported_blocks;
1761
0
      block_idx++) {
1762
0
    if (supported_blocks[block_idx].type == type)
1763
0
      return supported_blocks[block_idx].support;
1764
0
  }
1765
1766
  /*
1767
   * Not found, which means not supported.
1768
   */
1769
0
  return BLOCK_NOT_SUPPORTED;
1770
0
}
1771
1772
/*
1773
 * Determine if a file type/subtype, when writing a block of the given type,
1774
 * can support adding the given option to the block.
1775
 */
1776
option_support_t
1777
wtap_file_type_subtype_supports_option(int file_type_subtype,
1778
    wtap_block_type_t type, unsigned option)
1779
0
{
1780
0
  size_t num_supported_blocks;
1781
0
  const struct supported_block_type *supported_blocks;
1782
1783
0
  if (file_type_subtype < 0 ||
1784
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1785
    /*
1786
     * There's no such file type, so it can't support any
1787
     * blocks, and thus can't support any options.
1788
     */
1789
0
    return OPTION_NOT_SUPPORTED;
1790
0
  }
1791
1792
0
  num_supported_blocks = file_type_subtype_table[file_type_subtype].num_supported_blocks;
1793
0
  supported_blocks = file_type_subtype_table[file_type_subtype].supported_blocks;
1794
1795
0
  for (size_t block_idx = 0; block_idx < num_supported_blocks;
1796
0
      block_idx++) {
1797
0
    if (supported_blocks[block_idx].type == type) {
1798
      /*
1799
       * OK, that block is known.
1800
       * Is it supported?
1801
       */
1802
0
      if (supported_blocks[block_idx].support == BLOCK_NOT_SUPPORTED) {
1803
        /*
1804
         * No, so clearly the option isn't
1805
         * supported in that block.
1806
         */
1807
0
        return OPTION_NOT_SUPPORTED;
1808
0
      }
1809
1810
      /*
1811
       * Yes, so check the options.
1812
       */
1813
0
      size_t num_supported_options;
1814
0
      const struct supported_option_type *supported_options;
1815
1816
0
      num_supported_options = supported_blocks[block_idx].num_supported_options;
1817
0
      supported_options = supported_blocks[block_idx].supported_options;
1818
0
      for (size_t opt_idx = 0; opt_idx < num_supported_options;
1819
0
          opt_idx++) {
1820
0
        if (supported_options[opt_idx].opt == option)
1821
0
          return supported_options[opt_idx].support;
1822
0
      }
1823
1824
      /*
1825
       * Not found, which means not supported.
1826
       */
1827
0
      return OPTION_NOT_SUPPORTED;
1828
0
    }
1829
0
  }
1830
1831
  /*
1832
   * The block type wasn't found, which means it's not supported,
1833
   * which means the option isn't supported in that block.
1834
   */
1835
0
  return OPTION_NOT_SUPPORTED;
1836
0
}
1837
1838
static GSList *
1839
add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
1840
    GSList *compression_type_extensions)
1841
0
{
1842
0
  char **extensions_set, **extensionp;
1843
0
  char *extension;
1844
1845
0
  if (file_type_subtype < 0 ||
1846
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1847
    /*
1848
     * There's no such file type, so it has no extensions
1849
     * to add.
1850
     */
1851
0
    return extensions;
1852
0
  }
1853
1854
  /*
1855
   * Add the default extension, and all of the compressed variants
1856
   * from the list of compressed-file extensions, if there is a
1857
   * default extension.
1858
   */
1859
0
  if (file_type_subtype_table[file_type_subtype].default_file_extension != NULL) {
1860
0
    extensions = add_extensions(extensions,
1861
0
        file_type_subtype_table[file_type_subtype].default_file_extension,
1862
0
        compression_type_extensions);
1863
0
  }
1864
1865
0
  if (file_type_subtype_table[file_type_subtype].additional_file_extensions != NULL) {
1866
    /*
1867
     * We have additional extensions; add them.
1868
     *
1869
     * First, split the extension-list string into a set of
1870
     * extensions.
1871
     */
1872
0
    extensions_set = g_strsplit(file_type_subtype_table[file_type_subtype].additional_file_extensions,
1873
0
        ";", 0);
1874
1875
    /*
1876
     * Add each of those extensions to the list.
1877
     */
1878
0
    for (extensionp = extensions_set; *extensionp != NULL;
1879
0
        extensionp++) {
1880
0
      extension = *extensionp;
1881
1882
      /*
1883
       * Add the extension, and all compressed variants
1884
       * of it if requested.
1885
       */
1886
0
      extensions = add_extensions(extensions, extension,
1887
0
          compression_type_extensions);
1888
0
    }
1889
1890
0
    g_strfreev(extensions_set);
1891
0
  }
1892
0
  return extensions;
1893
0
}
1894
1895
/* Return a list of file extensions that are used by the specified file
1896
 * type/subtype.
1897
 *
1898
 * If include_compressed is true, the list will include compressed
1899
 * extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1900
 * gzipped files.
1901
 *
1902
 * All strings in the list are allocated with g_malloc() and must be freed
1903
 * with g_free().
1904
 */
1905
GSList *
1906
wtap_get_file_extensions_list(int file_type_subtype, bool include_compressed)
1907
0
{
1908
0
  GSList *extensions, *compression_type_extensions;
1909
1910
0
  if (file_type_subtype < 0 ||
1911
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len)
1912
0
    return NULL; /* not a valid file type */
1913
1914
0
  if (file_type_subtype_table[file_type_subtype].default_file_extension == NULL)
1915
0
    return NULL; /* valid, but no extensions known */
1916
1917
0
  extensions = NULL; /* empty list, to start with */
1918
1919
  /*
1920
   * Add all this file type's extensions, with compressed
1921
   * variants if include_compressed is true.
1922
   */
1923
0
  if (include_compressed) {
1924
    /*
1925
     * Get compression-type extensions, if any.
1926
     */
1927
0
    compression_type_extensions = ws_get_all_compression_type_extensions_list();
1928
0
  } else {
1929
    /*
1930
     * We don't want the compressed file extensions.
1931
     */
1932
0
    compression_type_extensions = NULL;
1933
0
  }
1934
0
  extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
1935
0
      compression_type_extensions);
1936
1937
0
  g_slist_free(compression_type_extensions);
1938
1939
0
  return g_slist_reverse(extensions);
1940
0
}
1941
1942
/* Return a list of all extensions that are used by all capture file
1943
 * types, including compressed extensions, e.g. not just "pcap" but
1944
 * also "pcap.gz" if we can read gzipped files.
1945
 *
1946
 * "Capture files" means "include file types that correspond to
1947
 * collections of network packets, but not file types that
1948
 * store data that just happens to be transported over protocols
1949
 * such as HTTP but that aren't collections of network packets",
1950
 * so that it could be used for "All Capture Files" without picking
1951
 * up JPEG files or files such as that - those aren't capture files,
1952
 * and we *do* have them listed in the long list of individual file
1953
 * types, so omitting them from "All Capture Files" is the right
1954
 * thing to do.
1955
 *
1956
 * All strings in the list are allocated with g_malloc() and must be freed
1957
 * with g_free().
1958
 *
1959
 * This is used to generate a list of extensions to look for if the user
1960
 * chooses "All Capture Files" in a file open dialog.
1961
 */
1962
GSList *
1963
wtap_get_all_capture_file_extensions_list(void)
1964
0
{
1965
0
  GSList *extensions, *compression_type_extensions;
1966
0
  unsigned int i;
1967
1968
0
  extensions = NULL; /* empty list, to start with */
1969
1970
  /*
1971
   * Get compression-type extensions, if any.
1972
   */
1973
0
  compression_type_extensions = ws_get_all_compression_type_extensions_list();
1974
1975
0
  for (i = 0; i < file_type_extensions_arr->len; i++) {
1976
    /*
1977
     * Is this a capture file, rather than one of the
1978
     * other random file types we can read?
1979
     */
1980
0
    if (file_type_extensions[i].is_capture_file) {
1981
      /*
1982
       * Yes.  Add all this file extension type's
1983
       * extensions, with compressed variants.
1984
       */
1985
0
      extensions = add_extensions_for_file_extensions_type(i,
1986
0
          extensions, compression_type_extensions);
1987
0
    }
1988
0
  }
1989
1990
0
  g_slist_free(compression_type_extensions);
1991
1992
0
  return g_slist_reverse(extensions);
1993
0
}
1994
1995
/* Return a list of all extensions that are used by all file types that
1996
 * we can read, including compressed extensions, e.g. not just "pcap" but
1997
 * also "pcap.gz" if we can read gzipped files.
1998
 *
1999
 * "File type" means "include file types that correspond to collections
2000
 * of network packets, as well as file types that store data that just
2001
 * happens to be transported over protocols such as HTTP but that aren't
2002
 * collections of network packets, and plain text files".
2003
 *
2004
 * All strings in the list are allocated with g_malloc() and must be freed
2005
 * with g_free().
2006
 *
2007
 * This is used to get the "base name" for a file, by stripping off
2008
 * compressed-file extensions and extensions that correspond to file
2009
 * types that we know about.
2010
 */
2011
GSList *
2012
wtap_get_all_file_extensions_list(void)
2013
0
{
2014
0
  GSList *extensions, *compression_type_extensions;
2015
2016
0
  extensions = NULL; /* empty list, to start with */
2017
2018
  /*
2019
   * Get compression-type extensions, if any.
2020
   */
2021
0
  compression_type_extensions = ws_get_all_compression_type_extensions_list();
2022
2023
0
  for (int ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
2024
0
    extensions = add_extensions_for_file_type_subtype(ft, extensions,
2025
0
        compression_type_extensions);
2026
0
  }
2027
2028
0
  g_slist_free(compression_type_extensions);
2029
2030
0
  return g_slist_reverse(extensions);
2031
0
}
2032
2033
/*
2034
 * Free a list returned by wtap_get_file_extension_type_extensions(),
2035
 * wtap_get_all_capture_file_extensions_list, wtap_get_file_extensions_list(),
2036
 * or wtap_get_all_file_extensions_list().
2037
 */
2038
void
2039
wtap_free_extensions_list(GSList *extensions)
2040
0
{
2041
0
  GSList *extension;
2042
2043
0
  for (extension = extensions; extension != NULL;
2044
0
      extension = g_slist_next(extension)) {
2045
0
    g_free(extension->data);
2046
0
  }
2047
0
  g_slist_free(extensions);
2048
0
}
2049
2050
/*
2051
 * Return the default file extension to use with the specified file type
2052
 * and subtype; that's just the extension, without any ".".
2053
 */
2054
const char *
2055
wtap_default_file_extension(int file_type_subtype)
2056
0
{
2057
0
  if (file_type_subtype < 0 ||
2058
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len)
2059
0
    return NULL;
2060
0
  else
2061
0
    return file_type_subtype_table[file_type_subtype].default_file_extension;
2062
0
}
2063
2064
/*
2065
 * Return whether we know how to write the specified file type.
2066
 */
2067
bool
2068
wtap_dump_can_open(int file_type_subtype)
2069
0
{
2070
0
  if (file_type_subtype < 0 ||
2071
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2072
0
      file_type_subtype_table[file_type_subtype].dump_open == NULL)
2073
0
    return false;
2074
2075
0
  return true;
2076
0
}
2077
2078
/*
2079
 * Return whether we know how to write a compressed file of the specified
2080
 * file type.
2081
 */
2082
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H)
2083
bool
2084
wtap_dump_can_compress(int file_type_subtype)
2085
0
{
2086
  /*
2087
   * If this is an unknown file type, or if we have to
2088
   * seek when writing out a file with this file type,
2089
   * return false.
2090
   */
2091
0
  if (file_type_subtype < 0 ||
2092
0
      file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2093
0
      file_type_subtype_table[file_type_subtype].writing_must_seek)
2094
0
    return false;
2095
2096
0
  return true;
2097
0
}
2098
#else
2099
bool
2100
wtap_dump_can_compress(int file_type_subtype _U_)
2101
{
2102
  return false;
2103
}
2104
#endif
2105
2106
static bool wtap_dump_open_finish(wtap_dumper *wdh, int *err,
2107
              char **err_info);
2108
2109
static WFILE_T wtap_dump_file_open(const wtap_dumper *wdh, const char *filename);
2110
static WFILE_T wtap_dump_file_fdopen(const wtap_dumper *wdh, int fd);
2111
static int wtap_dump_file_close(wtap_dumper *wdh);
2112
static bool wtap_dump_fix_idb(wtap_dumper *wdh, wtap_block_t idb, int *err);
2113
2114
static wtap_dumper *
2115
wtap_dump_init_dumper(int file_type_subtype, ws_compression_type compression_type,
2116
                      const wtap_dump_params *params, int *err)
2117
0
{
2118
0
  wtap_dumper *wdh;
2119
0
  wtap_block_t descr, file_int_data;
2120
0
  wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
2121
0
  GArray *interfaces = params->idb_inf ? params->idb_inf->interface_data : NULL;
2122
2123
  /* Can we write files of this file type/subtype?
2124
   *
2125
   * This will fail if file_type_subtype isn't a valid
2126
   * file type/subtype value, so, if it doesn't fail,
2127
   * we know file_type_subtype is within the bounds of
2128
   * the table of file types/subtypes.
2129
   */
2130
0
  if (!wtap_dump_can_open(file_type_subtype)) {
2131
    /* Invalid type, or type we don't know how to write. */
2132
0
    *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2133
0
    return NULL;
2134
0
  }
2135
2136
  /* OK, we know how to write that file type/subtype; can we write
2137
   * the specified encapsulation type in that file type/subtype?
2138
   */
2139
0
  *err = (*file_type_subtype_table[file_type_subtype].can_write_encap)(params->encap);
2140
  /* if the err said to check wslua's can_write_encap, try that */
2141
0
  if (*err == WTAP_ERR_CHECK_WSLUA
2142
0
    && file_type_subtype_table[file_type_subtype].wslua_info != NULL
2143
0
    && file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
2144
2145
0
    *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);
2146
0
  }
2147
2148
0
  if (*err != 0) {
2149
    /* No, we can't. */
2150
0
    return NULL;
2151
0
  }
2152
2153
  /* Check whether we can open a capture file with that file type
2154
   * and that encapsulation, and, if the compression type isn't
2155
   * "uncompressed", whether we can write a *compressed* file
2156
   * of that file type.
2157
   * If we're doing compression, can this file type/subtype be
2158
     written in compressed form?
2159
   *
2160
   * (The particular type doesn't matter - if the file can't
2161
   * be written 100% sequentially, we can't compress it,
2162
   * because we can't go back and overwrite something we've
2163
   * already written.
2164
   */
2165
0
  if (compression_type != WS_FILE_UNCOMPRESSED &&
2166
0
      !wtap_dump_can_compress(file_type_subtype)) {
2167
0
    *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
2168
0
    return NULL;
2169
0
  }
2170
2171
  /* Allocate a data structure for the output stream. */
2172
0
  wdh = g_new0(wtap_dumper, 1);
2173
0
  if (wdh == NULL) {
2174
0
    *err = errno;
2175
0
    return NULL;
2176
0
  }
2177
2178
0
  wdh->file_type_subtype = file_type_subtype;
2179
0
  wdh->snaplen = params->snaplen;
2180
0
  wdh->file_encap = params->encap;
2181
0
  wdh->compression_type = compression_type;
2182
0
  wdh->wslua_data = NULL;
2183
0
  wdh->shb_iface_to_global = params->shb_iface_to_global;
2184
0
  wdh->interface_data = g_array_new(false, false, sizeof(wtap_block_t));
2185
2186
  /* Set Section Header Block data */
2187
0
  wdh->shb_hdrs = params->shb_hdrs;
2188
  /* Set Name Resolution Block data */
2189
0
  wdh->nrbs_growing = params->nrbs_growing;
2190
  /* Set Interface Description Block data */
2191
0
  if (interfaces && interfaces->len) {
2192
0
    if (!params->dont_copy_idbs) { /* XXX */
2193
0
      unsigned itf_count;
2194
2195
      /* Note: this memory is owned by wtap_dumper and will become
2196
       * invalid after wtap_dump_close. */
2197
0
      for (itf_count = 0; itf_count < interfaces->len; itf_count++) {
2198
0
        file_int_data = g_array_index(interfaces, wtap_block_t, itf_count);
2199
0
        file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
2200
0
        descr = wtap_block_make_copy(file_int_data);
2201
0
        if ((params->encap != WTAP_ENCAP_PER_PACKET) && (params->encap != file_int_data_mand->wtap_encap)) {
2202
0
          descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2203
0
          descr_mand->wtap_encap = params->encap;
2204
0
        }
2205
0
        if (!wtap_dump_fix_idb(wdh, descr, err)) {
2206
0
          wtap_block_array_free(wdh->interface_data);
2207
0
          g_free(wdh);
2208
0
          return NULL;
2209
0
        }
2210
0
        g_array_append_val(wdh->interface_data, descr);
2211
0
      }
2212
0
    }
2213
0
  } else if (params->encap != WTAP_ENCAP_NONE && params->encap != WTAP_ENCAP_PER_PACKET) {
2214
    /* Generate a fake IDB if we don't have one, unless the
2215
     * file encapsulation is none. (WTAP_ENCAP_NONE either
2216
     * means that there are no interfaces, or they will be
2217
     * provided later when reading the file in single-pass mode.)
2218
     *
2219
     * For WTAP_ENCAP_PER_PACKET, we'll have to generate IDBs
2220
     * from packet records as they come in. (pcapng does this now.)
2221
     *
2222
     * XXX File types should provide their own IDBs (possibly
2223
     * fake ones generated by wtap_add_generated_idb()), in
2224
     * order to support being used as inputs for mergecap where
2225
     * pcapng is the output.
2226
     */
2227
0
    descr = wtap_dump_params_generate_idb(params);
2228
0
    g_array_append_val(wdh->interface_data, descr);
2229
0
  }
2230
  /* Set Decryption Secrets Blocks */
2231
0
  wdh->dsbs_initial = params->dsbs_initial;
2232
0
  wdh->dsbs_growing = params->dsbs_growing;
2233
  /* Set Sysdig meta events */
2234
0
  wdh->mevs_growing = params->mevs_growing;
2235
  /* Set DPIBs */
2236
0
  wdh->dpibs_growing = params->dpibs_growing;
2237
0
  return wdh;
2238
0
}
2239
2240
wtap_dumper *
2241
wtap_dump_open(const char *filename, int file_type_subtype,
2242
    ws_compression_type compression_type, const wtap_dump_params *params,
2243
    int *err, char **err_info)
2244
0
{
2245
0
  wtap_dumper *wdh;
2246
0
  WFILE_T fh;
2247
2248
0
  *err = 0;
2249
0
  *err_info = NULL;
2250
2251
  /* Allocate and initialize a data structure for the output stream. */
2252
0
  wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2253
0
      err);
2254
0
  if (wdh == NULL)
2255
0
    return NULL;
2256
2257
  /* In case "fopen()" fails but doesn't set "errno", set "errno"
2258
     to a generic "the open failed" error. */
2259
0
  errno = WTAP_ERR_CANT_OPEN;
2260
0
  fh = wtap_dump_file_open(wdh, filename);
2261
0
  if (fh == NULL) {
2262
0
    *err = errno;
2263
0
    g_free(wdh);
2264
0
    return NULL; /* can't create file */
2265
0
  }
2266
0
  wdh->fh = fh;
2267
2268
0
  if (!wtap_dump_open_finish(wdh, err, err_info)) {
2269
    /* Get rid of the file we created; we couldn't finish
2270
       opening it. */
2271
0
    wtap_dump_file_close(wdh);
2272
0
    ws_unlink(filename);
2273
0
    g_free(wdh->priv);
2274
0
    wtap_block_array_free(wdh->interface_data);
2275
0
    wtap_block_array_unref(wdh->dsbs_initial);
2276
0
    g_free(wdh);
2277
0
    return NULL;
2278
0
  }
2279
0
  return wdh;
2280
0
}
2281
2282
wtap_dumper *
2283
wtap_dump_open_tempfile(const char *tmpdir, char **filenamep, const char *pfx,
2284
    int file_type_subtype, ws_compression_type compression_type,
2285
    const wtap_dump_params *params, int *err, char **err_info)
2286
0
{
2287
0
  int fd;
2288
0
  const char *ext;
2289
0
  char sfx[16];
2290
0
  wtap_dumper *wdh;
2291
0
  WFILE_T fh;
2292
2293
  /* No path name for the temporary file yet. */
2294
0
  *filenamep = NULL;
2295
2296
0
  *err = 0;
2297
0
  *err_info = NULL;
2298
2299
  /* Allocate and initialize a data structure for the output stream. */
2300
0
  wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2301
0
      err);
2302
0
  if (wdh == NULL)
2303
0
    return NULL;
2304
2305
  /* Choose an appropriate suffix for the file */
2306
0
  ext = wtap_default_file_extension(file_type_subtype);
2307
0
  if (ext == NULL)
2308
0
    ext = "tmp";
2309
0
  sfx[0] = '.';
2310
0
  sfx[1] = '\0';
2311
0
  (void) g_strlcat(sfx, ext, 16);
2312
2313
  /* Choose a random name for the file */
2314
0
  fd = create_tempfile(tmpdir, filenamep, pfx, sfx, NULL);
2315
0
  if (fd == -1) {
2316
0
    *err = WTAP_ERR_CANT_OPEN;
2317
0
    g_free(wdh);
2318
0
    return NULL; /* can't create file */
2319
0
  }
2320
2321
  /* In case "fopen()" fails but doesn't set "errno", set "errno"
2322
     to a generic "the open failed" error. */
2323
0
  errno = WTAP_ERR_CANT_OPEN;
2324
0
  fh = wtap_dump_file_fdopen(wdh, fd);
2325
0
  if (fh == NULL) {
2326
0
    *err = errno;
2327
0
    ws_close(fd);
2328
0
    g_free(wdh);
2329
0
    return NULL; /* can't create file */
2330
0
  }
2331
0
  wdh->fh = fh;
2332
2333
0
  if (!wtap_dump_open_finish(wdh, err, err_info)) {
2334
    /* Get rid of the file we created; we couldn't finish
2335
       opening it. */
2336
0
    wtap_dump_file_close(wdh);
2337
0
    ws_unlink(*filenamep);
2338
0
    g_free(wdh->priv);
2339
0
    wtap_block_array_free(wdh->interface_data);
2340
0
    wtap_block_array_unref(wdh->dsbs_initial);
2341
0
    g_free(wdh);
2342
0
    return NULL;
2343
0
  }
2344
0
  return wdh;
2345
0
}
2346
2347
wtap_dumper *
2348
wtap_dump_fdopen(int fd, int file_type_subtype, ws_compression_type compression_type,
2349
    const wtap_dump_params *params, int *err, char **err_info)
2350
0
{
2351
0
  wtap_dumper *wdh;
2352
0
  WFILE_T fh;
2353
2354
0
  *err = 0;
2355
0
  *err_info = NULL;
2356
2357
  /* Allocate and initialize a data structure for the output stream. */
2358
0
  wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2359
0
      err);
2360
0
  if (wdh == NULL)
2361
0
    return NULL;
2362
2363
  /* In case "fopen()" fails but doesn't set "errno", set "errno"
2364
     to a generic "the open failed" error. */
2365
0
  errno = WTAP_ERR_CANT_OPEN;
2366
0
  fh = wtap_dump_file_fdopen(wdh, fd);
2367
0
  if (fh == NULL) {
2368
0
    *err = errno;
2369
0
    g_free(wdh);
2370
0
    return NULL; /* can't create standard I/O stream */
2371
0
  }
2372
0
  wdh->fh = fh;
2373
2374
0
  if (!wtap_dump_open_finish(wdh, err, err_info)) {
2375
0
    wtap_dump_file_close(wdh);
2376
0
    g_free(wdh->priv);
2377
0
    wtap_block_array_free(wdh->interface_data);
2378
0
    wtap_block_array_unref(wdh->dsbs_initial);
2379
0
    g_free(wdh);
2380
0
    return NULL;
2381
0
  }
2382
0
  return wdh;
2383
0
}
2384
2385
wtap_dumper *
2386
wtap_dump_open_stdout(int file_type_subtype, ws_compression_type compression_type,
2387
    const wtap_dump_params *params, int *err, char **err_info)
2388
0
{
2389
0
  int new_fd;
2390
0
  wtap_dumper *wdh;
2391
2392
  /*
2393
   * Duplicate the file descriptor, so that we can close the
2394
   * wtap_dumper handle the same way we close any other
2395
   * wtap_dumper handle, without closing the standard output.
2396
   */
2397
0
  new_fd = ws_dup(1);
2398
0
  if (new_fd == -1) {
2399
    /* dup failed */
2400
0
    *err = errno;
2401
0
    return NULL;
2402
0
  }
2403
#ifdef _WIN32
2404
  /*
2405
   * Put the new descriptor into binary mode.
2406
   *
2407
   * XXX - even if the file format we're writing is a text
2408
   * format?
2409
   */
2410
  if (_setmode(new_fd, O_BINARY) == -1) {
2411
    /* "Should not happen" */
2412
    *err = errno;
2413
    ws_close(new_fd);
2414
    return NULL;
2415
  }
2416
#endif
2417
2418
0
  wdh = wtap_dump_fdopen(new_fd, file_type_subtype, compression_type,
2419
0
      params, err, err_info);
2420
0
  if (wdh == NULL) {
2421
    /* Failed; close the new FD */
2422
0
    ws_close(new_fd);
2423
0
    return NULL;
2424
0
  }
2425
0
  return wdh;
2426
0
}
2427
2428
static bool
2429
wtap_dump_open_finish(wtap_dumper *wdh, int *err, char **err_info)
2430
0
{
2431
0
  int fd;
2432
0
  bool cant_seek;
2433
2434
  /* Can we do a seek on the file descriptor?
2435
     If not, note that fact. */
2436
0
  if (wdh->compression_type != WS_FILE_UNCOMPRESSED) {
2437
    /* We've already checked this case in wtap_dump_init_dumper
2438
     * via wtap_dump_can_compress, so we shouldn't need to return
2439
     * WTAP_ERR_COMPRESSION_NOT_SUPPORTED instead of
2440
     * WTAP_ERR_CANT_WRITE_TO_PIPE below. */
2441
0
    cant_seek = true;
2442
0
  } else {
2443
0
    fd = ws_fileno((FILE *)wdh->fh);
2444
0
    if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
2445
0
      cant_seek = true;
2446
0
    else {
2447
      /* Undo the seek. */
2448
0
      ws_lseek64(fd, 0, SEEK_SET);
2449
0
      cant_seek = false;
2450
0
    }
2451
0
  }
2452
2453
  /* If this file type requires seeking, and we can't seek, fail. */
2454
0
  if (file_type_subtype_table[wdh->file_type_subtype].writing_must_seek && cant_seek) {
2455
0
    *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
2456
0
    return false;
2457
0
  }
2458
2459
  /* Set wdh with wslua data if any - this is how we pass the data
2460
   * to the file writer.
2461
   */
2462
0
  if (file_type_subtype_table[wdh->file_type_subtype].wslua_info)
2463
0
    wdh->wslua_data = file_type_subtype_table[wdh->file_type_subtype].wslua_info->wslua_data;
2464
2465
  /* Now try to open the file for writing. */
2466
0
  if (!(*file_type_subtype_table[wdh->file_type_subtype].dump_open)(wdh, err,
2467
0
      err_info)) {
2468
0
    return false;
2469
0
  }
2470
2471
0
  return true; /* success! */
2472
0
}
2473
2474
/* XXX - Temporary hack to deal with nstime_t, and thus wtap_rec and libwiretap
2475
 * in general, not storing precision greater than nanoseconds yet. Despite
2476
 * whatever precision an IDB claims, we can't write finer than nanosecond.
2477
 * Eventually this should be removed.
2478
 * Fix a given IDB to indicate no greater than nanosecond precision. */
2479
static bool
2480
wtap_dump_fix_idb(wtap_dumper *wdb _U_, wtap_block_t idb, int *err)
2481
0
{
2482
0
  wtapng_if_descr_mandatory_t *idb_mand;
2483
0
  int64_t tsoffset;
2484
0
  idb_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(idb);
2485
2486
  /*
2487
   * nstime_t only stores nanoseconds, so instead of claiming false
2488
   * precision, fix things up.
2489
   */
2490
0
  if (idb_mand->time_units_per_second > 1000000000) {
2491
0
    ws_warning("original time precision reduced to nanoseconds");
2492
0
    idb_mand->time_units_per_second = 1000000000;
2493
0
    switch (wtap_block_set_uint8_option_value(idb, OPT_IDB_TSRESOL, 9)) {
2494
0
    case WTAP_OPTTYPE_SUCCESS:
2495
0
      break;
2496
0
    case WTAP_OPTTYPE_NOT_FOUND:
2497
      // This "should not" happen, because no if_tsresol means 6,
2498
      // and time_units_per_second should be 1000000;
2499
0
      if (wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL, 9) == WTAP_OPTTYPE_SUCCESS) {
2500
0
        break;
2501
0
      }
2502
      /* FALLTHROUGH */
2503
0
    default:
2504
      // These "should not" happen either.
2505
0
      *err = WTAP_ERR_INTERNAL;
2506
0
      return false;
2507
0
    }
2508
0
  }
2509
2510
  /*
2511
   * Since we're not writing more than nanosecond resolution, if_tsoffset
2512
   * isn't necessary, as anything we can store in absolute timestamps in
2513
   * Wireshark records we can write to a file without an offset (unless
2514
   * we have 32-bit time_t, but that's rare these days.) So we remove it
2515
   * here, though in the long term we should keep it.
2516
   */
2517
0
  if (wtap_block_get_int64_option_value(idb, OPT_IDB_TSOFFSET, &tsoffset) == WTAP_OPTTYPE_SUCCESS) {
2518
0
    wtap_block_remove_option(idb, OPT_IDB_TSOFFSET);
2519
0
  }
2520
2521
0
  return true;
2522
0
}
2523
2524
bool
2525
wtap_dump_add_idb(wtap_dumper *wdh, wtap_block_t idb, int *err,
2526
                  char **err_info)
2527
0
{
2528
0
  wtap_block_t idb_copy;
2529
2530
0
  if (wdh->subtype_add_idb == NULL) {
2531
    /* Not supported. */
2532
0
    *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
2533
0
    *err_info = g_strdup("Adding IDBs isn't supported by this file type");
2534
0
    return false;
2535
0
  }
2536
2537
  /*
2538
   * Add a copy of this IDB to our array of IDBs.
2539
   */
2540
0
  idb_copy = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
2541
0
  wtap_block_copy(idb_copy, idb);
2542
0
  g_array_append_val(wdh->interface_data, idb_copy);
2543
2544
0
  if (!wtap_dump_fix_idb(wdh, idb_copy, err)) {
2545
0
    *err_info = ws_strdup_printf("pcapng: failed to lower time resolution to nanoseconds");
2546
0
    return false;
2547
0
  }
2548
2549
0
  *err = 0;
2550
0
  *err_info = NULL;
2551
0
  return (wdh->subtype_add_idb)(wdh, idb, err, err_info);
2552
0
}
2553
2554
bool
2555
wtap_dump(wtap_dumper *wdh, const wtap_rec *rec, int *err, char **err_info)
2556
0
{
2557
0
  *err = 0;
2558
0
  *err_info = NULL;
2559
0
  return (wdh->subtype_write)(wdh, rec, err, err_info);
2560
0
}
2561
2562
bool
2563
wtap_dump_flush(wtap_dumper *wdh, int *err)
2564
0
{
2565
0
  switch (wdh->compression_type) {
2566
0
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2567
0
  case WS_FILE_GZIP_COMPRESSED:
2568
0
    if (gzwfile_flush((GZWFILE_T)wdh->fh) == -1) {
2569
0
      *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2570
0
      return false;
2571
0
    }
2572
0
    break;
2573
0
#endif
2574
#ifdef HAVE_LZ4FRAME_H
2575
  case WS_FILE_LZ4_COMPRESSED:
2576
    if (lz4wfile_flush((LZ4WFILE_T)wdh->fh) == -1) {
2577
      *err = lz4wfile_geterr((LZ4WFILE_T)wdh->fh);
2578
      return false;
2579
    }
2580
    break;
2581
#endif /* HAVE_LZ4FRAME_H */
2582
0
  default:
2583
0
    if (fflush((FILE *)wdh->fh) == EOF) {
2584
0
      *err = errno;
2585
0
      return false;
2586
0
    }
2587
0
  }
2588
0
  return true;
2589
0
}
2590
2591
bool
2592
wtap_dump_close(wtap_dumper *wdh, bool *needs_reload,
2593
    int *err, char **err_info)
2594
0
{
2595
0
  bool ret = true;
2596
2597
0
  *err = 0;
2598
0
  *err_info = NULL;
2599
0
  if (wdh->subtype_finish != NULL) {
2600
    /* There's a finish routine for this dump stream. */
2601
0
    if (!(wdh->subtype_finish)(wdh, err, err_info))
2602
0
      ret = false;
2603
0
  }
2604
0
  errno = WTAP_ERR_CANT_CLOSE;
2605
0
  if (wtap_dump_file_close(wdh) == EOF) {
2606
0
    if (ret) {
2607
      /* The per-format finish function succeeded,
2608
         but the stream close didn't.  Save the
2609
         reason why. */
2610
0
      *err = errno;
2611
0
    }
2612
0
    ret = false;
2613
0
  }
2614
0
  if (needs_reload != NULL)
2615
0
    *needs_reload = wdh->needs_reload;
2616
0
  g_free(wdh->priv);
2617
0
  wtap_block_array_free(wdh->interface_data);
2618
0
  wtap_block_array_unref(wdh->dsbs_initial);
2619
0
  g_free(wdh);
2620
0
  return ret;
2621
0
}
2622
2623
int
2624
wtap_dump_file_type_subtype(const wtap_dumper *wdh)
2625
0
{
2626
0
  return wdh->file_type_subtype;
2627
0
}
2628
2629
int64_t
2630
wtap_get_bytes_dumped(const wtap_dumper *wdh)
2631
0
{
2632
0
  return wdh->bytes_dumped;
2633
0
}
2634
2635
void
2636
wtap_set_bytes_dumped(wtap_dumper *wdh, int64_t bytes_dumped)
2637
0
{
2638
0
  wdh->bytes_dumped = bytes_dumped;
2639
0
}
2640
2641
bool
2642
wtap_addrinfo_list_empty(const addrinfo_lists_t *addrinfo_lists)
2643
0
{
2644
0
  return (addrinfo_lists == NULL) ||
2645
0
      ((addrinfo_lists->ipv4_addr_list == NULL) &&
2646
0
       (addrinfo_lists->ipv6_addr_list == NULL));
2647
0
}
2648
2649
bool
2650
wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2651
0
{
2652
0
  if (!wdh || wdh->file_type_subtype < 0 ||
2653
0
      wdh->file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2654
0
      wtap_file_type_subtype_supports_block(wdh->file_type_subtype, WTAP_BLOCK_NAME_RESOLUTION) == BLOCK_NOT_SUPPORTED)
2655
0
    return false;
2656
0
  wdh->addrinfo_lists = addrinfo_lists;
2657
0
  return true;
2658
0
}
2659
2660
void
2661
wtap_dump_discard_name_resolution(wtap_dumper *wdh)
2662
0
{
2663
  /* As below for DSBs. */
2664
0
  if (wdh->nrbs_growing) {
2665
    /*
2666
     * Pretend we've written all of them.
2667
     */
2668
0
    wdh->nrbs_growing_written = wdh->nrbs_growing->len;
2669
0
  }
2670
0
}
2671
2672
void
2673
wtap_dump_discard_decryption_secrets(wtap_dumper *wdh)
2674
0
{
2675
  /*
2676
   * This doesn't free the data, as it might be pointed to
2677
   * from other structures; it merely marks all of them as
2678
   * having been written to the file, so that they don't
2679
   * get written by wtap_dump().
2680
   *
2681
   * XXX - our APIs for dealing with some metadata, such as
2682
   * resolved names, decryption secrets, and interface
2683
   * statistics is not very well oriented towards one-pass
2684
   * programs; this needs to be cleaned up.  See bug 15502.
2685
   */
2686
0
  if (wdh->dsbs_growing) {
2687
    /*
2688
     * Pretend we've written all of them.
2689
     */
2690
0
    wdh->dsbs_growing_written = wdh->dsbs_growing->len;
2691
0
  }
2692
0
}
2693
2694
void
2695
wtap_dump_discard_sysdig_meta_events(wtap_dumper *wdh)
2696
0
{
2697
  /* As above for DSBs. */
2698
0
  if (wdh->mevs_growing) {
2699
    /*
2700
     * Pretend we've written all of them.
2701
     */
2702
0
    wdh->mevs_growing_written = wdh->mevs_growing->len;
2703
0
  }
2704
0
}
2705
2706
/* internally open a file for writing (compressed or not) */
2707
static WFILE_T
2708
wtap_dump_file_open(const wtap_dumper *wdh, const char *filename)
2709
0
{
2710
0
  switch (wdh->compression_type) {
2711
0
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2712
0
  case WS_FILE_GZIP_COMPRESSED:
2713
0
    return gzwfile_open(filename);
2714
0
#endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
2715
#ifdef HAVE_LZ4FRAME_H
2716
  case WS_FILE_LZ4_COMPRESSED:
2717
    return lz4wfile_open(filename);
2718
#endif /* HAVE_LZ4FRAME_H */
2719
0
  default:
2720
0
    return ws_fopen(filename, "wb");
2721
0
  }
2722
0
}
2723
2724
/* internally open a file for writing (compressed or not) */
2725
static WFILE_T
2726
wtap_dump_file_fdopen(const wtap_dumper *wdh, int fd)
2727
0
{
2728
0
  switch (wdh->compression_type) {
2729
0
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2730
0
  case WS_FILE_GZIP_COMPRESSED:
2731
0
    return gzwfile_fdopen(fd);
2732
0
#endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
2733
#ifdef HAVE_LZ4FRAME_H
2734
  case WS_FILE_LZ4_COMPRESSED:
2735
    return lz4wfile_fdopen(fd);
2736
#endif /* HAVE_LZ4FRAME_H */
2737
0
  default:
2738
0
    return ws_fdopen(fd, "wb");
2739
0
  }
2740
0
}
2741
2742
/* internally writing raw bytes (compressed or not). Updates wdh->bytes_dumped on success */
2743
bool
2744
wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2745
0
{
2746
0
  size_t nwritten;
2747
2748
0
  switch (wdh->compression_type) {
2749
0
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2750
0
  case WS_FILE_GZIP_COMPRESSED:
2751
0
    nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2752
    /*
2753
     * gzwfile_write() returns 0 on error.
2754
     */
2755
0
    if (nwritten == 0) {
2756
0
      *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2757
0
      return false;
2758
0
    }
2759
0
    break;
2760
0
#endif
2761
#ifdef HAVE_LZ4FRAME_H
2762
  case WS_FILE_LZ4_COMPRESSED:
2763
    nwritten = lz4wfile_write((LZ4WFILE_T)wdh->fh, buf, bufsize);
2764
    /*
2765
     * lz4wfile_write() returns 0 on error.
2766
     */
2767
    if (nwritten == 0) {
2768
      *err = lz4wfile_geterr((LZ4WFILE_T)wdh->fh);
2769
      return false;
2770
    }
2771
    break;
2772
#endif /* HAVE_LZ4FRAME_H */
2773
0
  default:
2774
0
    errno = WTAP_ERR_CANT_WRITE;
2775
0
    nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2776
    /*
2777
     * At least according to the macOS man page,
2778
     * this can return a short count on an error.
2779
     */
2780
0
    if (nwritten != bufsize) {
2781
0
      if (ferror((FILE *)wdh->fh))
2782
0
        *err = errno;
2783
0
      else
2784
0
        *err = WTAP_ERR_SHORT_WRITE;
2785
0
      return false;
2786
0
    }
2787
0
  }
2788
0
  wdh->bytes_dumped += bufsize;
2789
0
  return true;
2790
0
}
2791
2792
/* internally close a file for writing (compressed or not) */
2793
static int
2794
wtap_dump_file_close(wtap_dumper *wdh)
2795
0
{
2796
0
  switch (wdh->compression_type) {
2797
0
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2798
0
  case WS_FILE_GZIP_COMPRESSED:
2799
0
    return gzwfile_close((GZWFILE_T)wdh->fh);
2800
0
#endif
2801
#ifdef HAVE_LZ4FRAME_H
2802
  case WS_FILE_LZ4_COMPRESSED:
2803
    return lz4wfile_close((LZ4WFILE_T)wdh->fh);
2804
#endif /* HAVE_LZ4FRAME_H */
2805
0
  default:
2806
0
    return fclose((FILE *)wdh->fh);
2807
0
  }
2808
0
}
2809
2810
int64_t
2811
wtap_dump_file_seek(wtap_dumper *wdh, int64_t offset, int whence, int *err)
2812
0
{
2813
0
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H)
2814
0
  if (wdh->compression_type != WS_FILE_UNCOMPRESSED) {
2815
0
    *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2816
0
    return -1;
2817
0
  } else
2818
0
#endif
2819
0
  {
2820
0
    if (-1 == ws_fseek64((FILE *)wdh->fh, offset, whence)) {
2821
0
      *err = errno;
2822
0
      return -1;
2823
0
    } else
2824
0
    {
2825
0
      return 0;
2826
0
    }
2827
0
  }
2828
0
}
2829
2830
int64_t
2831
wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2832
0
{
2833
0
  int64_t rval;
2834
0
#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H)
2835
  /* XXX - The gzip_writer and lz4_writer structs do contain the
2836
   * position in the uncompressed data as an int64_t so we could
2837
   * return that, but that should be the same as bytes_dumped as
2838
   * we can't seek while compressing. (Alternatively we could return
2839
   * the position in the compressed file, but that seems less useful.)
2840
   */
2841
0
  if (wdh->compression_type != WS_FILE_UNCOMPRESSED) {
2842
0
    *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2843
0
    return -1;
2844
0
  } else
2845
0
#endif
2846
0
  {
2847
0
    if (-1 == (rval = ws_ftell64((FILE *)wdh->fh))) {
2848
0
      *err = errno;
2849
0
      return -1;
2850
0
    } else
2851
0
    {
2852
0
      return rval;
2853
0
    }
2854
0
  }
2855
0
}
2856
2857
void
2858
cleanup_open_routines(void)
2859
0
{
2860
0
  unsigned i;
2861
0
  struct open_info *i_open;
2862
2863
0
  if (open_routines != NULL && open_info_arr) {
2864
0
    for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
2865
0
      if (i_open->extensions != NULL)
2866
0
        g_strfreev(i_open->extensions_set);
2867
0
    }
2868
2869
0
    g_array_free(open_info_arr, true);
2870
0
    open_info_arr = NULL;
2871
0
  }
2872
0
}
2873
2874
/*
2875
 * Allow built-in file handlers (but *not* plugin file handlers!) to
2876
 * register a "backwards-compatibility" name and file type value, to
2877
 * put in the Lua wtap_filetypes table.
2878
 *
2879
 * This is only to be used as long as we have that table; new Lua
2880
 * code should use wtap_name_to_file_type_subtype() to look up
2881
 * file types by their name, just as C code should.
2882
 *
2883
 * The backwards-compatibility names are the old WTAP_FILE_TYPE_SUBTYPE_
2884
 * #define name, with WTAP_FILE_TYPE_SUBTYPE_ removed.
2885
 */
2886
2887
static GArray *backwards_compatibility_lua_names;
2888
2889
void
2890
// NOLINTNEXTLINE(misc-no-recursion)
2891
wtap_register_backwards_compatibility_lua_name(const char *name, int ft)
2892
1.41k
{
2893
1.41k
  struct backwards_compatibiliity_lua_name entry;
2894
2895
  /*
2896
   * Create the table if it doesn't already exist.
2897
   * Use the same size as we do for the file type/subtype table.
2898
   */
2899
1.41k
  if (backwards_compatibility_lua_names == NULL) {
2900
14
    backwards_compatibility_lua_names = g_array_sized_new(false,
2901
14
        true, sizeof(struct backwards_compatibiliity_lua_name),
2902
14
        wtap_module_count*2);
2903
2904
    /*
2905
     * Extra backwards compatibility hack - add entries
2906
     * for time stamp precision values(!), as well as
2907
     * for "UNKNOWN" and types that don't yet register
2908
     * themselves.
2909
     *
2910
     * If new WS_TSPREC_ value are added, don't bother
2911
     * adding them to this table; any Lua program that
2912
     * would use them should use the wtap_tsprecs type.
2913
     *
2914
     * (Recursion: see "recursion".)
2915
     */
2916
14
    wtap_register_backwards_compatibility_lua_name("TSPREC_SEC",
2917
14
        WTAP_TSPREC_SEC);
2918
14
    wtap_register_backwards_compatibility_lua_name("TSPREC_DSEC",
2919
14
        WTAP_TSPREC_100_MSEC);
2920
14
    wtap_register_backwards_compatibility_lua_name("TSPREC_CSEC",
2921
14
        WTAP_TSPREC_10_MSEC);
2922
14
    wtap_register_backwards_compatibility_lua_name("TSPREC_MSEC",
2923
14
        WTAP_TSPREC_MSEC);
2924
14
    wtap_register_backwards_compatibility_lua_name("TSPREC_USEC",
2925
14
        WTAP_TSPREC_USEC);
2926
14
    wtap_register_backwards_compatibility_lua_name("TSPREC_NSEC",
2927
14
        WTAP_TSPREC_NSEC);
2928
14
    wtap_register_backwards_compatibility_lua_name("UNKNOWN",
2929
14
        WTAP_FILE_TYPE_SUBTYPE_UNKNOWN);
2930
14
  }
2931
1.41k
  entry.name = name;
2932
1.41k
  entry.ft = ft;
2933
1.41k
  g_array_append_val(backwards_compatibility_lua_names, entry);
2934
1.41k
}
2935
2936
const GArray *
2937
get_backwards_compatibility_lua_table(void)
2938
0
{
2939
0
  return backwards_compatibility_lua_names;
2940
0
}
2941
2942
/*
2943
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2944
 *
2945
 * Local variables:
2946
 * c-basic-offset: 8
2947
 * tab-width: 8
2948
 * indent-tabs-mode: t
2949
 * End:
2950
 *
2951
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2952
 * :indentSize=8:tabSize=8:noTabs=false:
2953
 */