### Bug Summary

File: | wiretap/file_access.c
Warning: | line 2290, column 13 Potential leak of memory pointed to by 'wdh'

### Annotated Source Code

Press '?' to see keyboard shortcuts

Show analyzer invocation
clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name file_access.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/libxml2 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D wiretap_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -I /builds/wireshark/wireshark/build/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-11-04-100327-3623-1 -x c /builds/wireshark/wireshark/wiretap/file_access.c

Keyboard shortcuts:

- Use 'j/k' keys for keyboard navigation
- Use 'Shift+S' to show/hide relevant lines
- Use '?' to toggle this window

Close
Show only relevant lines Show control flow arrows

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