File: | wiretap/libpcap.c |
Warning: | line 1442, column 3 Value stored to 'bytes_to_read' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* libpcap.c |
2 | * |
3 | * Wiretap Library |
4 | * Copyright (c) 1998 by Gilbert Ramirez <[email protected]> |
5 | * |
6 | * SPDX-License-Identifier: GPL-2.0-or-later |
7 | */ |
8 | |
9 | #include "config.h" |
10 | #include "libpcap.h" |
11 | |
12 | #include <stdlib.h> |
13 | #include <string.h> |
14 | #include "wtap-int.h" |
15 | #include "file_wrappers.h" |
16 | #include "required_file_handlers.h" |
17 | #include "pcap-common.h" |
18 | #include "pcap-encap.h" |
19 | #include "erf-common.h" |
20 | #include <wsutil/ws_assert.h> |
21 | |
22 | /* |
23 | * The "libpcap" file format was determined by reading the "libpcap" code; |
24 | * wiretap reads the "libpcap" file format with its own code, rather than |
25 | * using the "libpcap" library's code to read it. |
26 | * See source to the "libpcap" library for information on the "libpcap" |
27 | * file format. |
28 | */ |
29 | |
30 | /* |
31 | * Private per-wtap_t data needed to read a file. |
32 | */ |
33 | typedef enum { |
34 | NOT_SWAPPED, |
35 | SWAPPED, |
36 | MAYBE_SWAPPED |
37 | } swapped_type_t; |
38 | |
39 | /* |
40 | * Variants of pcap, some distinguished by the magic number and some, |
41 | * alas, not. |
42 | * |
43 | * (Don't do that. Srsly.) |
44 | */ |
45 | typedef enum { |
46 | PCAP, /* OG pcap */ |
47 | PCAP_NSEC, /* PCAP with nanosecond resolution */ |
48 | PCAP_AIX, /* AIX pcap */ |
49 | PCAP_SS990417, /* Modified, from 1999-04-17 patch */ |
50 | PCAP_SS990915, /* Modified, from 1999-09-15 patch */ |
51 | PCAP_SS991029, /* Modified, from 1999-10-29 patch */ |
52 | PCAP_NOKIA, /* Nokia pcap */ |
53 | PCAP_UNKNOWN /* Unknown as yet */ |
54 | } pcap_variant_t; |
55 | |
56 | typedef struct { |
57 | bool_Bool byte_swapped; |
58 | swapped_type_t lengths_swapped; |
59 | uint16_t version_major; |
60 | uint16_t version_minor; |
61 | pcap_variant_t variant; |
62 | int fcs_len; |
63 | void *encap_priv; |
64 | } libpcap_t; |
65 | |
66 | /* Try to read the first few records of the capture file. */ |
67 | static bool_Bool libpcap_try_variants(wtap *wth, const pcap_variant_t *variants, |
68 | size_t n_variants, int *err, char **err_info); |
69 | static int libpcap_try_variant(wtap *wth, pcap_variant_t variant, |
70 | int *err, char **err_info); |
71 | typedef enum { |
72 | TRY_REC_KEEP_READING, /* Keep reading records */ |
73 | TRY_REC_EOF, /* EOF - no ore records to read */ |
74 | TRY_REC_ERROR /* Error - give up */ |
75 | } try_record_ret_t; |
76 | static try_record_ret_t libpcap_try_record(wtap *wth, pcap_variant_t variant, |
77 | int *figure_of_meritp, int *err, char **err_info); |
78 | |
79 | static bool_Bool libpcap_read(wtap *wth, wtap_rec *rec, |
80 | int *err, char **err_info, int64_t *data_offset); |
81 | static bool_Bool libpcap_seek_read(wtap *wth, int64_t seek_off, |
82 | wtap_rec *rec, int *err, char **err_info); |
83 | static bool_Bool libpcap_read_packet(wtap *wth, FILE_T fh, |
84 | wtap_rec *rec, int *err, char **err_info); |
85 | static bool_Bool libpcap_read_header(wtap *wth, FILE_T fh, int *err, char **err_info, |
86 | struct pcaprec_ss990915_hdr *hdr); |
87 | static void libpcap_close(wtap *wth); |
88 | |
89 | static bool_Bool libpcap_dump_pcap(wtap_dumper *wdh, const wtap_rec *rec, |
90 | int *err, char **err_info); |
91 | static bool_Bool libpcap_dump_pcap_nsec(wtap_dumper *wdh, const wtap_rec *rec, |
92 | int *err, char **err_info); |
93 | static bool_Bool libpcap_dump_pcap_ss990417(wtap_dumper *wdh, const wtap_rec *rec, |
94 | int *err, char **err_info); |
95 | static bool_Bool libpcap_dump_pcap_ss990915(wtap_dumper *wdh, const wtap_rec *rec, |
96 | int *err, char **err_info); |
97 | static bool_Bool libpcap_dump_pcap_ss991029(wtap_dumper *wdh, const wtap_rec *rec, |
98 | int *err, char **err_info); |
99 | static bool_Bool libpcap_dump_pcap_nokia(wtap_dumper *wdh, const wtap_rec *rec, |
100 | int *err, char **err_info); |
101 | |
102 | /* |
103 | * Subfields of the field containing the link-layer header type. |
104 | * |
105 | * Link-layer header types are assigned for both pcap and |
106 | * pcapng, and the same value must work with both. In pcapng, |
107 | * the link-layer header type field in an Interface Description |
108 | * Block is 16 bits, so only the bottommost 16 bits of the |
109 | * link-layer header type in a pcap file can be used for the |
110 | * header type value. |
111 | * |
112 | * In libpcap, the upper 16 bits, from the top down, are divided into: |
113 | * |
114 | * A 4-bit "FCS length" field, to allow the FCS length to |
115 | * be specified, just as it can be specified in the if_fcslen |
116 | * field of the pcapng IDB. The field is in units of 16 bits, |
117 | * i.e. 1 means 16 bits of FCS, 2 means 32 bits of FCS, etc.. |
118 | * |
119 | * A reserved bit, which must be zero. |
120 | * |
121 | * An "FCS length present" flag; if 0, the "FCS length" field |
122 | * should be ignored, and if 1, the "FCS length" field should |
123 | * be used. |
124 | * |
125 | * 10 reserved bits, which must be zero. They were originally |
126 | * intended to be used as a "class" field, allowing additional |
127 | * classes of link-layer types to be defined, with a class value |
128 | * of 0 indicating that the link-layer type is a LINKTYPE_ value. |
129 | * A value of 0x224 was, at one point, used by NetBSD to define |
130 | * "raw" packet types, with the lower 16 bits containing a |
131 | * NetBSD AF_ value; see |
132 | * |
133 | * https://marc.info/?l=tcpdump-workers&m=98296750229149&w=2 |
134 | * |
135 | * It's unknown whether those were ever used in capture files, |
136 | * or if the intent was just to use it as a link-layer type |
137 | * for BPF programs; NetBSD's libpcap used to support them in |
138 | * the BPF code generator, but it no longer does so. If it |
139 | * was ever used in capture files, or if classes other than |
140 | * "LINKTYPE_ value" are ever useful in capture files, we could |
141 | * re-enable this, and use the reserved 16 bits following the |
142 | * link-layer type in pcapng files to hold the class information |
143 | * there. (Note, BTW, that LINKTYPE_RAW/DLT_RAW is now being |
144 | * interpreted by libpcap, tcpdump, and Wireshark as "raw IP", |
145 | * including both IPv4 and IPv6, with the version number in the |
146 | * header being checked to see which it is, not just "raw IPv4"; |
147 | * there are LINKTYPE_IPV4/DLT_IPV4 and LINKTYPE_IPV6/DLT_IPV6 |
148 | * values if "these are IPv{4,6} and only IPv{4,6} packets" |
149 | * types are needed.) |
150 | * |
151 | * Or we might be able to use it for other purposes. |
152 | */ |
153 | #define LT_LINKTYPE(x)((x) & 0x0000FFFF) ((x) & 0x0000FFFF) |
154 | #define LT_RESERVED1(x)((x) & 0x03FF0000) ((x) & 0x03FF0000) |
155 | #define LT_FCS_LENGTH_PRESENT(x)((x) & 0x04000000) ((x) & 0x04000000) |
156 | #define LT_FCS_LENGTH(x)(((x) & 0xF0000000) >> 28) (((x) & 0xF0000000) >> 28) |
157 | #define LT_FCS_DATALINK_EXT(x)(((x) & 0xF) << 28) | 0x04000000) (((x) & 0xF) << 28) | 0x04000000) |
158 | |
159 | /* |
160 | * Private file type/subtype values; pcap and nanosecond-resolution |
161 | * pcap are imported from wiretap/file_access.c. |
162 | */ |
163 | static int pcap_aix_file_type_subtype = -1; |
164 | static int pcap_ss990417_file_type_subtype = -1; |
165 | static int pcap_ss990915_file_type_subtype = -1; |
166 | static int pcap_ss991029_file_type_subtype = -1; |
167 | static int pcap_nokia_file_type_subtype = -1; |
168 | |
169 | /* |
170 | * pcap variants that use the standard magic number. |
171 | */ |
172 | static const pcap_variant_t variants_standard[] = { |
173 | PCAP, |
174 | PCAP_SS990417, |
175 | PCAP_NOKIA |
176 | }; |
177 | #define N_VARIANTS_STANDARD(sizeof (variants_standard) / sizeof ((variants_standard)[0]) ) G_N_ELEMENTS(variants_standard)(sizeof (variants_standard) / sizeof ((variants_standard)[0]) ) |
178 | |
179 | /* |
180 | * pcap variants that use the modified magic number. |
181 | */ |
182 | static const pcap_variant_t variants_modified[] = { |
183 | PCAP_SS991029, |
184 | PCAP_SS990915 |
185 | }; |
186 | #define N_VARIANTS_MODIFIED(sizeof (variants_modified) / sizeof ((variants_modified)[0]) ) G_N_ELEMENTS(variants_modified)(sizeof (variants_modified) / sizeof ((variants_modified)[0]) ) |
187 | |
188 | wtap_open_return_val libpcap_open(wtap *wth, int *err, char **err_info) |
189 | { |
190 | uint32_t magic; |
191 | struct pcap_hdr hdr; |
192 | bool_Bool byte_swapped; |
193 | pcap_variant_t variant; |
194 | libpcap_t *libpcap; |
195 | bool_Bool skip_ixia_extra = false0; |
196 | |
197 | /* Read in the number that should be at the start of a "libpcap" file */ |
198 | if (!wtap_read_bytes(wth->fh, &magic, sizeof magic, err, err_info)) { |
199 | if (*err != WTAP_ERR_SHORT_READ-12) |
200 | return WTAP_OPEN_ERROR; |
201 | return WTAP_OPEN_NOT_MINE; |
202 | } |
203 | |
204 | switch (magic) { |
205 | |
206 | case PCAP_MAGIC0xa1b2c3d4: |
207 | /* Host that wrote it has our byte order, and was running |
208 | a program using either standard or ss990417 libpcap, |
209 | or maybe it was written by AIX. That means we don't |
210 | yet know the variant. */ |
211 | byte_swapped = false0; |
212 | variant = PCAP_UNKNOWN; |
213 | break; |
214 | |
215 | case PCAP_SWAPPED_MAGIC0xd4c3b2a1: |
216 | /* Host that wrote it has a byte order opposite to ours, |
217 | and was running a program using either standard or |
218 | ss990417 libpcap, or maybe it was written by AIX. |
219 | That means we don't yet know the variant. */ |
220 | byte_swapped = true1; |
221 | variant = PCAP_UNKNOWN; |
222 | break; |
223 | |
224 | case PCAP_IXIAHW_MAGIC0x1c0001ac: |
225 | /* Ixia "lcap" hardware-capture variant, in our |
226 | byte order, in which there's an extra 4-byte |
227 | field at the end of the file header, containing |
228 | the total number of bytes of packet records in |
229 | the file, i.e. the file size minus the file header |
230 | size. It's otherwise like standard pcap, with |
231 | nanosecond time-stamp resolution. |
232 | |
233 | See issue #14073. */ |
234 | skip_ixia_extra = true1; |
235 | byte_swapped = false0; |
236 | variant = PCAP_NSEC; |
237 | break; |
238 | |
239 | case PCAP_SWAPPED_IXIAHW_MAGIC0xac01001c: |
240 | /* Ixia "lcap" hardware-capture variant, in a byte |
241 | order opposite to ours, in which there's an extra |
242 | 4-byte field at the end of the file header, |
243 | containing the total number of bytes of packet |
244 | records in the file, i.e. the file size minus |
245 | the file header size. It's otherwise like standard |
246 | pcap with nanosecond time-stamp resolution. |
247 | |
248 | See issue #14073. */ |
249 | skip_ixia_extra = true1; |
250 | byte_swapped = true1; |
251 | variant = PCAP_NSEC; |
252 | break; |
253 | |
254 | case PCAP_IXIASW_MAGIC0x1c0001ab: |
255 | /* Ixia "lcap" software-capture variant, in our |
256 | byte order, in which there's an extra 4-byte |
257 | field at the end of the file header, containing |
258 | the total number of bytes of packet records in |
259 | the file, i.e. the file size minus the file header |
260 | size. It's otherwise like standard pcap, with |
261 | microsecond time-stamp resolution. |
262 | |
263 | See issue #14073. */ |
264 | skip_ixia_extra = true1; |
265 | byte_swapped = false0; |
266 | variant = PCAP; |
267 | break; |
268 | |
269 | case PCAP_SWAPPED_IXIASW_MAGIC0xab01001c: |
270 | /* Ixia "lcap" software-capture variant, in a byte |
271 | order opposite to ours, in which there's an extra |
272 | 4-byte field at the end of the file header, |
273 | containing the total number of bytes of packet |
274 | records in the file, i.e. the file size minus |
275 | the file header size. It's otherwise like standard |
276 | pcap with microsecond time-stamp resolution. |
277 | |
278 | See issue #14073. */ |
279 | skip_ixia_extra = true1; |
280 | byte_swapped = true1; |
281 | variant = PCAP; |
282 | break; |
283 | |
284 | case PCAP_MODIFIED_MAGIC0xa1b2cd34: |
285 | /* Host that wrote it has our byte order, and was running |
286 | a program using either ss990915 or ss991029 libpcap. |
287 | That means we don't yet know the variant; there's |
288 | no obvious default, so default to "unknown". */ |
289 | byte_swapped = false0; |
290 | variant = PCAP_UNKNOWN; |
291 | break; |
292 | |
293 | case PCAP_SWAPPED_MODIFIED_MAGIC0x34cdb2a1: |
294 | /* Host that wrote it out has a byte order opposite to |
295 | ours, and was running a program using either ss990915 |
296 | or ss991029 libpcap. That means we don't yet know |
297 | the variant; there's no obvious default, so default |
298 | to "unknown". */ |
299 | byte_swapped = true1; |
300 | variant = PCAP_UNKNOWN; |
301 | break; |
302 | |
303 | case PCAP_NSEC_MAGIC0xa1b23c4d: |
304 | /* Host that wrote it has our byte order, and was writing |
305 | the file in a format similar to standard libpcap |
306 | except that the time stamps have nanosecond resolution. */ |
307 | byte_swapped = false0; |
308 | variant = PCAP_NSEC; |
309 | break; |
310 | |
311 | case PCAP_SWAPPED_NSEC_MAGIC0x4d3cb2a1: |
312 | /* Host that wrote it out has a byte order opposite to |
313 | ours, and was writing the file in a format similar to |
314 | standard libpcap except that the time stamps have |
315 | nanosecond resolution. */ |
316 | byte_swapped = true1; |
317 | variant = PCAP_NSEC; |
318 | break; |
319 | |
320 | default: |
321 | /* Not a "libpcap" type we know about. */ |
322 | return WTAP_OPEN_NOT_MINE; |
323 | } |
324 | |
325 | /* Read the rest of the header. */ |
326 | if (!wtap_read_bytes(wth->fh, &hdr, sizeof hdr, err, err_info)) |
327 | return WTAP_OPEN_ERROR; |
328 | if (skip_ixia_extra) { |
329 | /* |
330 | * Skip 4 bytes of size information in the file header. |
331 | */ |
332 | if (!wtap_read_bytes(wth->fh, NULL((void*)0), 4, err, err_info)) |
333 | return WTAP_OPEN_ERROR; |
334 | } |
335 | |
336 | if (byte_swapped) { |
337 | /* Byte-swap the header fields about which we care. */ |
338 | magic = GUINT32_SWAP_LE_BE(magic)(((guint32) ( (((guint32) (magic) & (guint32) 0x000000ffU ) << 24) | (((guint32) (magic) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (magic) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (magic) & (guint32) 0xff000000U ) >> 24)))); |
339 | hdr.version_major = GUINT16_SWAP_LE_BE(hdr.version_major)(((guint16) ( (guint16) ((guint16) (hdr.version_major) >> 8) | (guint16) ((guint16) (hdr.version_major) << 8)))); |
340 | hdr.version_minor = GUINT16_SWAP_LE_BE(hdr.version_minor)(((guint16) ( (guint16) ((guint16) (hdr.version_minor) >> 8) | (guint16) ((guint16) (hdr.version_minor) << 8)))); |
341 | hdr.snaplen = GUINT32_SWAP_LE_BE(hdr.snaplen)(((guint32) ( (((guint32) (hdr.snaplen) & (guint32) 0x000000ffU ) << 24) | (((guint32) (hdr.snaplen) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (hdr.snaplen) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (hdr.snaplen) & (guint32) 0xff000000U ) >> 24)))); |
342 | hdr.network = GUINT32_SWAP_LE_BE(hdr.network)(((guint32) ( (((guint32) (hdr.network) & (guint32) 0x000000ffU ) << 24) | (((guint32) (hdr.network) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (hdr.network) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (hdr.network) & (guint32) 0xff000000U ) >> 24)))); |
343 | } |
344 | if (hdr.version_major < 2) { |
345 | /* We only support version 2.0 and later. */ |
346 | *err = WTAP_ERR_UNSUPPORTED-4; |
347 | *err_info = ws_strdup_printf("pcap: major version %u unsupported",wmem_strdup_printf(((void*)0), "pcap: major version %u unsupported" , hdr.version_major) |
348 | hdr.version_major)wmem_strdup_printf(((void*)0), "pcap: major version %u unsupported" , hdr.version_major); |
349 | return WTAP_OPEN_ERROR; |
350 | } |
351 | |
352 | /* This is a libpcap file */ |
353 | wth->subtype_read = libpcap_read; |
354 | wth->subtype_seek_read = libpcap_seek_read; |
355 | wth->subtype_close = libpcap_close; |
356 | wth->snapshot_length = hdr.snaplen; |
357 | libpcap = g_new0(libpcap_t, 1)((libpcap_t *) g_malloc0_n ((1), sizeof (libpcap_t))); |
358 | wth->priv = (void *)libpcap; |
359 | /* |
360 | * Fill in the information we already know or can determine |
361 | * at this point, so the private data is usable by the code |
362 | * that tries reading packets as a heuristic to guess the |
363 | * variant. |
364 | */ |
365 | libpcap->byte_swapped = byte_swapped; |
366 | /* In file format version 2.3, the order of the "incl_len" and |
367 | "orig_len" fields in the per-packet header was reversed, |
368 | in order to match the BPF header layout. |
369 | |
370 | Therefore, in files with versions prior to that, we must swap |
371 | those two fields. |
372 | |
373 | Unfortunately, some files were, according to a comment in the |
374 | "libpcap" source, written with version 2.3 in their headers |
375 | but without the interchanged fields, so if "incl_len" is |
376 | greater than "orig_len" - which would make no sense - we |
377 | assume that we need to swap them in version 2.3 files |
378 | as well. |
379 | |
380 | In addition, DG/UX's tcpdump uses version 543.0, and writes |
381 | the two fields in the pre-2.3 order. |
382 | |
383 | Furthermore, files that don't have a magic number of 2.4 |
384 | were not used by the variant forms of pcap that need |
385 | heuristic tests to detect. */ |
386 | switch (hdr.version_major) { |
387 | |
388 | case 2: |
389 | if (hdr.version_minor < 3) { |
390 | libpcap->lengths_swapped = SWAPPED; |
391 | variant = PCAP; |
392 | } else if (hdr.version_minor == 3) { |
393 | libpcap->lengths_swapped = MAYBE_SWAPPED; |
394 | variant = PCAP; |
395 | } else |
396 | libpcap->lengths_swapped = NOT_SWAPPED; |
397 | break; |
398 | |
399 | case 543: |
400 | libpcap->lengths_swapped = SWAPPED; |
401 | variant = PCAP; |
402 | break; |
403 | |
404 | default: |
405 | libpcap->lengths_swapped = NOT_SWAPPED; |
406 | break; |
407 | } |
408 | libpcap->version_major = hdr.version_major; |
409 | libpcap->version_minor = hdr.version_minor; |
410 | /* |
411 | * Check whether this is an AIX pcap before we convert the |
412 | * link-layer type in the header file to an encapsulation, |
413 | * because AIX pcaps use RFC 1573 ifType values in the header. |
414 | * |
415 | * AIX pcap files use the standard magic number, and have a |
416 | * major and minor version of 2. |
417 | * |
418 | * Unfortunately, that's also true of older versions of libpcap, |
419 | * so we need to do some heuristics to try to identify AIX pcap |
420 | * files. |
421 | */ |
422 | if (magic == PCAP_MAGIC0xa1b2c3d4 && hdr.version_major == 2 && |
423 | hdr.version_minor == 2) { |
424 | /* |
425 | * The AIX libpcap uses RFC 1573 ifType values rather |
426 | * than LINKTYPE_/DLT_ values in the header; the ifType |
427 | * values for LAN devices are: |
428 | * |
429 | * Ethernet 6 |
430 | * Token Ring 9 |
431 | * FDDI 15 |
432 | * |
433 | * which correspond to LINKTYPE_IEEE802_5/DLT_IEEE802 (used |
434 | * for Token Ring), LINKTYPE_PPP/DLT_PPP, and |
435 | * LINKTYPE_SLIP_BSDOS/DLT_SLIP_BSDOS, respectively, and |
436 | * the ifType value for a loopback interface is 24, which |
437 | * currently isn't used by any version of libpcap I know |
438 | * about (and, as tcpdump.org are assigning LINKTYPE_/DLT_ |
439 | * values above 100, and NetBSD started assigning values |
440 | * starting at 50, and the values chosen by other libpcaps |
441 | * appear to stop at 19, it's probably not going to be used |
442 | * by any libpcap in the future). |
443 | * |
444 | * So we shall assume that if the network type is 6, 9, 15, |
445 | * or 24 it's AIX libpcap. |
446 | * |
447 | * We also assume those older versions of libpcap didn't use |
448 | * LINKTYPE_IEEE802_5/DLT_IEEE802 for Token Ring, and didn't |
449 | * use LINKTYPE_SLIP_BSDOS/DLT_SLIP_BSDOS as that came later. |
450 | * It may have used LINKTYPE_PPP/DLT_PPP, however, in which |
451 | * case we're out of luck; we assume it's Token Ring in AIX |
452 | * libpcap rather than PPP in standard libpcap, as you're |
453 | * probably more likely to be handing an AIX libpcap token- |
454 | *ring capture than an old (pre-libpcap 0.4) PPP capture to |
455 | * Wireshark. |
456 | * |
457 | * AIX pcap files didn't use the upper 16 bits, so we don't |
458 | * need to ignore them here - they'll be 0. |
459 | */ |
460 | switch (hdr.network) { |
461 | |
462 | case 6: |
463 | hdr.network = 1; /* LINKTYPE_EN10MB, Ethernet */ |
464 | variant = PCAP_AIX; |
465 | break; |
466 | |
467 | case 9: |
468 | hdr.network = 6; /* LINKTYPE_IEEE802_5, Token Ring */ |
469 | variant = PCAP_AIX; |
470 | break; |
471 | |
472 | case 15: |
473 | hdr.network = 10; /* LINKTYPE_FDDI, FDDI */ |
474 | variant = PCAP_AIX; |
475 | break; |
476 | |
477 | case 24: |
478 | hdr.network = 0; /* LINKTYPE_NULL, loopback */ |
479 | variant = PCAP_AIX; |
480 | break; |
481 | } |
482 | } |
483 | |
484 | /* |
485 | * Check the main reserved field. |
486 | */ |
487 | if (LT_RESERVED1(hdr.network)((hdr.network) & 0x03FF0000) != 0) { |
488 | *err = WTAP_ERR_UNSUPPORTED-4; |
489 | *err_info = ws_strdup_printf("pcap: network type reserved field not zero (0x%08x)",wmem_strdup_printf(((void*)0), "pcap: network type reserved field not zero (0x%08x)" , ((hdr.network) & 0x03FF0000)) |
490 | LT_RESERVED1(hdr.network))wmem_strdup_printf(((void*)0), "pcap: network type reserved field not zero (0x%08x)" , ((hdr.network) & 0x03FF0000)); |
491 | return WTAP_OPEN_ERROR; |
492 | } |
493 | |
494 | /* |
495 | * Map the link-layer type from the "network" field in |
496 | * the header to a Wiretap encapsulation. |
497 | */ |
498 | wth->file_encap = wtap_pcap_encap_to_wtap_encap(LT_LINKTYPE(hdr.network)((hdr.network) & 0x0000FFFF)); |
499 | if (wth->file_encap == WTAP_ENCAP_UNKNOWN0) { |
500 | *err = WTAP_ERR_UNSUPPORTED-4; |
501 | *err_info = ws_strdup_printf("pcap: network type %u unknown or unsupported",wmem_strdup_printf(((void*)0), "pcap: network type %u unknown or unsupported" , hdr.network) |
502 | hdr.network)wmem_strdup_printf(((void*)0), "pcap: network type %u unknown or unsupported" , hdr.network); |
503 | return WTAP_OPEN_ERROR; |
504 | } |
505 | |
506 | /* |
507 | * Extract the FCS information, if present. |
508 | */ |
509 | libpcap->fcs_len = -1; |
510 | if (LT_FCS_LENGTH_PRESENT(hdr.network)((hdr.network) & 0x04000000)) { |
511 | /* |
512 | * We have an FCS length, in units of 16 bits. |
513 | * Convert it to bits. |
514 | */ |
515 | libpcap->fcs_len = LT_FCS_LENGTH(hdr.network)(((hdr.network) & 0xF0000000) >> 28) * 16; |
516 | } |
517 | |
518 | libpcap->encap_priv = NULL((void*)0); |
519 | |
520 | /* |
521 | * If this file has the standard magic number, it could be |
522 | * one of a number of variants, including regular pcap, the |
523 | * AIX variant, the ss990417 variant, and a Nokia variant. |
524 | * The ss990417 variant is used in, for example, Red Hat 6.1, |
525 | * so some versions of AIX, RH 6.1, and some Nokia devices |
526 | * write files that can't be read by any software that expects |
527 | * standard libpcap packet record headers if the magic number |
528 | * is the standard magic number (e.g., any program such as |
529 | * tcpdump that uses libpcap, when using the standard libpcap, |
530 | * and Wireshark if we don't do the heuristics below). |
531 | * |
532 | * If this file has the patched magic number, used by the |
533 | * ss990915 and ss991029 variants, then it could be either |
534 | * of those. The ss991029 variant uses the same packet |
535 | * record header as the ss990417 variant, but the ss990915 |
536 | * variant uses a packet record header with some additional |
537 | * fields and it is used in, for example, SuSE 6.3, so SuSE |
538 | * 6.3 writes files that can't be read by any software that |
539 | * expects ss990417 packet record headers if the magic number |
540 | * is the modified magic number. |
541 | * |
542 | * So, for the standard and modified magic number: |
543 | * |
544 | * For the standard magic number, we first do some heuristic |
545 | * checks of data from the file header to see if it looks like |
546 | * an AIX libpcap file. If so, we choose PCAP_AIX as the variant, |
547 | * and we don't have to do any more guessing. |
548 | * |
549 | * Otherwise, we determine the variant by, for each variant, |
550 | * trying to read the first few packets as if that file were |
551 | * in that variant's format, and seeing whether the packet |
552 | * record headers make sense. |
553 | * |
554 | * But don't do the latter if the input is a pipe; that would mean |
555 | * the open won't complete until two packets have been written to |
556 | * the pipe, unless the pipe is closed after one packet has been |
557 | * written, so a program reading from the file won't see the |
558 | * first packet until the second packet has been written. |
559 | */ |
560 | switch (magic) { |
561 | |
562 | case PCAP_MAGIC0xa1b2c3d4: |
563 | /* |
564 | * Original libpcap magic. |
565 | * |
566 | * If we still don't know the variant, look at the first |
567 | * few packets to see what type of per-packet header they |
568 | * have. |
569 | * |
570 | * Default to PCAP, as that's probably what this is; |
571 | * libpcap_try_variants() will just give up if we're |
572 | * reading from a pipe. |
573 | */ |
574 | if (variant == PCAP_UNKNOWN) { |
575 | if (wth->ispipe) { |
576 | /* |
577 | * We can't do the heuristics. |
578 | * Just go with standard libpcap. |
579 | */ |
580 | libpcap->variant = PCAP; |
581 | } else { |
582 | /* |
583 | * Try the variants that use the standard |
584 | * pcap magic number. |
585 | */ |
586 | if (!libpcap_try_variants(wth, variants_standard, |
587 | N_VARIANTS_STANDARD(sizeof (variants_standard) / sizeof ((variants_standard)[0]) ), err, err_info)) { |
588 | /* |
589 | * File read error. |
590 | */ |
591 | return WTAP_OPEN_ERROR; |
592 | } |
593 | } |
594 | } else { |
595 | /* |
596 | * Use the variant we found. |
597 | */ |
598 | libpcap->variant = variant; |
599 | } |
600 | break; |
601 | |
602 | case PCAP_MODIFIED_MAGIC0xa1b2cd34: |
603 | /* |
604 | * Modified libpcap magic, from Alexey's later two |
605 | * patches. |
606 | * |
607 | * This might be one of two different flavors of |
608 | * pcap file, with different modified per-packet |
609 | * headers. |
610 | * |
611 | * If we're reading from a pipe, we don't have an |
612 | * obvious choice to use as a default. |
613 | */ |
614 | if (wth->ispipe) { |
615 | /* |
616 | * We can't do the heuristics. |
617 | * There's no obvious choice to use as a |
618 | * default, so just report an error. |
619 | */ |
620 | *err = WTAP_ERR_UNSUPPORTED-4; |
621 | *err_info = g_strdup("pcap: that type of pcap file can't be read from a pipe")g_strdup_inline ("pcap: that type of pcap file can't be read from a pipe" ); |
622 | return WTAP_OPEN_ERROR; |
623 | } else { |
624 | /* |
625 | * Try the variants that use the modified |
626 | * pcap magic number. |
627 | */ |
628 | if (!libpcap_try_variants(wth, variants_modified, |
629 | N_VARIANTS_MODIFIED(sizeof (variants_modified) / sizeof ((variants_modified)[0]) ), err, err_info)) { |
630 | /* |
631 | * File read error. |
632 | */ |
633 | return WTAP_OPEN_ERROR; |
634 | } |
635 | } |
636 | break; |
637 | |
638 | default: |
639 | /* |
640 | * None of these require heuristics to guess the |
641 | * variant; just use the variant we found. |
642 | */ |
643 | libpcap->variant = variant; |
644 | break; |
645 | } |
646 | |
647 | /* |
648 | * Set the file type and subtype, and handle some variants |
649 | * specially. |
650 | */ |
651 | switch (libpcap->variant) { |
652 | |
653 | case PCAP: |
654 | wth->file_type_subtype = pcap_file_type_subtype; |
655 | wth->file_tsprec = WTAP_TSPREC_USEC6; |
656 | break; |
657 | |
658 | case PCAP_NSEC: |
659 | wth->file_type_subtype = pcap_nsec_file_type_subtype; |
660 | wth->file_tsprec = WTAP_TSPREC_NSEC9; |
661 | break; |
662 | |
663 | case PCAP_SS990417: |
664 | wth->file_type_subtype = pcap_ss990417_file_type_subtype; |
665 | wth->file_tsprec = WTAP_TSPREC_USEC6; |
666 | break; |
667 | |
668 | case PCAP_SS990915: |
669 | wth->file_type_subtype = pcap_ss990915_file_type_subtype; |
670 | wth->file_tsprec = WTAP_TSPREC_USEC6; |
671 | break; |
672 | |
673 | case PCAP_SS991029: |
674 | wth->file_type_subtype = pcap_ss991029_file_type_subtype; |
675 | wth->file_tsprec = WTAP_TSPREC_USEC6; |
676 | break; |
677 | |
678 | case PCAP_AIX: |
679 | wth->file_type_subtype = pcap_aix_file_type_subtype; |
680 | wth->file_tsprec = WTAP_TSPREC_NSEC9; |
681 | break; |
682 | |
683 | case PCAP_NOKIA: |
684 | wth->file_type_subtype = pcap_nokia_file_type_subtype; |
685 | wth->file_tsprec = WTAP_TSPREC_USEC6; |
686 | /* |
687 | * We treat a DLT_ value of 13 specially - it appears |
688 | * that in Nokia libpcap format, it's some form of ATM |
689 | * with what I suspect is a pseudo-header (even though |
690 | * Nokia's IPSO is based on FreeBSD, which #defines |
691 | * DLT_SLIP_BSDOS as 13). |
692 | * |
693 | * Treat 13 as WTAP_ENCAP_ATM_PDUS, rather than as what |
694 | * we normally treat it. |
695 | */ |
696 | switch (hdr.network) { |
697 | |
698 | case 13: |
699 | wth->file_encap = WTAP_ENCAP_ATM_PDUS13; |
700 | break; |
701 | } |
702 | break; |
703 | |
704 | default: |
705 | ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "wiretap/libpcap.c", 705 , __func__, "assertion \"not reached\" failed"); |
706 | } |
707 | |
708 | if (wth->file_encap == WTAP_ENCAP_ERF98) { |
709 | /* Reset the ERF interface lookup table */ |
710 | libpcap->encap_priv = erf_priv_create(); |
711 | } else { |
712 | /* |
713 | * Add an IDB; we don't know how many interfaces were |
714 | * involved, so we just say one interface, about which |
715 | * we only know the link-layer type, snapshot length, |
716 | * and time stamp resolution. |
717 | */ |
718 | wtap_add_generated_idb(wth); |
719 | } |
720 | |
721 | return WTAP_OPEN_MINE; |
722 | } |
723 | |
724 | static bool_Bool libpcap_try_variants(wtap *wth, const pcap_variant_t *variants, |
725 | size_t n_variants, int *err, char **err_info) |
726 | { |
727 | libpcap_t *libpcap = (libpcap_t *)wth->priv; |
728 | #define MAX_FIGURES_OF_MERIT((((sizeof (variants_modified) / sizeof ((variants_modified)[ 0]))) > ((sizeof (variants_standard) / sizeof ((variants_standard )[0])))) ? ((sizeof (variants_modified) / sizeof ((variants_modified )[0]))) : ((sizeof (variants_standard) / sizeof ((variants_standard )[0])))) \ |
729 | MAX(N_VARIANTS_MODIFIED, N_VARIANTS_STANDARD)((((sizeof (variants_modified) / sizeof ((variants_modified)[ 0]))) > ((sizeof (variants_standard) / sizeof ((variants_standard )[0])))) ? ((sizeof (variants_modified) / sizeof ((variants_modified )[0]))) : ((sizeof (variants_standard) / sizeof ((variants_standard )[0])))) |
730 | int figures_of_merit[MAX_FIGURES_OF_MERIT((((sizeof (variants_modified) / sizeof ((variants_modified)[ 0]))) > ((sizeof (variants_standard) / sizeof ((variants_standard )[0])))) ? ((sizeof (variants_modified) / sizeof ((variants_modified )[0]))) : ((sizeof (variants_standard) / sizeof ((variants_standard )[0]))))]; |
731 | int best_variant; |
732 | int64_t first_packet_offset; |
733 | |
734 | first_packet_offset = file_tell(wth->fh); |
735 | for (size_t i = 0; i < n_variants; i++) { |
736 | figures_of_merit[i] = libpcap_try_variant(wth, variants[i], |
737 | err, err_info); |
738 | if (figures_of_merit[i] == -1) { |
739 | /* |
740 | * Well, we couldn't even read it. Give up. |
741 | */ |
742 | return false0; |
743 | } |
744 | if (figures_of_merit[i] == 0) { |
745 | /* |
746 | * This format doesn't have any issues. |
747 | * Put the seek pointer back, and finish, |
748 | * using that format as the subtype. |
749 | */ |
750 | if (file_seek(wth->fh, first_packet_offset, SEEK_SET0, |
751 | err) == -1) { |
752 | return false0; |
753 | } |
754 | libpcap->variant = variants[i]; |
755 | return true1; |
756 | } |
757 | |
758 | /* |
759 | * OK, we've recorded the figure of merit for this |
760 | * one; go back to the first packet and try the |
761 | * next one. |
762 | */ |
763 | if (file_seek(wth->fh, first_packet_offset, SEEK_SET0, |
764 | err) == -1) { |
765 | return false0; |
766 | } |
767 | } |
768 | |
769 | /* |
770 | * OK, none are perfect; let's see which one is least bad. |
771 | */ |
772 | best_variant = INT_MAX2147483647; |
773 | for (size_t i = 0; i < n_variants; i++) { |
774 | /* |
775 | * Is this subtype better than the last one we saw? |
776 | */ |
777 | if (figures_of_merit[i] < best_variant) { |
778 | /* |
779 | * Yes. Choose it until we find a better one. |
780 | */ |
781 | libpcap->variant = variants[i]; |
782 | best_variant = figures_of_merit[i]; |
783 | } |
784 | } |
785 | return true1; |
786 | } |
787 | |
788 | /* |
789 | * Maximum number of records to try to read. Must be >= 2. |
790 | */ |
791 | #define MAX_RECORDS_TO_TRY3 3 |
792 | |
793 | /* Try to read the first MAX_RECORDS_TO_TRY records of the capture file. */ |
794 | static int libpcap_try_variant(wtap *wth, pcap_variant_t variant, |
795 | int *err, char **err_info) |
796 | { |
797 | int figure_of_merit; |
798 | |
799 | figure_of_merit = 0; |
800 | |
801 | /* |
802 | * Attempt to read the MAX_RECORDS_TO_TRY records. |
803 | */ |
804 | for (unsigned int i = 0; i < MAX_RECORDS_TO_TRY3; i++) { |
805 | /* |
806 | * Attempt to read this record. |
807 | */ |
808 | try_record_ret_t try_record_ret; |
809 | |
810 | try_record_ret = libpcap_try_record(wth, variant, |
811 | &figure_of_merit, err, err_info); |
812 | |
813 | if (try_record_ret == TRY_REC_ERROR) { |
814 | /* |
815 | * Error; return the error indication. |
816 | */ |
817 | return -1; |
818 | } |
819 | if (try_record_ret == TRY_REC_EOF) { |
820 | /* |
821 | * Nothing more to read from this file. |
822 | */ |
823 | break; |
824 | } |
825 | } |
826 | |
827 | return figure_of_merit; |
828 | } |
829 | |
830 | /* Read the header of the next packet and, if that succeeds, read the |
831 | data of the next packet. |
832 | |
833 | Return -1 on an I/O error, 0 on success, or a positive number if the |
834 | header looks corrupt. The higher the positive number, the more things |
835 | are wrong with the header; this is used by the heuristics that try to |
836 | guess what type of file it is, with the type with the fewest problems |
837 | being chosen. */ |
838 | static try_record_ret_t libpcap_try_record(wtap *wth, pcap_variant_t variant, |
839 | int *figure_of_meritp, int *err, char **err_info) |
840 | { |
841 | libpcap_t *libpcap = (libpcap_t *)wth->priv; |
842 | struct pcaprec_hdr hdr; |
843 | /* Fields from PCAP_SS* modified headers */ |
844 | uint32_t ifindex; |
845 | uint16_t protocol; |
846 | uint8_t pkt_type; |
847 | uint32_t nokia_stuff; |
848 | bool_Bool incl_len_ok = true1; |
849 | |
850 | /* |
851 | * Read the header, one field at a time. |
852 | * First, do the fields that all pcap formats have - the |
853 | * time stamp, the captured length, and the original |
854 | * length. |
855 | */ |
856 | if (!wtap_read_bytes_or_eof(wth->fh, &hdr.ts_sec, 4, err, err_info)) { |
857 | if (*err == 0) { |
858 | /* |
859 | * EOF - assume the file is in this format. |
860 | * This means it doesn't have all the |
861 | * records we're trying to read. |
862 | */ |
863 | return TRY_REC_EOF; |
864 | } |
865 | if (*err == WTAP_ERR_SHORT_READ-12) { |
866 | /* |
867 | * Short read; this might be a corrupt |
868 | * file in this format or might not be |
869 | * in this format. Return a figure of |
870 | * merit of 1 more than what we've |
871 | * accumulated so far, to note the |
872 | * short read in addition to any other |
873 | * issues we've found. |
874 | */ |
875 | *figure_of_meritp += 1; |
876 | return TRY_REC_EOF; |
877 | } |
878 | /* Hard error. */ |
879 | return TRY_REC_ERROR; |
880 | } |
881 | |
882 | if (libpcap->byte_swapped) { |
883 | /* Byte-swap the field. */ |
884 | hdr.ts_sec = GUINT32_SWAP_LE_BE(hdr.ts_sec)(((guint32) ( (((guint32) (hdr.ts_sec) & (guint32) 0x000000ffU ) << 24) | (((guint32) (hdr.ts_sec) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (hdr.ts_sec) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (hdr.ts_sec) & (guint32) 0xff000000U ) >> 24)))); |
885 | } |
886 | |
887 | if (!wtap_read_bytes(wth->fh, &hdr.ts_usec, 4, err, err_info)) { |
888 | if (*err == WTAP_ERR_SHORT_READ-12) { |
889 | /* |
890 | * Short read; this might be a corrupt |
891 | * file in this format or might not be |
892 | * in this format. Return a figure of |
893 | * merit of 1 more than what we've |
894 | * accumulated so far, to note the |
895 | * short read in addition to any other |
896 | * issues we've found. |
897 | */ |
898 | *figure_of_meritp += 1; |
899 | return TRY_REC_EOF; |
900 | } |
901 | /* Hard error. */ |
902 | return TRY_REC_ERROR; |
903 | } |
904 | |
905 | if (libpcap->byte_swapped) { |
906 | /* Byte-swap the field. */ |
907 | hdr.ts_usec = GUINT32_SWAP_LE_BE(hdr.ts_usec)(((guint32) ( (((guint32) (hdr.ts_usec) & (guint32) 0x000000ffU ) << 24) | (((guint32) (hdr.ts_usec) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (hdr.ts_usec) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (hdr.ts_usec) & (guint32) 0xff000000U ) >> 24)))); |
908 | } |
909 | |
910 | /* |
911 | * The only file types for which we have to do variant |
912 | * determination by looking at packets have microsecond |
913 | * resolution; treat fractions-of-a-second values >= 1 000 000 |
914 | * as an indication that the header format might not be |
915 | * what we think it is. |
916 | */ |
917 | if (hdr.ts_usec >= 1000000) |
918 | *figure_of_meritp += 1; |
919 | |
920 | if (!wtap_read_bytes(wth->fh, &hdr.incl_len, 4, err, err_info)) { |
921 | if (*err == WTAP_ERR_SHORT_READ-12) { |
922 | /* |
923 | * Short read; this might be a corrupt |
924 | * file in this format or might not be |
925 | * in this format. Return a figure of |
926 | * merit of 1 more than what we've |
927 | * accumulated so far, to note the |
928 | * short read in addition to any other |
929 | * issues we've found. |
930 | */ |
931 | *figure_of_meritp += 1; |
932 | return TRY_REC_EOF; |
933 | } |
934 | /* Hard error. */ |
935 | return TRY_REC_ERROR; |
936 | } |
937 | |
938 | if (libpcap->byte_swapped) { |
939 | /* Byte-swap the field. */ |
940 | hdr.incl_len = GUINT32_SWAP_LE_BE(hdr.incl_len)(((guint32) ( (((guint32) (hdr.incl_len) & (guint32) 0x000000ffU ) << 24) | (((guint32) (hdr.incl_len) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (hdr.incl_len) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (hdr.incl_len) & (guint32) 0xff000000U ) >> 24)))); |
941 | } |
942 | |
943 | if (hdr.incl_len > wtap_max_snaplen_for_encap(wth->file_encap)) { |
944 | /* |
945 | * Probably either a corrupt capture file or a file |
946 | * of a type different from the one we're trying. |
947 | */ |
948 | incl_len_ok = false0; |
949 | *figure_of_meritp += 1; |
950 | } |
951 | |
952 | if (hdr.incl_len > wth->snapshot_length) { |
953 | /* |
954 | * This is not a fatal error, and packets that have one |
955 | * such packet probably have thousands. For discussion, |
956 | * see |
957 | * https://lists.wireshark.org/archives/wireshark-dev/201307/msg00076.html |
958 | * and related messages. |
959 | * |
960 | * The packet contents will be copied to a Buffer, which |
961 | * expands as necessary to hold the contents; we don't have |
962 | * to worry about fixed-length buffers allocated based on |
963 | * the original snapshot length. |
964 | * |
965 | * We just treat this as an indication that we might be |
966 | * trying the wrong file type here. |
967 | */ |
968 | *figure_of_meritp += 1; |
969 | } |
970 | |
971 | if (!wtap_read_bytes(wth->fh, &hdr.orig_len, 4, err, err_info)) { |
972 | if (*err == WTAP_ERR_SHORT_READ-12) { |
973 | /* |
974 | * Short read; this might be a corrupt |
975 | * file in this format or might not be |
976 | * in this format. Return a figure of |
977 | * merit of 1 more than what we've |
978 | * accumulated so far, to note the |
979 | * short read in addition to any other |
980 | * issues we've found. |
981 | */ |
982 | *figure_of_meritp += 1; |
983 | return TRY_REC_EOF; |
984 | } |
985 | /* Hard error. */ |
986 | return TRY_REC_ERROR; |
987 | } |
988 | |
989 | if (libpcap->byte_swapped) { |
990 | /* Byte-swap the field. */ |
991 | hdr.orig_len = GUINT32_SWAP_LE_BE(hdr.orig_len)(((guint32) ( (((guint32) (hdr.orig_len) & (guint32) 0x000000ffU ) << 24) | (((guint32) (hdr.orig_len) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (hdr.orig_len) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (hdr.orig_len) & (guint32) 0xff000000U ) >> 24)))); |
992 | } |
993 | |
994 | if (hdr.orig_len > 128*1024*1024) { |
995 | /* |
996 | * In theory I guess the on-the-wire packet size can be |
997 | * arbitrarily large, and it can certainly be larger than the |
998 | * maximum snapshot length which bounds the snapshot size, |
999 | * but any file claiming 128MB in a single packet is *probably* |
1000 | * corrupt, and treating them as such makes the heuristics |
1001 | * much more reliable. See, for example, |
1002 | * |
1003 | * https://gitlab.com/wireshark/wireshark/-/issues/9634 |
1004 | * |
1005 | * (128MB is an arbitrary size at this point, chosen to be |
1006 | * large enough for the largest D-Bus packet). |
1007 | */ |
1008 | *figure_of_meritp += 1; |
1009 | } |
1010 | |
1011 | if (hdr.incl_len > hdr.orig_len) { |
1012 | /* |
1013 | * Another hint that this might be the wrong file type. |
1014 | */ |
1015 | *figure_of_meritp += 1; |
1016 | } |
1017 | |
1018 | /* |
1019 | * Now check any additional fields that the variant we're |
1020 | * trying has. |
1021 | */ |
1022 | switch (variant) { |
1023 | |
1024 | case PCAP: |
1025 | case PCAP_AIX: |
1026 | case PCAP_NSEC: |
1027 | /* No more fields. */ |
1028 | break; |
1029 | |
1030 | case PCAP_SS990417: |
1031 | case PCAP_SS991029: |
1032 | case PCAP_SS990915: |
1033 | /* struct pcaprec_modified_hdr */ |
1034 | |
1035 | /* 32-bit interface index. */ |
1036 | if (!wtap_read_bytes(wth->fh, &ifindex, 4, err, err_info)) { |
1037 | if (*err == WTAP_ERR_SHORT_READ-12) { |
1038 | /* |
1039 | * Short read; this might be a corrupt |
1040 | * file in this format or might not be |
1041 | * in this format. Return a figure of |
1042 | * merit of 1 more than what we've |
1043 | * accumulated so far, to note the |
1044 | * short read in addition to any other |
1045 | * issues we've found. |
1046 | */ |
1047 | *figure_of_meritp += 1; |
1048 | return TRY_REC_EOF; |
1049 | } |
1050 | /* Hard error. */ |
1051 | return TRY_REC_ERROR; |
1052 | } |
1053 | |
1054 | if (libpcap->byte_swapped) { |
1055 | /* Byte-swap the field. */ |
1056 | ifindex = GUINT32_SWAP_LE_BE(ifindex)(((guint32) ( (((guint32) (ifindex) & (guint32) 0x000000ffU ) << 24) | (((guint32) (ifindex) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (ifindex) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (ifindex) & (guint32) 0xff000000U ) >> 24)))); |
1057 | } |
1058 | |
1059 | /* |
1060 | * Make sure it's not too large; those files date |
1061 | * from an era when a Linux box probably didn't |
1062 | * have more than 10000 interfaces, so check for |
1063 | * a value >= 10000. |
1064 | */ |
1065 | if (ifindex > 10000) |
1066 | *figure_of_meritp += 1; |
1067 | |
1068 | /* |
1069 | * 16-bit "Ethernet packet type", which is either an |
1070 | * Ethertype or one of the internal Linux ETH_P_ |
1071 | * values from linux/if_ether.h. |
1072 | */ |
1073 | if (!wtap_read_bytes(wth->fh, &protocol, 2, err, err_info)) { |
1074 | if (*err == WTAP_ERR_SHORT_READ-12) { |
1075 | /* |
1076 | * Short read; this might be a corrupt |
1077 | * file in this format or might not be |
1078 | * in this format. Return a figure of |
1079 | * merit of 1 more than what we've |
1080 | * accumulated so far, to note the |
1081 | * short read in addition to any other |
1082 | * issues we've found. |
1083 | */ |
1084 | *figure_of_meritp += 1; |
1085 | return TRY_REC_EOF; |
1086 | } |
1087 | /* Hard error. */ |
1088 | return TRY_REC_ERROR; |
1089 | } |
1090 | |
1091 | if (libpcap->byte_swapped) { |
1092 | /* Byte-swap the field. */ |
1093 | protocol = GUINT16_SWAP_LE_BE(protocol)(((guint16) ( (guint16) ((guint16) (protocol) >> 8) | ( guint16) ((guint16) (protocol) << 8)))); |
1094 | } |
1095 | |
1096 | /* |
1097 | * Valid values are: |
1098 | * |
1099 | * anything >= 0x0600 (normal Ethertype range) |
1100 | * 0x0060 (ETH_P_LOOP) |
1101 | * 0x0200 (ETH_P_ECHO) |
1102 | * 0x0400 (ETH_P_PUP) |
1103 | * 0x0000 (see in some such captures) |
1104 | * 0x0001 to 0x0017 ("Non DIX types") |
1105 | */ |
1106 | if (!(protocol >= 0x0600 || |
1107 | protocol == 0x0060 || |
1108 | protocol == 0x0200 || |
1109 | protocol == 0x0400 || |
1110 | protocol == 0x0000 || |
1111 | (protocol >= 0x0001 && protocol <= 0x0017))) |
1112 | *figure_of_meritp += 1; |
1113 | |
1114 | /* |
1115 | * 8-bit packet type - one of the Linux PACKET_ |
1116 | * types from linux/if_packet.h. The ones that |
1117 | * would appear in files from the era in which |
1118 | * these formats existed (the patches that |
1119 | * introduced them from are from 1999) are in |
1120 | * the range 0 through 4; anything else is treated |
1121 | * as a sign that this is unlikely to be in that |
1122 | * format. |
1123 | */ |
1124 | if (!wtap_read_bytes(wth->fh, &pkt_type, 1, err, err_info)) { |
1125 | if (*err == WTAP_ERR_SHORT_READ-12) { |
1126 | /* |
1127 | * Short read; this might be a corrupt |
1128 | * file in this format or might not be |
1129 | * in this format. Return a figure of |
1130 | * merit of 1 more than what we've |
1131 | * accumulated so far, to note the |
1132 | * short read in addition to any other |
1133 | * issues we've found. |
1134 | */ |
1135 | *figure_of_meritp += 1; |
1136 | return TRY_REC_EOF; |
1137 | } |
1138 | /* Hard error. */ |
1139 | return TRY_REC_ERROR; |
1140 | } |
1141 | |
1142 | if (pkt_type > 4) |
1143 | *figure_of_meritp += 1; |
1144 | |
1145 | if (variant == PCAP_SS990915) { |
1146 | /* |
1147 | * 2 8-bit values that are filled in only |
1148 | * if libpcap is built with SMP debugging, |
1149 | * fllowed by 3 bytes of 8-bit padding, |
1150 | * not guaranteed to be zero. |
1151 | * |
1152 | * Just skip them. |
1153 | */ |
1154 | if (!wtap_read_bytes(wth->fh, NULL((void*)0), 5, err, err_info)) { |
1155 | if (*err == WTAP_ERR_SHORT_READ-12) { |
1156 | /* |
1157 | * Short read; this might be a corrupt |
1158 | * file in this format or might not be |
1159 | * in this format. Return a figure of |
1160 | * merit of 1 more than what we've |
1161 | * accumulated so far, to note the |
1162 | * short read in addition to any other |
1163 | * issues we've found. |
1164 | */ |
1165 | *figure_of_meritp += 1; |
1166 | return TRY_REC_EOF; |
1167 | } |
1168 | /* Hard error. */ |
1169 | return TRY_REC_ERROR; |
1170 | } |
1171 | } else { |
1172 | /* |
1173 | * 8-bit structure padding, not guaranteed to be |
1174 | * zero. |
1175 | */ |
1176 | if (!wtap_read_bytes(wth->fh, NULL((void*)0), 1, err, err_info)) { |
1177 | if (*err == WTAP_ERR_SHORT_READ-12) { |
1178 | /* |
1179 | * Short read; this might be a corrupt |
1180 | * file in this format or might not be |
1181 | * in this format. Return a figure of |
1182 | * merit of 1 more than what we've |
1183 | * accumulated so far, to note the |
1184 | * short read in addition to any other |
1185 | * issues we've found. |
1186 | */ |
1187 | *figure_of_meritp += 1; |
1188 | return TRY_REC_EOF; |
1189 | } |
1190 | /* Hard error. */ |
1191 | return TRY_REC_ERROR; |
1192 | } |
1193 | } |
1194 | break; |
1195 | |
1196 | case PCAP_NOKIA: |
1197 | /* |
1198 | * pcaprec_nokia_hdr. |
1199 | * |
1200 | * 4 bytes of unknown stuff. |
1201 | */ |
1202 | if (!wtap_read_bytes(wth->fh, &nokia_stuff, 4, err, err_info)) { |
1203 | if (*err == WTAP_ERR_SHORT_READ-12) { |
1204 | /* |
1205 | * Short read; this might be a corrupt |
1206 | * file in this format or might not be |
1207 | * in this format. Return a figure of |
1208 | * merit of 1 more than what we've |
1209 | * accumulated so far, to note the |
1210 | * short read in addition to any other |
1211 | * issues we've found. |
1212 | */ |
1213 | *figure_of_meritp += 1; |
1214 | return TRY_REC_EOF; |
1215 | } |
1216 | /* Hard error. */ |
1217 | return TRY_REC_ERROR; |
1218 | } |
1219 | |
1220 | /* |
1221 | * Values we've seen in this field are of the form |
1222 | * |
1223 | * 0xXfbfYZ0W |
1224 | * |
1225 | * where X is either 9/1001 or b/1011, Y is either b/1011 |
1226 | * or d/1101, Z is either 6/0110 or 9/1001, and W is either |
1227 | * 1/0001 or 2/0010. |
1228 | * |
1229 | * Check for those values. |
1230 | */ |
1231 | #define NOKIA_STUFF_CONSTANT(ns)((ns) & 0x0FFF00F0) ((ns) & 0x0FFF00F0) |
1232 | #define NOKIA_STUFF_PART_1(ns)((ns) & 0xF0000000) ((ns) & 0xF0000000) |
1233 | #define NOKIA_STUFF_PART_2(ns)((ns) & 0x0000F000) ((ns) & 0x0000F000) |
1234 | #define NOKIA_STUFF_PART_3(ns)((ns) & 0x00000F00) ((ns) & 0x00000F00) |
1235 | #define NOKIA_STUFF_PART_4(ns)((ns) & 0x0000000F) ((ns) & 0x0000000F) |
1236 | if (!(NOKIA_STUFF_CONSTANT(nokia_stuff)((nokia_stuff) & 0x0FFF00F0) == 0x0fbf0000 && |
1237 | (NOKIA_STUFF_PART_1(nokia_stuff)((nokia_stuff) & 0xF0000000) == 0x90000000 || |
1238 | NOKIA_STUFF_PART_1(nokia_stuff)((nokia_stuff) & 0xF0000000) == 0xb0000000) && |
1239 | (NOKIA_STUFF_PART_2(nokia_stuff)((nokia_stuff) & 0x0000F000) == 0x0000b000 || |
1240 | NOKIA_STUFF_PART_2(nokia_stuff)((nokia_stuff) & 0x0000F000) == 0x0000d000) && |
1241 | (NOKIA_STUFF_PART_3(nokia_stuff)((nokia_stuff) & 0x00000F00) == 0x00000600 || |
1242 | NOKIA_STUFF_PART_3(nokia_stuff)((nokia_stuff) & 0x00000F00) == 0x00000900) && |
1243 | (NOKIA_STUFF_PART_4(nokia_stuff)((nokia_stuff) & 0x0000000F) == 0x00000001 || |
1244 | NOKIA_STUFF_PART_4(nokia_stuff)((nokia_stuff) & 0x0000000F) == 0x00000002))) |
1245 | *figure_of_meritp += 1; |
1246 | break; |
1247 | |
1248 | default: |
1249 | ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "wiretap/libpcap.c", 1249 , __func__, "assertion \"not reached\" failed"); |
1250 | } |
1251 | |
1252 | if (!incl_len_ok) { |
1253 | /* |
1254 | * Might be the wrong file type; stop trying, and give |
1255 | * this as the figure of merit for this file type. |
1256 | */ |
1257 | return TRY_REC_EOF; |
1258 | } |
1259 | |
1260 | /* |
1261 | * Now skip over the record's data, under the assumption that |
1262 | * the header is sane. |
1263 | */ |
1264 | if (!wtap_read_bytes(wth->fh, NULL((void*)0), hdr.incl_len, err, err_info)) { |
1265 | if (*err == WTAP_ERR_SHORT_READ-12) { |
1266 | /* |
1267 | * Short read; this might be a corrupt |
1268 | * file in this format or might not be |
1269 | * in this format. Return a figure of |
1270 | * merit of 1 more than what we've |
1271 | * accumulated so far, to note the |
1272 | * short read in addition to any other |
1273 | * issues we've found. |
1274 | */ |
1275 | *figure_of_meritp += 1; |
1276 | return TRY_REC_EOF; |
1277 | } |
1278 | /* Hard error. */ |
1279 | return TRY_REC_ERROR; |
1280 | } |
1281 | |
1282 | return TRY_REC_KEEP_READING; |
1283 | } |
1284 | |
1285 | /* Read the next packet */ |
1286 | static bool_Bool libpcap_read(wtap *wth, wtap_rec *rec, |
1287 | int *err, char **err_info, int64_t *data_offset) |
1288 | { |
1289 | *data_offset = file_tell(wth->fh); |
1290 | |
1291 | return libpcap_read_packet(wth, wth->fh, rec, err, err_info); |
1292 | } |
1293 | |
1294 | static bool_Bool |
1295 | libpcap_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec, |
1296 | int *err, char **err_info) |
1297 | { |
1298 | if (file_seek(wth->random_fh, seek_off, SEEK_SET0, err) == -1) |
1299 | return false0; |
1300 | |
1301 | if (!libpcap_read_packet(wth, wth->random_fh, rec, err, err_info)) { |
1302 | if (*err == 0) |
1303 | *err = WTAP_ERR_SHORT_READ-12; |
1304 | return false0; |
1305 | } |
1306 | return true1; |
1307 | } |
1308 | |
1309 | static bool_Bool |
1310 | libpcap_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec, |
1311 | int *err, char **err_info) |
1312 | { |
1313 | struct pcaprec_ss990915_hdr hdr; |
1314 | unsigned packet_size; |
1315 | unsigned orig_size; |
1316 | int phdr_len; |
1317 | libpcap_t *libpcap = (libpcap_t *)wth->priv; |
1318 | bool_Bool is_nokia; |
1319 | |
1320 | if (!libpcap_read_header(wth, fh, err, err_info, &hdr)) |
1321 | return false0; |
1322 | |
1323 | if (hdr.hdr.incl_len > wtap_max_snaplen_for_encap(wth->file_encap)) { |
1324 | /* |
1325 | * Probably a corrupt capture file; return an error, |
1326 | * so that our caller doesn't blow up trying to allocate |
1327 | * space for an immensely-large packet. |
1328 | */ |
1329 | *err = WTAP_ERR_BAD_FILE-13; |
1330 | if (err_info != NULL((void*)0)) { |
1331 | *err_info = ws_strdup_printf("pcap: File has %u-byte packet, bigger than maximum of %u",wmem_strdup_printf(((void*)0), "pcap: File has %u-byte packet, bigger than maximum of %u" , hdr.hdr.incl_len, wtap_max_snaplen_for_encap(wth->file_encap )) |
1332 | hdr.hdr.incl_len,wmem_strdup_printf(((void*)0), "pcap: File has %u-byte packet, bigger than maximum of %u" , hdr.hdr.incl_len, wtap_max_snaplen_for_encap(wth->file_encap )) |
1333 | wtap_max_snaplen_for_encap(wth->file_encap))wmem_strdup_printf(((void*)0), "pcap: File has %u-byte packet, bigger than maximum of %u" , hdr.hdr.incl_len, wtap_max_snaplen_for_encap(wth->file_encap )); |
1334 | } |
1335 | return false0; |
1336 | } |
1337 | |
1338 | packet_size = hdr.hdr.incl_len; |
1339 | orig_size = hdr.hdr.orig_len; |
1340 | |
1341 | /* |
1342 | * AIX appears to put 3 bytes of padding in front of FDDI |
1343 | * frames; strip that crap off. |
1344 | */ |
1345 | if (libpcap->variant == PCAP_AIX && |
1346 | (wth->file_encap == WTAP_ENCAP_FDDI5 || |
1347 | wth->file_encap == WTAP_ENCAP_FDDI_BITSWAPPED6)) { |
1348 | /* |
1349 | * The packet size is really a record size and includes |
1350 | * the padding. |
1351 | */ |
1352 | packet_size -= 3; |
1353 | orig_size -= 3; |
1354 | |
1355 | /* |
1356 | * Skip the padding. |
1357 | */ |
1358 | if (!wtap_read_bytes(fh, NULL((void*)0), 3, err, err_info)) |
1359 | return false0; |
1360 | } |
1361 | |
1362 | is_nokia = (libpcap->variant == PCAP_NOKIA); |
1363 | phdr_len = pcap_process_pseudo_header(fh, is_nokia, |
1364 | wth->file_encap, packet_size, rec, err, err_info); |
1365 | if (phdr_len < 0) |
1366 | return false0; /* error */ |
1367 | |
1368 | /* |
1369 | * Don't count any pseudo-header as part of the packet. |
1370 | */ |
1371 | orig_size -= phdr_len; |
1372 | packet_size -= phdr_len; |
1373 | |
1374 | wtap_setup_packet_rec(rec, wth->file_encap); |
1375 | rec->block = wtap_block_create(WTAP_BLOCK_PACKET); |
1376 | rec->presence_flags = WTAP_HAS_TS0x00000001|WTAP_HAS_CAP_LEN0x00000002; |
1377 | |
1378 | /* Update the timestamp, if not already done */ |
1379 | if (wth->file_encap != WTAP_ENCAP_ERF98) { |
1380 | rec->ts.secs = hdr.hdr.ts_sec; |
1381 | if (libpcap->variant == PCAP_NSEC || |
1382 | libpcap->variant == PCAP_AIX) |
1383 | rec->ts.nsecs = hdr.hdr.ts_usec; |
1384 | else |
1385 | rec->ts.nsecs = hdr.hdr.ts_usec * 1000; |
1386 | } else { |
1387 | int interface_id; |
1388 | /* Set interface ID for ERF format */ |
1389 | rec->presence_flags |= WTAP_HAS_INTERFACE_ID0x00000004; |
1390 | if ((interface_id = erf_populate_interface_from_header((erf_t*) libpcap->encap_priv, wth, &rec->rec_header.packet_header.pseudo_header, err, err_info)) < 0) |
1391 | return false0; |
1392 | |
1393 | rec->rec_header.packet_header.interface_id = (unsigned) interface_id; |
1394 | } |
1395 | rec->rec_header.packet_header.caplen = packet_size; |
1396 | rec->rec_header.packet_header.len = orig_size; |
1397 | |
1398 | /* |
1399 | * Read the packet data. |
1400 | */ |
1401 | if (!wtap_read_bytes_buffer(fh, &rec->data, packet_size, err, err_info)) |
1402 | return false0; /* failed */ |
1403 | |
1404 | pcap_read_post_process(is_nokia, wth->file_encap, rec, |
1405 | libpcap->byte_swapped, libpcap->fcs_len); |
1406 | return true1; |
1407 | } |
1408 | |
1409 | /* Read the header of the next packet. |
1410 | |
1411 | Return false on an error, true on success. */ |
1412 | static bool_Bool |
1413 | libpcap_read_header(wtap *wth, FILE_T fh, int *err, char **err_info, |
1414 | struct pcaprec_ss990915_hdr *hdr) |
1415 | { |
1416 | int bytes_to_read; |
1417 | uint32_t temp; |
1418 | libpcap_t *libpcap = (libpcap_t *)wth->priv; |
1419 | |
1420 | switch (libpcap->variant) { |
1421 | |
1422 | case PCAP: |
1423 | case PCAP_AIX: |
1424 | case PCAP_NSEC: |
1425 | bytes_to_read = sizeof (struct pcaprec_hdr); |
1426 | break; |
1427 | |
1428 | case PCAP_SS990417: |
1429 | case PCAP_SS991029: |
1430 | bytes_to_read = sizeof (struct pcaprec_modified_hdr); |
1431 | break; |
1432 | |
1433 | case PCAP_SS990915: |
1434 | bytes_to_read = sizeof (struct pcaprec_ss990915_hdr); |
1435 | break; |
1436 | |
1437 | case PCAP_NOKIA: |
1438 | bytes_to_read = sizeof (struct pcaprec_nokia_hdr); |
1439 | break; |
1440 | |
1441 | default: |
1442 | bytes_to_read = 0; |
Value stored to 'bytes_to_read' is never read | |
1443 | ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "wiretap/libpcap.c", 1443 , __func__, "assertion \"not reached\" failed"); |
1444 | } |
1445 | if (!wtap_read_bytes_or_eof(fh, hdr, bytes_to_read, err, err_info)) |
1446 | return false0; |
1447 | |
1448 | if (libpcap->byte_swapped) { |
1449 | /* Byte-swap the record header fields. */ |
1450 | hdr->hdr.ts_sec = GUINT32_SWAP_LE_BE(hdr->hdr.ts_sec)(((guint32) ( (((guint32) (hdr->hdr.ts_sec) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (hdr->hdr.ts_sec ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (hdr ->hdr.ts_sec) & (guint32) 0x00ff0000U) >> 8) | ( ((guint32) (hdr->hdr.ts_sec) & (guint32) 0xff000000U) >> 24)))); |
1451 | hdr->hdr.ts_usec = GUINT32_SWAP_LE_BE(hdr->hdr.ts_usec)(((guint32) ( (((guint32) (hdr->hdr.ts_usec) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (hdr->hdr.ts_usec ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (hdr ->hdr.ts_usec) & (guint32) 0x00ff0000U) >> 8) | ( ((guint32) (hdr->hdr.ts_usec) & (guint32) 0xff000000U) >> 24)))); |
1452 | hdr->hdr.incl_len = GUINT32_SWAP_LE_BE(hdr->hdr.incl_len)(((guint32) ( (((guint32) (hdr->hdr.incl_len) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (hdr->hdr.incl_len ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (hdr ->hdr.incl_len) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (hdr->hdr.incl_len) & (guint32) 0xff000000U ) >> 24)))); |
1453 | hdr->hdr.orig_len = GUINT32_SWAP_LE_BE(hdr->hdr.orig_len)(((guint32) ( (((guint32) (hdr->hdr.orig_len) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (hdr->hdr.orig_len ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (hdr ->hdr.orig_len) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (hdr->hdr.orig_len) & (guint32) 0xff000000U ) >> 24)))); |
1454 | } |
1455 | |
1456 | /* Swap the "incl_len" and "orig_len" fields, if necessary. */ |
1457 | switch (libpcap->lengths_swapped) { |
1458 | |
1459 | case NOT_SWAPPED: |
1460 | break; |
1461 | |
1462 | case MAYBE_SWAPPED: |
1463 | if (hdr->hdr.incl_len <= hdr->hdr.orig_len) { |
1464 | /* |
1465 | * The captured length is <= the actual length, |
1466 | * so presumably they weren't swapped. |
1467 | */ |
1468 | break; |
1469 | } |
1470 | /* FALLTHROUGH */ |
1471 | |
1472 | case SWAPPED: |
1473 | temp = hdr->hdr.orig_len; |
1474 | hdr->hdr.orig_len = hdr->hdr.incl_len; |
1475 | hdr->hdr.incl_len = temp; |
1476 | break; |
1477 | } |
1478 | |
1479 | return true1; |
1480 | } |
1481 | |
1482 | /* Returns 0 if we could write the specified encapsulation type, |
1483 | an error indication otherwise. */ |
1484 | static int libpcap_dump_can_write_encap(int encap) |
1485 | { |
1486 | /* Per-packet encapsulations aren't supported. */ |
1487 | if (encap == WTAP_ENCAP_PER_PACKET-1) |
1488 | return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED-9; |
1489 | |
1490 | if (wtap_wtap_encap_to_pcap_encap(encap) == -1) |
1491 | return WTAP_ERR_UNWRITABLE_ENCAP-8; |
1492 | |
1493 | return 0; |
1494 | } |
1495 | |
1496 | static bool_Bool libpcap_dump_write_file_header(wtap_dumper *wdh, uint32_t magic, |
1497 | int *err) |
1498 | { |
1499 | struct pcap_hdr file_hdr; |
1500 | |
1501 | if (!wtap_dump_file_write(wdh, &magic, sizeof magic, err)) |
1502 | return false0; |
1503 | |
1504 | /* current "libpcap" format is 2.4 */ |
1505 | file_hdr.version_major = 2; |
1506 | file_hdr.version_minor = 4; |
1507 | file_hdr.thiszone = 0; /* XXX - current offset? */ |
1508 | file_hdr.sigfigs = 0; /* unknown, but also apparently unused */ |
1509 | /* |
1510 | * Tcpdump cannot handle capture files with a snapshot length of 0, |
1511 | * as BPF filters return either 0 if they fail or the snapshot length |
1512 | * if they succeed, and a snapshot length of 0 means success is |
1513 | * indistinguishable from failure and the filter expression would |
1514 | * reject all packets. |
1515 | * |
1516 | * A snapshot length of 0, inside Wiretap, means "snapshot length |
1517 | * unknown"; if the snapshot length supplied to us is 0, we make |
1518 | * the snapshot length in the header file the maximum for the |
1519 | * link-layer type we'll be writing. |
1520 | */ |
1521 | file_hdr.snaplen = (wdh->snaplen != 0) ? (unsigned)wdh->snaplen : |
1522 | wtap_max_snaplen_for_encap(wdh->file_encap); |
1523 | file_hdr.network = wtap_wtap_encap_to_pcap_encap(wdh->file_encap); |
1524 | if (!wtap_dump_file_write(wdh, &file_hdr, sizeof file_hdr, err)) |
1525 | return false0; |
1526 | |
1527 | return true1; |
1528 | } |
1529 | |
1530 | /* Good old fashioned pcap. |
1531 | Returns true on success, false on failure; sets "*err" to an error code on |
1532 | failure */ |
1533 | static bool_Bool |
1534 | libpcap_dump_open_pcap(wtap_dumper *wdh, int *err, char **err_info _U___attribute__((unused))) |
1535 | { |
1536 | /* This is a libpcap file */ |
1537 | wdh->subtype_write = libpcap_dump_pcap; |
1538 | |
1539 | /* Write the file header. */ |
1540 | return libpcap_dump_write_file_header(wdh, PCAP_MAGIC0xa1b2c3d4, err); |
1541 | } |
1542 | |
1543 | /* Like classic pcap, but with nanosecond resolution. |
1544 | Returns true on success, false on failure; sets "*err" to an error code on |
1545 | failure */ |
1546 | static bool_Bool |
1547 | libpcap_dump_open_pcap_nsec(wtap_dumper *wdh, int *err, char **err_info _U___attribute__((unused))) |
1548 | { |
1549 | /* This is a nanosecond-resolution libpcap file */ |
1550 | wdh->subtype_write = libpcap_dump_pcap_nsec; |
1551 | |
1552 | /* Write the file header. */ |
1553 | return libpcap_dump_write_file_header(wdh, PCAP_NSEC_MAGIC0xa1b23c4d, err); |
1554 | } |
1555 | |
1556 | /* Modified, but with the old magic, sigh. |
1557 | Returns true on success, false on failure; sets "*err" to an error code on |
1558 | failure */ |
1559 | static bool_Bool |
1560 | libpcap_dump_open_pcap_ss990417(wtap_dumper *wdh, int *err, |
1561 | char **err_info _U___attribute__((unused))) |
1562 | { |
1563 | /* This is a modified-by-patch-SS990417 libpcap file */ |
1564 | wdh->subtype_write = libpcap_dump_pcap_ss990417; |
1565 | |
1566 | /* Write the file header. */ |
1567 | return libpcap_dump_write_file_header(wdh, PCAP_MAGIC0xa1b2c3d4, err); |
1568 | } |
1569 | |
1570 | /* New magic, extra crap. |
1571 | Returns true on success, false on failure; sets "*err" to an error code on |
1572 | failure */ |
1573 | static bool_Bool |
1574 | libpcap_dump_open_pcap_ss990915(wtap_dumper *wdh, int *err, |
1575 | char **err_info _U___attribute__((unused))) |
1576 | { |
1577 | /* This is a modified-by-patch-SS990915 libpcap file */ |
1578 | wdh->subtype_write = libpcap_dump_pcap_ss990915; |
1579 | |
1580 | /* Write the file header. */ |
1581 | return libpcap_dump_write_file_header(wdh, PCAP_MODIFIED_MAGIC0xa1b2cd34, err); |
1582 | } |
1583 | |
1584 | /* Same magic as SS990915, *different* extra crap, sigh. |
1585 | Returns true on success, false on failure; sets "*err" to an error code on |
1586 | failure */ |
1587 | static bool_Bool |
1588 | libpcap_dump_open_pcap_ss991029(wtap_dumper *wdh, int *err, |
1589 | char **err_info _U___attribute__((unused))) |
1590 | { |
1591 | /* This is a modified-by-patch-SS991029 libpcap file */ |
1592 | wdh->subtype_write = libpcap_dump_pcap_ss991029; |
1593 | |
1594 | /* Write the file header. */ |
1595 | return libpcap_dump_write_file_header(wdh, PCAP_MODIFIED_MAGIC0xa1b2cd34, err); |
1596 | } |
1597 | |
1598 | static void libpcap_close(wtap *wth) |
1599 | { |
1600 | libpcap_t *libpcap = (libpcap_t *)wth->priv; |
1601 | |
1602 | if (libpcap->encap_priv) { |
1603 | switch (wth->file_encap) { |
1604 | |
1605 | case WTAP_ENCAP_ERF98: |
1606 | erf_priv_free((erf_t*) libpcap->encap_priv); |
1607 | break; |
1608 | |
1609 | default: |
1610 | g_free(libpcap->encap_priv); |
1611 | break; |
1612 | } |
1613 | } |
1614 | } |
1615 | |
1616 | /* Nokia libpcap of some sort. |
1617 | Returns true on success, false on failure; sets "*err" to an error code on |
1618 | failure */ |
1619 | static bool_Bool |
1620 | libpcap_dump_open_pcap_nokia(wtap_dumper *wdh, int *err, char **err_info _U___attribute__((unused))) |
1621 | { |
1622 | /* This is a Nokia libpcap file */ |
1623 | wdh->subtype_write = libpcap_dump_pcap_nokia; |
1624 | |
1625 | /* Write the file header. */ |
1626 | return libpcap_dump_write_file_header(wdh, PCAP_MAGIC0xa1b2c3d4, err); |
1627 | } |
1628 | |
1629 | static bool_Bool |
1630 | libpcap_dump_write_packet(wtap_dumper *wdh, const wtap_rec *rec, |
1631 | struct pcaprec_hdr *hdr, size_t hdr_size, int *err, char **err_info) |
1632 | { |
1633 | const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header; |
1634 | unsigned phdrsize; |
1635 | |
1636 | phdrsize = pcap_get_phdr_size(wdh->file_encap, pseudo_header); |
1637 | |
1638 | /* We can only write packet records. */ |
1639 | if (rec->rec_type != REC_TYPE_PACKET0) { |
1640 | *err = WTAP_ERR_UNWRITABLE_REC_TYPE-24; |
1641 | *err_info = wtap_unwritable_rec_type_err_string(rec); |
1642 | return false0; |
1643 | } |
1644 | |
1645 | /* |
1646 | * Make sure this packet doesn't have a link-layer type that |
1647 | * differs from the one for the file. |
1648 | */ |
1649 | if (wdh->file_encap != rec->rec_header.packet_header.pkt_encap) { |
1650 | *err = WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED-9; |
1651 | return false0; |
1652 | } |
1653 | |
1654 | /* |
1655 | * Don't write anything we're not willing to read. |
1656 | * (The cast is to prevent an overflow.) |
1657 | */ |
1658 | if ((uint64_t)rec->rec_header.packet_header.caplen + phdrsize > wtap_max_snaplen_for_encap(wdh->file_encap)) { |
1659 | *err = WTAP_ERR_PACKET_TOO_LARGE-22; |
1660 | return false0; |
1661 | } |
1662 | |
1663 | hdr->incl_len = rec->rec_header.packet_header.caplen + phdrsize; |
1664 | hdr->orig_len = rec->rec_header.packet_header.len + phdrsize; |
1665 | |
1666 | if (!wtap_dump_file_write(wdh, hdr, hdr_size, err)) |
1667 | return false0; |
1668 | |
1669 | if (!pcap_write_phdr(wdh, wdh->file_encap, pseudo_header, err)) |
1670 | return false0; |
1671 | |
1672 | if (!wtap_dump_file_write(wdh, ws_buffer_start_ptr(&rec->data), |
1673 | rec->rec_header.packet_header.caplen, err)) |
1674 | return false0; |
1675 | return true1; |
1676 | } |
1677 | |
1678 | /* Good old fashioned pcap. |
1679 | Write a record for a packet to a dump file. |
1680 | Returns true on success, false on failure. */ |
1681 | static bool_Bool |
1682 | libpcap_dump_pcap(wtap_dumper *wdh, const wtap_rec *rec, |
1683 | int *err, char **err_info) |
1684 | { |
1685 | struct pcaprec_hdr rec_hdr; |
1686 | |
1687 | /* |
1688 | * Some code that reads libpcap files may handle time |
1689 | * stamps as unsigned, but most of it probably handles |
1690 | * them as signed. |
1691 | */ |
1692 | if (rec->ts.secs < 0 || rec->ts.secs > INT32_MAX(2147483647)) { |
1693 | *err = WTAP_ERR_TIME_STAMP_NOT_SUPPORTED-27; |
1694 | return false0; |
1695 | } |
1696 | rec_hdr.ts_sec = (uint32_t) rec->ts.secs; |
1697 | rec_hdr.ts_usec = rec->ts.nsecs / 1000; |
1698 | return libpcap_dump_write_packet(wdh, rec, &rec_hdr, sizeof rec_hdr, |
1699 | err, err_info); |
1700 | } |
1701 | |
1702 | /* Like classic pcap, but with nanosecond resolution. |
1703 | Write a record for a packet to a dump file. |
1704 | Returns true on success, false on failure. */ |
1705 | static bool_Bool |
1706 | libpcap_dump_pcap_nsec(wtap_dumper *wdh, const wtap_rec *rec, |
1707 | int *err, char **err_info) |
1708 | { |
1709 | struct pcaprec_hdr rec_hdr; |
1710 | |
1711 | /* |
1712 | * Some code that reads libpcap files may handle time |
1713 | * stamps as unsigned, but most of it probably handles |
1714 | * them as signed. |
1715 | */ |
1716 | if (rec->ts.secs < 0 || rec->ts.secs > INT32_MAX(2147483647)) { |
1717 | *err = WTAP_ERR_TIME_STAMP_NOT_SUPPORTED-27; |
1718 | return false0; |
1719 | } |
1720 | rec_hdr.ts_sec = (uint32_t) rec->ts.secs; |
1721 | rec_hdr.ts_usec = rec->ts.nsecs; |
1722 | return libpcap_dump_write_packet(wdh, rec, &rec_hdr, sizeof rec_hdr, |
1723 | err, err_info); |
1724 | } |
1725 | |
1726 | /* Modified, but with the old magic, sigh. |
1727 | Write a record for a packet to a dump file. |
1728 | Returns true on success, false on failure. */ |
1729 | static bool_Bool |
1730 | libpcap_dump_pcap_ss990417(wtap_dumper *wdh, const wtap_rec *rec, |
1731 | int *err, char **err_info) |
1732 | { |
1733 | struct pcaprec_modified_hdr rec_hdr; |
1734 | |
1735 | /* |
1736 | * Some code that reads libpcap files may handle time |
1737 | * stamps as unsigned, but most of it probably handles |
1738 | * them as signed. |
1739 | */ |
1740 | if (rec->ts.secs < 0 || rec->ts.secs > INT32_MAX(2147483647)) { |
1741 | *err = WTAP_ERR_TIME_STAMP_NOT_SUPPORTED-27; |
1742 | return false0; |
1743 | } |
1744 | rec_hdr.hdr.ts_sec = (uint32_t) rec->ts.secs; |
1745 | rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000; |
1746 | /* XXX - what should we supply here? |
1747 | |
1748 | Alexey's "libpcap" looks up the interface in the system's |
1749 | interface list if "ifindex" is non-zero, and prints |
1750 | the interface name. It ignores "protocol", and uses |
1751 | "pkt_type" to tag the packet as "host", "broadcast", |
1752 | "multicast", "other host", "outgoing", or "none of the |
1753 | above", but that's it. |
1754 | |
1755 | If the capture we're writing isn't a modified or |
1756 | RH 6.1 capture, we'd have to do some work to |
1757 | generate the packet type and interface index - and |
1758 | we can't generate the interface index unless we |
1759 | just did the capture ourselves in any case. |
1760 | |
1761 | I'm inclined to continue to punt; systems other than |
1762 | those with the older patch can read standard "libpcap" |
1763 | files, and systems with the older patch, e.g. RH 6.1, |
1764 | will just have to live with this. */ |
1765 | rec_hdr.ifindex = 0; |
1766 | rec_hdr.protocol = 0; |
1767 | rec_hdr.pkt_type = 0; |
1768 | return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr, |
1769 | err, err_info); |
1770 | } |
1771 | |
1772 | /* New magic, extra crap. |
1773 | Write a record for a packet to a dump file. |
1774 | Returns true on success, false on failure. */ |
1775 | static bool_Bool |
1776 | libpcap_dump_pcap_ss990915(wtap_dumper *wdh, const wtap_rec *rec, |
1777 | int *err, char **err_info) |
1778 | { |
1779 | struct pcaprec_ss990915_hdr rec_hdr; |
1780 | |
1781 | /* |
1782 | * Some code that reads libpcap files may handle time |
1783 | * stamps as unsigned, but most of it probably handles |
1784 | * them as signed. |
1785 | */ |
1786 | if (rec->ts.secs < 0 || rec->ts.secs > INT32_MAX(2147483647)) { |
1787 | *err = WTAP_ERR_TIME_STAMP_NOT_SUPPORTED-27; |
1788 | return false0; |
1789 | } |
1790 | rec_hdr.hdr.ts_sec = (uint32_t) rec->ts.secs; |
1791 | rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000; |
1792 | rec_hdr.ifindex = 0; |
1793 | rec_hdr.protocol = 0; |
1794 | rec_hdr.pkt_type = 0; |
1795 | rec_hdr.cpu1 = 0; |
1796 | rec_hdr.cpu2 = 0; |
1797 | return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr, |
1798 | err, err_info); |
1799 | } |
1800 | |
1801 | /* Same magic as SS990915, *different* extra crap, sigh. |
1802 | Write a record for a packet to a dump file. |
1803 | Returns true on success, false on failure. */ |
1804 | static bool_Bool |
1805 | libpcap_dump_pcap_ss991029(wtap_dumper *wdh, const wtap_rec *rec, |
1806 | int *err, char **err_info) |
1807 | { |
1808 | struct pcaprec_modified_hdr rec_hdr; |
1809 | |
1810 | /* |
1811 | * Some code that reads libpcap files may handle time |
1812 | * stamps as unsigned, but most of it probably handles |
1813 | * them as signed. |
1814 | */ |
1815 | if (rec->ts.secs < 0 || rec->ts.secs > INT32_MAX(2147483647)) { |
1816 | *err = WTAP_ERR_TIME_STAMP_NOT_SUPPORTED-27; |
1817 | return false0; |
1818 | } |
1819 | rec_hdr.hdr.ts_sec = (uint32_t) rec->ts.secs; |
1820 | rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000; |
1821 | /* XXX - what should we supply here? |
1822 | |
1823 | Alexey's "libpcap" looks up the interface in the system's |
1824 | interface list if "ifindex" is non-zero, and prints |
1825 | the interface name. It ignores "protocol", and uses |
1826 | "pkt_type" to tag the packet as "host", "broadcast", |
1827 | "multicast", "other host", "outgoing", or "none of the |
1828 | above", but that's it. |
1829 | |
1830 | If the capture we're writing isn't a modified or |
1831 | RH 6.1 capture, we'd have to do some work to |
1832 | generate the packet type and interface index - and |
1833 | we can't generate the interface index unless we |
1834 | just did the capture ourselves in any case. |
1835 | |
1836 | I'm inclined to continue to punt; systems other than |
1837 | those with the older patch can read standard "libpcap" |
1838 | files, and systems with the older patch, e.g. RH 6.1, |
1839 | will just have to live with this. */ |
1840 | rec_hdr.ifindex = 0; |
1841 | rec_hdr.protocol = 0; |
1842 | rec_hdr.pkt_type = 0; |
1843 | return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr, |
1844 | err, err_info); |
1845 | } |
1846 | |
1847 | /* Nokia libpcap of some sort. |
1848 | Write a record for a packet to a dump file. |
1849 | Returns true on success, false on failure. */ |
1850 | static bool_Bool |
1851 | libpcap_dump_pcap_nokia(wtap_dumper *wdh, const wtap_rec *rec, |
1852 | int *err, char **err_info) |
1853 | { |
1854 | struct pcaprec_nokia_hdr rec_hdr; |
1855 | const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header; |
1856 | |
1857 | /* |
1858 | * Some code that reads libpcap files may handle time |
1859 | * stamps as unsigned, but most of it probably handles |
1860 | * them as signed. |
1861 | */ |
1862 | if (rec->ts.secs < 0 || rec->ts.secs > INT32_MAX(2147483647)) { |
1863 | *err = WTAP_ERR_TIME_STAMP_NOT_SUPPORTED-27; |
1864 | return false0; |
1865 | } |
1866 | rec_hdr.hdr.ts_sec = (uint32_t) rec->ts.secs; |
1867 | rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000; |
1868 | /* restore the "mysterious stuff" that came with the packet */ |
1869 | memcpy(rec_hdr.stuff, pseudo_header->nokia.stuff, 4); |
1870 | return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr, |
1871 | err, err_info); |
1872 | } |
1873 | |
1874 | static const struct supported_block_type pcap_blocks_supported[] = { |
1875 | /* |
1876 | * We support packet blocks, with no comments or other options. |
1877 | */ |
1878 | { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED0, ((void*)0) } |
1879 | }; |
1880 | |
1881 | static const struct file_type_subtype_info pcap_info = { |
1882 | /* Gianluca Varenni suggests that we add "deprecated" to the description. */ |
1883 | "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp", |
1884 | false0, BLOCKS_SUPPORTED(pcap_blocks_supported)(sizeof (pcap_blocks_supported) / sizeof (pcap_blocks_supported )[0]), pcap_blocks_supported, |
1885 | libpcap_dump_can_write_encap, libpcap_dump_open_pcap, NULL((void*)0) |
1886 | }; |
1887 | |
1888 | static const struct file_type_subtype_info pcap_nsec_info = { |
1889 | "Wireshark/tcpdump/... - nanosecond pcap", "nsecpcap", "pcap", "cap;dmp", |
1890 | false0, BLOCKS_SUPPORTED(pcap_blocks_supported)(sizeof (pcap_blocks_supported) / sizeof (pcap_blocks_supported )[0]), pcap_blocks_supported, |
1891 | libpcap_dump_can_write_encap, libpcap_dump_open_pcap_nsec, NULL((void*)0) |
1892 | }; |
1893 | |
1894 | static const struct file_type_subtype_info pcap_aix_info = { |
1895 | "AIX tcpdump - pcap", "aixpcap", "pcap", "cap;dmp", |
1896 | false0, BLOCKS_SUPPORTED(pcap_blocks_supported)(sizeof (pcap_blocks_supported) / sizeof (pcap_blocks_supported )[0]), pcap_blocks_supported, |
1897 | NULL((void*)0), NULL((void*)0), NULL((void*)0) |
1898 | }; |
1899 | |
1900 | static const struct file_type_subtype_info pcap_ss990417_info = { |
1901 | "RedHat 6.1 tcpdump - pcap", "rh6_1pcap", "pcap", "cap;dmp", |
1902 | false0, BLOCKS_SUPPORTED(pcap_blocks_supported)(sizeof (pcap_blocks_supported) / sizeof (pcap_blocks_supported )[0]), pcap_blocks_supported, |
1903 | libpcap_dump_can_write_encap, libpcap_dump_open_pcap_ss990417, NULL((void*)0) |
1904 | }; |
1905 | |
1906 | static const struct file_type_subtype_info pcap_ss990915_info = { |
1907 | "SuSE 6.3 tcpdump - pcap", "suse6_3pcap", "pcap", "cap;dmp", |
1908 | false0, BLOCKS_SUPPORTED(pcap_blocks_supported)(sizeof (pcap_blocks_supported) / sizeof (pcap_blocks_supported )[0]), pcap_blocks_supported, |
1909 | libpcap_dump_can_write_encap, libpcap_dump_open_pcap_ss990915, NULL((void*)0) |
1910 | }; |
1911 | |
1912 | static const struct file_type_subtype_info pcap_ss991029_info = { |
1913 | "Modified tcpdump - pcap", "modpcap", "pcap", "cap;dmp", |
1914 | false0, BLOCKS_SUPPORTED(pcap_blocks_supported)(sizeof (pcap_blocks_supported) / sizeof (pcap_blocks_supported )[0]), pcap_blocks_supported, |
1915 | libpcap_dump_can_write_encap, libpcap_dump_open_pcap_ss991029, NULL((void*)0) |
1916 | }; |
1917 | |
1918 | static const struct file_type_subtype_info pcap_nokia_info = { |
1919 | "Nokia tcpdump - pcap", "nokiapcap", "pcap", "cap;dmp", |
1920 | false0, BLOCKS_SUPPORTED(pcap_blocks_supported)(sizeof (pcap_blocks_supported) / sizeof (pcap_blocks_supported )[0]), pcap_blocks_supported, |
1921 | libpcap_dump_can_write_encap, libpcap_dump_open_pcap_nokia, NULL((void*)0) |
1922 | }; |
1923 | |
1924 | void register_pcap(void) |
1925 | { |
1926 | pcap_file_type_subtype = wtap_register_file_type_subtype(&pcap_info); |
1927 | pcap_nsec_file_type_subtype = wtap_register_file_type_subtype(&pcap_nsec_info); |
1928 | pcap_aix_file_type_subtype = wtap_register_file_type_subtype(&pcap_aix_info); |
1929 | pcap_ss990417_file_type_subtype = wtap_register_file_type_subtype(&pcap_ss990417_info); |
1930 | pcap_ss990915_file_type_subtype = wtap_register_file_type_subtype(&pcap_ss990915_info); |
1931 | pcap_ss991029_file_type_subtype = wtap_register_file_type_subtype(&pcap_ss991029_info); |
1932 | pcap_nokia_file_type_subtype = wtap_register_file_type_subtype(&pcap_nokia_info); |
1933 | |
1934 | /* |
1935 | * We now call the libpcap file format just pcap, but we allow |
1936 | * the various variants of it to be specified using names |
1937 | * containing "libpcap" as well as "pcap", for backwards |
1938 | * compatibility. |
1939 | * |
1940 | * Register names for that purpose. |
1941 | */ |
1942 | wtap_register_compatibility_file_subtype_name("libpcap", "pcap"); |
1943 | wtap_register_compatibility_file_subtype_name("nseclibpcap", "nsecpcap"); |
1944 | wtap_register_compatibility_file_subtype_name("aixlibpcap", "aixpcap"); |
1945 | wtap_register_compatibility_file_subtype_name("modlibpcap", "modpcap"); |
1946 | wtap_register_compatibility_file_subtype_name("nokialibpcap", "nokiapcap"); |
1947 | wtap_register_compatibility_file_subtype_name("rh6_1libpcap", "rh6_1pcap"); |
1948 | wtap_register_compatibility_file_subtype_name("suse6_3libpcap", "suse6_3pcap"); |
1949 | |
1950 | /* |
1951 | * Register names for backwards compatibility with the |
1952 | * wtap_filetypes table in Lua. |
1953 | */ |
1954 | wtap_register_backwards_compatibility_lua_name("PCAP", |
1955 | pcap_file_type_subtype); |
1956 | wtap_register_backwards_compatibility_lua_name("PCAP_NSEC", |
1957 | pcap_nsec_file_type_subtype); |
1958 | wtap_register_backwards_compatibility_lua_name("PCAP_AIX", |
1959 | pcap_aix_file_type_subtype); |
1960 | wtap_register_backwards_compatibility_lua_name("PCAP_SS990417", |
1961 | pcap_ss990417_file_type_subtype); |
1962 | wtap_register_backwards_compatibility_lua_name("PCAP_SS990915", |
1963 | pcap_ss990915_file_type_subtype); |
1964 | wtap_register_backwards_compatibility_lua_name("PCAP_SS991029", |
1965 | pcap_ss991029_file_type_subtype); |
1966 | wtap_register_backwards_compatibility_lua_name("PCAP_NOKIA", |
1967 | pcap_nokia_file_type_subtype); |
1968 | } |
1969 | |
1970 | /* |
1971 | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1972 | * |
1973 | * Local variables: |
1974 | * c-basic-offset: 8 |
1975 | * tab-width: 8 |
1976 | * indent-tabs-mode: t |
1977 | * End: |
1978 | * |
1979 | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
1980 | * :indentSize=8:tabSize=8:noTabs=false: |
1981 | */ |