### Bug Summary

File: | builds/wireshark/wireshark/ui/text_import.c
Warning: | line 1316, column 32 Addition of a null pointer (from variable 'str') and a nonzero integer value results in undefined behavior

### 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 text_import.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-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/ui -I /builds/wireshark/wireshark/build/ui -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../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-nonliteral -std=gnu17 -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 -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-07-28-100419-3660-1 -x c /builds/wireshark/wireshark/ui/text_import.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 | /* text_import.c
2 | * State machine for text import
3 | * November 2010, Jaap Keuter <jaap.keuter@xs4all.nl>
4 | * Modified March 2021, Paul Weiß <paulniklasweiss@gmail.com>
5 | *
6 | * Wireshark - Network traffic analyzer
7 | * By Gerald Combs <gerald@wireshark.org>
8 | * Copyright 1998 Gerald Combs
9 | *
10 | * Based on text2pcap.c by Ashok Narayanan <ashokn@cisco.com>
11 | *
12 | * SPDX-License-Identifier: GPL-2.0-or-later
13 | */
14 |
15 | /*******************************************************************************
16 | *
17 | * This code reads in an ASCII hexdump of this common format:
18 | *
19 | * 00000000 00 E0 1E A7 05 6F 00 10 5A A0 B9 12 08 00 46 00 .....o..Z.....F.
20 | * 00000010 03 68 00 00 00 00 0A 2E EE 33 0F 19 08 7F 0F 19 .h.......3......
21 | * 00000020 03 80 94 04 00 00 10 01 16 A2 0A 00 03 50 00 0C .............P..
22 | * 00000030 01 01 0F 19 03 80 11 01 1E 61 00 0C 03 01 0F 19 .........a......
23 | *
24 | * Each bytestring line consists of an offset, one or more bytes, and
25 | * text at the end. An offset is defined as a hex string of more than
26 | * two characters. A byte is defined as a hex string of exactly two
27 | * characters. The text at the end is ignored, as is any text before
28 | * the offset. Bytes read from a bytestring line are added to the
29 | * current packet only if all the following conditions are satisfied:
30 | *
31 | * - No text appears between the offset and the bytes (any bytes appearing after
32 | * such text would be ignored)
33 | *
34 | * - The offset must be arithmetically correct, i.e. if the offset is 00000020,
35 | * then exactly 32 bytes must have been read into this packet before this.
36 | * If the offset is wrong, the packet is immediately terminated
37 | *
38 | * A packet start is signaled by a zero offset.
39 | *
40 | * Lines starting with #TEXT2PCAP are directives. These allow the user
41 | * to embed instructions into the capture file which allows text2pcap
42 | * to take some actions (e.g. specifying the encapsulation
43 | * etc.). Currently no directives are implemented.
44 | *
45 | * Lines beginning with # which are not directives are ignored as
46 | * comments. Currently all non-hexdump text is ignored by text2pcap;
47 | * in the future, text processing may be added, but lines prefixed
48 | * with '#' will still be ignored.
49 | *
50 | * The output is a libpcap packet containing Ethernet frames by
51 | * default. This program takes options which allow the user to add
52 | * dummy Ethernet, IP and UDP, TCP or SCTP headers to the packets in order
53 | * to allow dumps of L3 or higher protocols to be decoded.
54 | *
55 | * Considerable flexibility is built into this code to read hexdumps
56 | * of slightly different formats. For example, any text prefixing the
57 | * hexdump line is dropped (including mail forwarding '>'). The offset
58 | * can be any hex number of four digits or greater.
59 | *
60 | * This converter cannot read a single packet greater than
61 | * WTAP_MAX_PACKET_SIZE_STANDARD. The snapshot length is automatically
62 | * set to WTAP_MAX_PACKET_SIZE_STANDARD.
63 | */
64 |
65 | /*******************************************************************************
66 | * Alternatively this parses a Textfile based on a prel regex containing named
67 | * capturing groups like so:
68 | * (?<seqno>\d+)\s*(?<dir><|>)\s*(?<time>\d+:\d\d:\d\d.\d+)\s+(?<data>[0-9a-fA-F]+)\\s+
69 | *
70 | * Fields are decoded using a lenient parser, but only one attempt is made.
71 | * Except for in data invalid values will be replaced by default ones.
72 | * data currently only accepts plain HEX, OCT or BIN encoded data.
73 | * common field separators are ignored. Note however that 0x or 0b prefixing is
74 | * not supported and no automatic format detection is attempted.
75 | */
76 |
77 | #include "config.h"
78 | #define WS_LOG_DOMAIN"Main" LOG_DOMAIN_MAIN"Main"
79 | #include "text_import.h"
80 |
81 | #include <stdio.h>
82 | #include <stdlib.h>
83 | #include <string.h>
84 | #include <wsutil/file_util.h>
85 | #include <wsutil/buffer.h>
86 | #include <wsutil/strtoi.h>
87 | #include <ws_exit_codes.h>
88 |
89 | #include <time.h>
90 | #include <glib.h>
91 |
92 | #include <errno(*__errno_location ()).h>
93 | #include <assert.h>
94 |
95 | #include <epan/tvbuff.h>
96 | #include <wsutil/crc32.h>
97 | #include <epan/in_cksum.h>
98 |
99 | #include <wsutil/report_message.h>
100 | #include <wsutil/exported_pdu_tlvs.h>
101 |
102 | #include <wsutil/nstime.h>
103 | #include <wsutil/str_util.h>
104 | #include <wsutil/time_util.h>
105 | #include <wsutil/ws_strptime.h>
106 |
107 | #include <wsutil/version_info.h>
108 | #include <wsutil/cpu_info.h>
109 | #include <wsutil/os_version_info.h>
110 |
111 | #include "text_import_scanner.h"
112 | #include "text_import_scanner_lex.h"
113 | #include "text_import_regex.h"
114 |
115 | /*--- Options --------------------------------------------------------------------*/
116 |
117 | /* maximum time precision we can handle = 10^(-SUBSEC_PREC) */
118 | #define SUBSEC_PREC9 9
119 |
120 | static text_import_info_t *info_p;
121 |
122 | /* Dummy Ethernet header */
123 | static bool_Bool hdr_ethernet;
124 | static const uint8_t hdr_eth_dest_addr[6] = {0x20, 0x52, 0x45, 0x43, 0x56, 0x00};
125 | static const uint8_t hdr_eth_src_addr[6] = {0x20, 0x53, 0x45, 0x4E, 0x44, 0x00};
126 | static uint32_t hdr_ethernet_proto;
127 |
128 | /* Dummy IP header */
129 | static bool_Bool hdr_ip;
130 | static bool_Bool hdr_ipv6;
131 | static unsigned hdr_ip_proto;
132 |
133 | /* Destination and source addresses for IP header */
134 | static const ws_in6_addr NO_IPv6_ADDRESS = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
135 | /* These IPv6 default addresses are unique local addresses generated using
136 | * the pseudo-random method from Section 3.2.2 of RFC 4193
137 | */
138 | static const ws_in6_addr IPv6_SRC = {{0xfd, 0xce, 0xd8, 0x62, 0x14, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
139 | static const ws_in6_addr IPv6_DST = {{0xfd, 0xce, 0xd8, 0x62, 0x14, 0x1b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}};
140 |
141 | /* Dummy UDP header */
142 | static bool_Bool hdr_udp;
143 |
144 | /* Dummy TCP header */
145 | static bool_Bool hdr_tcp;
146 |
147 | /* TCP sequence numbers when has_direction is true */
148 | static uint32_t tcp_in_seq_num;
149 | static uint32_t tcp_out_seq_num;
150 |
151 | /* Dummy SCTP header */
152 | static bool_Bool hdr_sctp;
153 |
154 | /* Dummy DATA chunk header */
155 | static bool_Bool hdr_data_chunk;
156 | static uint8_t hdr_data_chunk_type;
157 | static uint8_t hdr_data_chunk_bits;
158 | static uint32_t hdr_data_chunk_tsn;
159 | static uint16_t hdr_data_chunk_sid;
160 | static uint16_t hdr_data_chunk_ssn;
161 |
162 | /* Dummy ExportPdu header */
163 | static bool_Bool hdr_export_pdu;
164 |
165 | /* Hex+ASCII text dump identification, to handle an edge case where
166 | * the ASCII representation contains patterns that look like bytes. */
167 | static uint8_t* pkt_lnstart;
168 |
169 | static bool_Bool has_direction;
170 | static uint32_t direction = PACK_FLAGS_RECEPTION_TYPE_UNSPECIFIED0;
171 | static bool_Bool has_seqno;
172 | static uint64_t seqno;
173 | /*--- Local data -----------------------------------------------------------------*/
174 |
175 | /* This is where we store the packet currently being built */
176 | static uint8_t *packet_buf;
177 | static Buffer prefix_buf;
178 | static uint32_t curr_offset;
179 | static uint32_t packet_start;
180 | static bool_Bool offset_warned;
181 | static import_status_t start_new_packet(bool_Bool);
182 |
183 | /* This buffer contains strings present before the packet offset 0 */
184 | #define PACKET_PREAMBLE_MAX_LEN2048 2048
185 | static uint8_t packet_preamble[PACKET_PREAMBLE_MAX_LEN2048+1];
186 | static int packet_preamble_len;
187 |
188 | /* Time code of packet, derived from packet_preamble */
189 | static time_t ts_sec;
190 | static uint32_t ts_nsec;
191 | static bool_Bool ts_fmt_iso;
192 | static struct tm timecode_default;
193 | static bool_Bool timecode_warned;
194 | /* The time delta to add to packets without a valid time code.
195 | * This can be no smaller than the time resolution of the dump
196 | * file, so the default is 1000 nanoseconds, or 1 microsecond.
197 | * XXX: We should at least get this from the resolution of the file we're
198 | * writing to, and possibly allow the user to set a different value.
199 | */
200 | static uint32_t ts_tick = 1000;
201 |
202 | /* HDR_ETH Offset base to parse */
203 | static uint32_t offset_base = 16;
204 |
205 | /* ----- State machine -----------------------------------------------------------*/
206 |
207 | /* Current state of parser */
208 | typedef enum {
209 | INIT, /* Waiting for start of new packet */
210 | START_OF_LINE, /* Starting from beginning of line */
211 | READ_OFFSET, /* Just read the offset */
212 | READ_BYTE, /* Just read a byte */
213 | READ_TEXT /* Just read text - ignore until EOL */
214 | } parser_state_t;
215 | static parser_state_t state = INIT;
216 |
217 | static const char * const state_str[] = {
218 | "Init",
219 | "Start-of-line",
220 | "Offset",
221 | "Byte",
222 | "Text"
223 | };
224 |
225 | static const char * const token_str[] = {
226 | "",
227 | "Byte",
228 | "Bytes",
229 | "Offset",
230 | "Directive",
231 | "Text",
232 | "End-of-line",
233 | "End-of-file"
234 | };
235 |
236 | /* ----- Skeleton Packet Headers --------------------------------------------------*/
237 |
238 | typedef struct {
239 | uint8_t dest_addr[6];
240 | uint8_t src_addr[6];
241 | uint16_t ethertype;
242 | } hdr_ethernet_t;
243 |
244 | static hdr_ethernet_t HDR_ETHERNET;
245 |
246 | typedef struct {
247 | uint8_t ver_hdrlen;
248 | uint8_t dscp;
249 | uint16_t packet_length;
250 | uint16_t identification;
251 | uint8_t flags;
252 | uint8_t fragment;
253 | uint8_t ttl;
254 | uint8_t protocol;
255 | uint16_t hdr_checksum;
256 | uint32_t src_addr;
257 | uint32_t dest_addr;
258 | } hdr_ip_t;
259 |
260 | /* Default IPv4 addresses if none supplied */
261 | #if G_BYTE_ORDER1234 == G_BIG_ENDIAN4321
262 | #define IP_ID0x3412 0x1234
263 | #define IP_SRC0x0101010a 0x0a010101
264 | #define IP_DST0x0202020a 0x0a020202
265 | #else
266 | #define IP_ID0x3412 0x3412
267 | #define IP_SRC0x0101010a 0x0101010a
268 | #define IP_DST0x0202020a 0x0202020a
269 | #endif
270 |
271 | static hdr_ip_t HDR_IP =
272 | {0x45, 0, 0, IP_ID0x3412, 0, 0, 0xff, 0, 0, IP_SRC0x0101010a, IP_DST0x0202020a};
273 |
274 | static struct { /* pseudo header for checksum calculation */
275 | uint32_t src_addr;
276 | uint32_t dest_addr;
277 | uint8_t zero;
278 | uint8_t protocol;
279 | uint16_t length;
280 | } pseudoh;
281 |
282 |
283 | /* headers taken from glibc */
284 |
285 | typedef struct {
286 | union {
287 | struct ip6_hdrctl {
288 | uint32_t ip6_un1_flow; /* 24 bits of flow-ID */
289 | uint16_t ip6_un1_plen; /* payload length */
290 | uint8_t ip6_un1_nxt; /* next header */
291 | uint8_t ip6_un1_hlim; /* hop limit */
292 | } ip6_un1;
293 | uint8_t ip6_un2_vfc; /* 4 bits version, 4 bits priority */
294 | } ip6_ctlun;
295 | ws_in6_addr ip6_src; /* source address */
296 | ws_in6_addr ip6_dst; /* destination address */
297 | } hdr_ipv6_t;
298 |
299 | static hdr_ipv6_t HDR_IPv6;
300 |
301 | /* https://tools.ietf.org/html/rfc2460#section-8.1 */
302 | static struct { /* pseudo header ipv6 for checksum calculation */
303 | struct e_in6_addr src_addr6;
304 | struct e_in6_addr dst_addr6;
305 | uint32_t length;
306 | uint8_t zero[3];
307 | uint8_t next_header;
308 | } pseudoh6;
309 |
310 |
311 | typedef struct {
312 | uint16_t source_port;
313 | uint16_t dest_port;
314 | uint16_t length;
315 | uint16_t checksum;
316 | } hdr_udp_t;
317 |
318 | static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
319 |
320 | typedef struct {
321 | uint16_t source_port;
322 | uint16_t dest_port;
323 | uint32_t seq_num;
324 | uint32_t ack_num;
325 | uint8_t hdr_length;
326 | uint8_t flags;
327 | uint16_t window;
328 | uint16_t checksum;
329 | uint16_t urg;
330 | } hdr_tcp_t;
331 |
332 | static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
333 |
334 | typedef struct {
335 | uint16_t src_port;
336 | uint16_t dest_port;
337 | uint32_t tag;
338 | uint32_t checksum;
339 | } hdr_sctp_t;
340 |
341 | static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
342 |
343 | typedef struct {
344 | uint8_t type;
345 | uint8_t bits;
346 | uint16_t length;
347 | uint32_t tsn;
348 | uint16_t sid;
349 | uint16_t ssn;
350 | uint32_t ppid;
351 | } hdr_data_chunk_t;
352 |
353 | static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
354 |
355 | typedef struct {
356 | uint16_t tag_type;
357 | uint16_t payload_len;
358 | } hdr_export_pdu_t;
359 |
360 | static hdr_export_pdu_t HDR_EXPORT_PDU = {0, 0};
361 |
362 | #define EXPORT_PDU_END_OF_OPTIONS_SIZE4 4
363 |
364 | /*----------------------------------------------------------------------
365 | * Parse a single hex number
366 | * Will abort the program if it can't parse the number
367 | * Pass in true if this is an offset, false if not
368 | */
369 | static import_status_t
370 | parse_num(const char *str, int offset, uint32_t* num)
371 | {
372 | char *c;
373 |
374 | if (str == NULL((void*)0)) {
375 | report_failure("FATAL ERROR: str is NULL");
376 | return IMPORT_FAILURE;
377 | }
378 |
379 | errno(*__errno_location ()) = 0;
380 | unsigned long ulnum = strtoul(str, &c, offset ? offset_base : 16);
381 | if (errno(*__errno_location ()) != 0) {
382 | report_failure("Unable to convert %s to base %u: %s", str,
383 | offset ? offset_base : 16, g_strerror(errno(*__errno_location ())));
384 | return IMPORT_FAILURE;
385 | }
386 | if (c == str) {
387 | report_failure("Unable to convert %s to base %u", str,
388 | offset ? offset_base : 16);
389 | return IMPORT_FAILURE;
390 | }
391 | if (ulnum > UINT32_MAX(4294967295U)) {
392 | report_failure("%s too large", str);
393 | return IMPORT_FAILURE;
394 | }
395 | *num = (uint32_t) ulnum;
396 | return IMPORT_SUCCESS;
397 | }
398 |
399 | /*----------------------------------------------------------------------
400 | * Write this byte into current packet
401 | */
402 | static import_status_t
403 | write_byte(const char *str)
404 | {
405 | uint32_t num;
406 |
407 | if (parse_num(str, false0, &num) != IMPORT_SUCCESS)
408 | return IMPORT_FAILURE;
409 |
410 | packet_buf[curr_offset] = (uint8_t) num;
411 | curr_offset++;
412 | if (curr_offset >= info_p->max_frame_length) /* packet full */
413 | if (start_new_packet(true1) != IMPORT_SUCCESS)
414 | return IMPORT_FAILURE;
415 |
416 | return IMPORT_SUCCESS;
417 | }
418 |
419 | static import_status_t
420 | write_bytes(const char *str)
421 | {
422 | uint32_t num;
423 |
424 | if (parse_num(str, false0, &num) != IMPORT_SUCCESS)
425 | return IMPORT_FAILURE;
426 |
427 | int len = (int)strlen(str);
428 | /* There's always extra room in the packet_buf for the dummy headers
429 | * compared to max_frame_length, so we could copy all the bytes at
430 | * once and then check for overflow afterwards (copying it off).
431 | * That would be moderately faster due to optimization on most
432 | * compilers (and we could use the routines from wsutil/pint.h)
433 | */
434 | if (info_p->hexdump.little_endian) {
435 | for (int i = 0; i < 4*len; i += 8) {
436 | packet_buf[curr_offset] = (uint8_t)(num >> i);
437 | curr_offset++;
438 | if (curr_offset >= info_p->max_frame_length) /* packet full */
439 | if (start_new_packet(true1) != IMPORT_SUCCESS)
440 | return IMPORT_FAILURE;
441 | }
442 | } else {
443 | for (int i = 4*len - 8; i >= 0; i -= 8) {
444 | packet_buf[curr_offset] = (uint8_t)(num >> i);
445 | curr_offset++;
446 | if (curr_offset >= info_p->max_frame_length) /* packet full */
447 | if (start_new_packet(true1) != IMPORT_SUCCESS)
448 | return IMPORT_FAILURE;
449 | }
450 | }
451 |
452 | return IMPORT_SUCCESS;
453 | }
454 |
455 | /*----------------------------------------------------------------------
456 | * Remove bytes from the current packet
457 | */
458 | static void
459 | unwrite_bytes (uint32_t nbytes)
460 | {
461 | curr_offset -= nbytes;
462 | }
463 |
464 | /*----------------------------------------------------------------------
465 | * Determine SCTP chunk padding length
466 | */
467 | static uint32_t
468 | number_of_padding_bytes (uint32_t length)
469 | {
470 | uint32_t remainder;
471 |
472 | remainder = length % 4;
473 |
474 | if (remainder == 0)
475 | return 0;
476 | else
477 | return 4 - remainder;
478 | }
479 |
480 | /*----------------------------------------------------------------------
481 | * Write current packet out
482 | *
483 | * @param cont [IN] true if a packet is being written because the max frame
484 | * length was reached, and the original packet from the input file is
485 | * continued in a later frame. Used to set fragmentation fields in dummy
486 | * headers (currently only implemented for SCTP; IPv4 could be added later.)
487 | */
488 | static import_status_t
489 | write_current_packet(bool_Bool cont)
490 | {
491 | int prefix_length = 0;
492 | int proto_length = 0;
493 | int ip_length = 0;
494 | int eth_trailer_length = 0;
495 | int i, padding_length;
496 |
497 | if (curr_offset > 0) {
498 | /* Write the packet */
499 |
500 | /* Is direction indication on with an inbound packet? */
501 | bool_Bool isOutbound = has_direction && (direction == PACK_FLAGS_DIRECTION_OUTBOUND2);
502 |
503 | ws_buffer_clean(&prefix_buf);
504 |
505 | /* Compute packet length */
506 | prefix_length = 0;
507 | if (hdr_export_pdu) {
508 | prefix_length += (int)sizeof(HDR_EXPORT_PDU) + (int)strlen(info_p->payload) + EXPORT_PDU_END_OF_OPTIONS_SIZE4;
509 | proto_length = prefix_length + curr_offset;
510 | }
511 | if (hdr_data_chunk) { prefix_length += (int)sizeof(HDR_DATA_CHUNK); }
512 | if (hdr_sctp) { prefix_length += (int)sizeof(HDR_SCTP); }
513 | if (hdr_udp) { prefix_length += (int)sizeof(HDR_UDP); proto_length = prefix_length + curr_offset; }
514 | if (hdr_tcp) { prefix_length += (int)sizeof(HDR_TCP); proto_length = prefix_length + curr_offset; }
515 | if (hdr_ip) {
516 | prefix_length += (int)sizeof(HDR_IP);
517 | ip_length = prefix_length + curr_offset + ((hdr_data_chunk) ? number_of_padding_bytes(curr_offset) : 0);
518 | } else if (hdr_ipv6) {
519 | ip_length = prefix_length + curr_offset + ((hdr_data_chunk) ? number_of_padding_bytes(curr_offset) : 0);
520 | /* IPv6 payload length field does not include the header itself.
521 | * It does include extension headers, but we don't put any
522 | * (if we later do fragments, that would change.)
523 | */
524 | prefix_length += (int)sizeof(HDR_IPv6);
525 | }
526 | if (hdr_ethernet) { prefix_length += (int)sizeof(HDR_ETHERNET); }
527 |
528 | if (hdr_ethernet) {
529 | /* Pad trailer */
530 | if (prefix_length + curr_offset < 60) {
531 | eth_trailer_length = 60 - (prefix_length + curr_offset);
532 | }
533 | }
534 |
535 | /* Write Ethernet header */
536 | if (hdr_ethernet) {
537 | if (isOutbound)
538 | {
539 | memcpy(HDR_ETHERNET.dest_addr, hdr_eth_src_addr, 6);
540 | memcpy(HDR_ETHERNET.src_addr, hdr_eth_dest_addr, 6);
541 | } else {
542 | memcpy(HDR_ETHERNET.dest_addr, hdr_eth_dest_addr, 6);
543 | memcpy(HDR_ETHERNET.src_addr, hdr_eth_src_addr, 6);
544 | }
545 | HDR_ETHERNET.ethertype = g_htons(hdr_ethernet_proto)(((((guint16) ( (guint16) ((guint16) (hdr_ethernet_proto) >> 8) | (guint16) ((guint16) (hdr_ethernet_proto) << 8))) )));
546 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_ETHERNET, sizeof(HDR_ETHERNET));
547 | }
548 |
549 | /* Write IP header */
550 | if (hdr_ip) {
551 | vec_t cksum_vector[1];
552 |
553 | if (isOutbound) {
554 | HDR_IP.src_addr = info_p->ip_dest_addr.ipv4 ? info_p->ip_dest_addr.ipv4 : IP_DST0x0202020a;
555 | HDR_IP.dest_addr = info_p->ip_src_addr.ipv4 ? info_p->ip_src_addr.ipv4 : IP_SRC0x0101010a;
556 | }
557 | else {
558 | HDR_IP.src_addr = info_p->ip_src_addr.ipv4 ? info_p->ip_src_addr.ipv4 : IP_SRC0x0101010a;
559 | HDR_IP.dest_addr = info_p->ip_dest_addr.ipv4 ? info_p->ip_dest_addr.ipv4 : IP_DST0x0202020a;
560 | }
561 | HDR_IP.packet_length = g_htons(ip_length)(((((guint16) ( (guint16) ((guint16) (ip_length) >> 8) | (guint16) ((guint16) (ip_length) << 8))))));
562 | HDR_IP.protocol = (uint8_t) hdr_ip_proto;
563 | HDR_IP.hdr_checksum = 0;
564 | cksum_vector[0].ptr = (uint8_t *)&HDR_IP; cksum_vector[0].len = sizeof(HDR_IP);
565 | HDR_IP.hdr_checksum = in_cksum(cksum_vector, 1);
566 |
567 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_IP, sizeof(HDR_IP));
568 |
569 | /* initialize pseudo header for checksum calculation */
570 | pseudoh.src_addr = HDR_IP.src_addr;
571 | pseudoh.dest_addr = HDR_IP.dest_addr;
572 | pseudoh.zero = 0;
573 | pseudoh.protocol = (uint8_t) hdr_ip_proto;
574 | pseudoh.length = g_htons(proto_length)(((((guint16) ( (guint16) ((guint16) (proto_length) >> 8 ) | (guint16) ((guint16) (proto_length) << 8))))));
575 | } else if (hdr_ipv6) {
576 | if (memcmp(&info_p->ip_dest_addr.ipv6, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr))) {
577 | memcpy(isOutbound ? &HDR_IPv6.ip6_src : &HDR_IPv6.ip6_dst, &info_p->ip_dest_addr.ipv6, sizeof(ws_in6_addr));
578 | } else {
579 | memcpy(isOutbound ? &HDR_IPv6.ip6_src : &HDR_IPv6.ip6_dst, &IPv6_DST, sizeof(ws_in6_addr));
580 | }
581 | if (memcmp(&info_p->ip_src_addr.ipv6, &NO_IPv6_ADDRESS, sizeof(ws_in6_addr))) {
582 | memcpy(isOutbound ? &HDR_IPv6.ip6_dst : &HDR_IPv6.ip6_src, &info_p->ip_src_addr.ipv6, sizeof(ws_in6_addr));
583 | } else {
584 | memcpy(isOutbound ? &HDR_IPv6.ip6_dst : &HDR_IPv6.ip6_src, &IPv6_SRC, sizeof(ws_in6_addr));
585 | }
586 |
587 | HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
588 | HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
589 | HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(ip_length)(((((guint16) ( (guint16) ((guint16) (ip_length) >> 8) | (guint16) ((guint16) (ip_length) << 8))))));
590 | HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt = (uint8_t) hdr_ip_proto;
591 | HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
592 |
593 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_IPv6, sizeof(HDR_IPv6));
594 |
595 | /* initialize pseudo ipv6 header for checksum calculation */
596 | pseudoh6.src_addr6 = HDR_IPv6.ip6_src;
597 | pseudoh6.dst_addr6 = HDR_IPv6.ip6_dst;
598 | memset(pseudoh6.zero, 0, sizeof(pseudoh6.zero));
599 | pseudoh6.next_header = (uint8_t) hdr_ip_proto;
600 | pseudoh6.length = g_htons(proto_length)(((((guint16) ( (guint16) ((guint16) (proto_length) >> 8 ) | (guint16) ((guint16) (proto_length) << 8))))));
601 | }
602 |
603 | /* Write UDP header */
604 | if (hdr_udp) {
605 | vec_t cksum_vector[3];
606 |
607 | HDR_UDP.source_port = isOutbound ? g_htons(info_p->dst_port)(((((guint16) ( (guint16) ((guint16) (info_p->dst_port) >> 8) | (guint16) ((guint16) (info_p->dst_port) << 8)) )))): g_htons(info_p->src_port)(((((guint16) ( (guint16) ((guint16) (info_p->src_port) >> 8) | (guint16) ((guint16) (info_p->src_port) << 8)) ))));
608 | HDR_UDP.dest_port = isOutbound ? g_htons(info_p->src_port)(((((guint16) ( (guint16) ((guint16) (info_p->src_port) >> 8) | (guint16) ((guint16) (info_p->src_port) << 8)) )))) : g_htons(info_p->dst_port)(((((guint16) ( (guint16) ((guint16) (info_p->dst_port) >> 8) | (guint16) ((guint16) (info_p->dst_port) << 8)) ))));
609 | HDR_UDP.length = g_htons(proto_length)(((((guint16) ( (guint16) ((guint16) (proto_length) >> 8 ) | (guint16) ((guint16) (proto_length) << 8))))));
610 |
611 | HDR_UDP.checksum = 0;
612 | if (hdr_ipv6) {
613 | cksum_vector[0].ptr = (uint8_t *)&pseudoh6; cksum_vector[0].len = sizeof(pseudoh6);
614 | } else {
615 | cksum_vector[0].ptr = (uint8_t *)&pseudoh; cksum_vector[0].len = sizeof(pseudoh);
616 | }
617 | cksum_vector[1].ptr = (uint8_t *)&HDR_UDP; cksum_vector[1].len = sizeof(HDR_UDP);
618 | cksum_vector[2].ptr = packet_buf; cksum_vector[2].len = curr_offset;
619 | HDR_UDP.checksum = in_cksum(cksum_vector, 3);
620 |
621 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_UDP, sizeof(HDR_UDP));
622 | }
623 |
624 | /* Write TCP header */
625 | if (hdr_tcp) {
626 | vec_t cksum_vector[3];
627 |
628 | HDR_TCP.source_port = isOutbound ? g_htons(info_p->dst_port)(((((guint16) ( (guint16) ((guint16) (info_p->dst_port) >> 8) | (guint16) ((guint16) (info_p->dst_port) << 8)) )))): g_htons(info_p->src_port)(((((guint16) ( (guint16) ((guint16) (info_p->src_port) >> 8) | (guint16) ((guint16) (info_p->src_port) << 8)) ))));
629 | HDR_TCP.dest_port = isOutbound ? g_htons(info_p->src_port)(((((guint16) ( (guint16) ((guint16) (info_p->src_port) >> 8) | (guint16) ((guint16) (info_p->src_port) << 8)) )))) : g_htons(info_p->dst_port)(((((guint16) ( (guint16) ((guint16) (info_p->dst_port) >> 8) | (guint16) ((guint16) (info_p->dst_port) << 8)) ))));
630 | /* set ack number if we have direction */
631 | if (has_direction) {
632 | HDR_TCP.flags = 0x10;
633 | HDR_TCP.ack_num = g_ntohl(isOutbound ? tcp_out_seq_num : tcp_in_seq_num)((((((guint32) ( (((guint32) (isOutbound ? tcp_out_seq_num : tcp_in_seq_num ) & (guint32) 0x000000ffU) << 24) | (((guint32) (isOutbound ? tcp_out_seq_num : tcp_in_seq_num) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (isOutbound ? tcp_out_seq_num : tcp_in_seq_num ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (isOutbound ? tcp_out_seq_num : tcp_in_seq_num) & (guint32) 0xff000000U ) >> 24)))))));
634 | HDR_TCP.ack_num = g_htonl(HDR_TCP.ack_num)(((((guint32) ( (((guint32) (HDR_TCP.ack_num) & (guint32) 0x000000ffU) << 24) | (((guint32) (HDR_TCP.ack_num) & (guint32) 0x0000ff00U) << 8) | (((guint32) (HDR_TCP.ack_num ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (HDR_TCP .ack_num) & (guint32) 0xff000000U) >> 24))))));
635 | }
636 | else {
637 | HDR_TCP.flags = 0;
638 | HDR_TCP.ack_num = 0;
639 | }
640 | HDR_TCP.seq_num = isOutbound ? tcp_in_seq_num : tcp_out_seq_num;
641 | HDR_TCP.window = g_htons(0x2000)(((((guint16) ( (guint16) ((guint16) (0x2000) >> 8) | ( guint16) ((guint16) (0x2000) << 8))))));
642 |
643 | HDR_TCP.checksum = 0;
644 | if (hdr_ipv6) {
645 | cksum_vector[0].ptr = (uint8_t *)&pseudoh6; cksum_vector[0].len = sizeof(pseudoh6);
646 | } else {
647 | cksum_vector[0].ptr = (uint8_t *)&pseudoh; cksum_vector[0].len = sizeof(pseudoh);
648 | }
649 | cksum_vector[1].ptr = (uint8_t *)&HDR_TCP; cksum_vector[1].len = sizeof(HDR_TCP);
650 | cksum_vector[2].ptr = packet_buf; cksum_vector[2].len = curr_offset;
651 | HDR_TCP.checksum = in_cksum(cksum_vector, 3);
652 |
653 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_TCP, sizeof(HDR_TCP));
654 | if (isOutbound) {
655 | tcp_in_seq_num = g_ntohl(tcp_in_seq_num)((((((guint32) ( (((guint32) (tcp_in_seq_num) & (guint32) 0x000000ffU) << 24) | (((guint32) (tcp_in_seq_num) & (guint32) 0x0000ff00U) << 8) | (((guint32) (tcp_in_seq_num ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (tcp_in_seq_num ) & (guint32) 0xff000000U) >> 24))))))) + curr_offset;
656 | tcp_in_seq_num = g_htonl(tcp_in_seq_num)(((((guint32) ( (((guint32) (tcp_in_seq_num) & (guint32) 0x000000ffU ) << 24) | (((guint32) (tcp_in_seq_num) & (guint32) 0x0000ff00U) << 8) | (((guint32) (tcp_in_seq_num) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (tcp_in_seq_num ) & (guint32) 0xff000000U) >> 24))))));
657 | }
658 | else {
659 | tcp_out_seq_num = g_ntohl(tcp_out_seq_num)((((((guint32) ( (((guint32) (tcp_out_seq_num) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (tcp_out_seq_num) & (guint32) 0x0000ff00U) << 8) | (((guint32) (tcp_out_seq_num ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (tcp_out_seq_num ) & (guint32) 0xff000000U) >> 24))))))) + curr_offset;
660 | tcp_out_seq_num = g_htonl(tcp_out_seq_num)(((((guint32) ( (((guint32) (tcp_out_seq_num) & (guint32) 0x000000ffU) << 24) | (((guint32) (tcp_out_seq_num) & (guint32) 0x0000ff00U) << 8) | (((guint32) (tcp_out_seq_num ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (tcp_out_seq_num ) & (guint32) 0xff000000U) >> 24))))));
661 | }
662 | }
663 |
664 | /* Compute DATA chunk header and append padding */
665 | if (hdr_data_chunk) {
666 | hdr_data_chunk_bits = 0;
667 | if (packet_start == 0) {
668 | hdr_data_chunk_bits |= 0x02;
669 | }
670 | if (!cont) {
671 | hdr_data_chunk_bits |= 0x01;
672 | }
673 | HDR_DATA_CHUNK.type = hdr_data_chunk_type;
674 | HDR_DATA_CHUNK.bits = hdr_data_chunk_bits;
675 | HDR_DATA_CHUNK.length = g_htons(curr_offset + sizeof(HDR_DATA_CHUNK))(((((guint16) ( (guint16) ((guint16) (curr_offset + sizeof(HDR_DATA_CHUNK )) >> 8) | (guint16) ((guint16) (curr_offset + sizeof(HDR_DATA_CHUNK )) << 8))))));
676 | HDR_DATA_CHUNK.tsn = g_htonl(hdr_data_chunk_tsn)(((((guint32) ( (((guint32) (hdr_data_chunk_tsn) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (hdr_data_chunk_tsn ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (hdr_data_chunk_tsn ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (hdr_data_chunk_tsn ) & (guint32) 0xff000000U) >> 24))))));
677 | HDR_DATA_CHUNK.sid = g_htons(hdr_data_chunk_sid)(((((guint16) ( (guint16) ((guint16) (hdr_data_chunk_sid) >> 8) | (guint16) ((guint16) (hdr_data_chunk_sid) << 8))) )));
678 | HDR_DATA_CHUNK.ssn = g_htons(hdr_data_chunk_ssn)(((((guint16) ( (guint16) ((guint16) (hdr_data_chunk_ssn) >> 8) | (guint16) ((guint16) (hdr_data_chunk_ssn) << 8))) )));
679 | HDR_DATA_CHUNK.ppid = g_htonl(info_p->ppi)(((((guint32) ( (((guint32) (info_p->ppi) & (guint32) 0x000000ffU ) << 24) | (((guint32) (info_p->ppi) & (guint32) 0x0000ff00U) << 8) | (((guint32) (info_p->ppi) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (info_p-> ppi) & (guint32) 0xff000000U) >> 24))))));
680 | hdr_data_chunk_tsn++;
681 | if (!cont) {
682 | hdr_data_chunk_ssn++;
683 | }
684 | padding_length = number_of_padding_bytes(curr_offset);
685 | for (i=0; i<padding_length; i++)
686 | packet_buf[curr_offset+i] = 0;
687 | curr_offset += padding_length;
688 | }
689 |
690 | /* Write SCTP header */
691 | if (hdr_sctp) {
692 | HDR_SCTP.src_port = isOutbound ? g_htons(info_p->dst_port)(((((guint16) ( (guint16) ((guint16) (info_p->dst_port) >> 8) | (guint16) ((guint16) (info_p->dst_port) << 8)) )))): g_htons(info_p->src_port)(((((guint16) ( (guint16) ((guint16) (info_p->src_port) >> 8) | (guint16) ((guint16) (info_p->src_port) << 8)) ))));
693 | HDR_SCTP.dest_port = isOutbound ? g_htons(info_p->src_port)(((((guint16) ( (guint16) ((guint16) (info_p->src_port) >> 8) | (guint16) ((guint16) (info_p->src_port) << 8)) )))) : g_htons(info_p->dst_port)(((((guint16) ( (guint16) ((guint16) (info_p->dst_port) >> 8) | (guint16) ((guint16) (info_p->dst_port) << 8)) ))));
694 | HDR_SCTP.tag = g_htonl(info_p->tag)(((((guint32) ( (((guint32) (info_p->tag) & (guint32) 0x000000ffU ) << 24) | (((guint32) (info_p->tag) & (guint32) 0x0000ff00U) << 8) | (((guint32) (info_p->tag) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (info_p-> tag) & (guint32) 0xff000000U) >> 24))))));
695 | HDR_SCTP.checksum = g_htonl(0)(((((guint32) ( (((guint32) (0) & (guint32) 0x000000ffU) << 24) | (((guint32) (0) & (guint32) 0x0000ff00U) << 8 ) | (((guint32) (0) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (0) & (guint32) 0xff000000U) >> 24)))) ));
696 |
697 | HDR_SCTP.checksum = crc32c_calculate(&HDR_SCTP, sizeof(HDR_SCTP), CRC32C_PRELOAD0xffffffff);
698 | if (hdr_data_chunk)
699 | HDR_SCTP.checksum = crc32c_calculate(&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK), HDR_SCTP.checksum);
700 | HDR_SCTP.checksum = g_htonl(~crc32c_calculate(packet_buf, curr_offset, HDR_SCTP.checksum))(((((guint32) ( (((guint32) (~crc32c_calculate(packet_buf, curr_offset , HDR_SCTP.checksum)) & (guint32) 0x000000ffU) << 24 ) | (((guint32) (~crc32c_calculate(packet_buf, curr_offset, HDR_SCTP .checksum)) & (guint32) 0x0000ff00U) << 8) | (((guint32 ) (~crc32c_calculate(packet_buf, curr_offset, HDR_SCTP.checksum )) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (~crc32c_calculate (packet_buf, curr_offset, HDR_SCTP.checksum)) & (guint32) 0xff000000U) >> 24))))));
701 |
702 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_SCTP, sizeof(HDR_SCTP));
703 | }
704 |
705 | /* Write DATA chunk header */
706 | if (hdr_data_chunk) {
707 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_DATA_CHUNK, sizeof(HDR_DATA_CHUNK));
708 | }
709 |
710 | /* Write ExportPDU header */
711 | if (hdr_export_pdu) {
712 | unsigned payload_len = (unsigned)strlen(info_p->payload);
713 | HDR_EXPORT_PDU.tag_type = g_htons(EXP_PDU_TAG_DISSECTOR_NAME)(((((guint16) ( (guint16) ((guint16) (12) >> 8) | (guint16 ) ((guint16) (12) << 8))))));
714 | HDR_EXPORT_PDU.payload_len = g_htons(payload_len)(((((guint16) ( (guint16) ((guint16) (payload_len) >> 8 ) | (guint16) ((guint16) (payload_len) << 8))))));
715 | ws_buffer_append(&prefix_buf, (uint8_t*)&HDR_EXPORT_PDU, sizeof(HDR_EXPORT_PDU));
716 | ws_buffer_append(&prefix_buf, (uint8_t*)info_p->payload, payload_len);
717 | /* Add end-of-options tag */
718 | ws_buffer_assure_space(&prefix_buf, 4);
719 | memset(ws_buffer_end_ptr(&prefix_buf), 0x00, 4);
720 | ws_buffer_increase_length(&prefix_buf, 4);
721 | }
722 |
723 | HDR_TCP.seq_num = g_ntohl(HDR_TCP.seq_num)((((((guint32) ( (((guint32) (HDR_TCP.seq_num) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (HDR_TCP.seq_num) & (guint32) 0x0000ff00U) << 8) | (((guint32) (HDR_TCP.seq_num ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (HDR_TCP .seq_num) & (guint32) 0xff000000U) >> 24))))))) + curr_offset;
724 | HDR_TCP.seq_num = g_htonl(HDR_TCP.seq_num)(((((guint32) ( (((guint32) (HDR_TCP.seq_num) & (guint32) 0x000000ffU) << 24) | (((guint32) (HDR_TCP.seq_num) & (guint32) 0x0000ff00U) << 8) | (((guint32) (HDR_TCP.seq_num ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (HDR_TCP .seq_num) & (guint32) 0xff000000U) >> 24))))));
725 |
726 | /* Write the record */
727 | int data_length;
728 | wtap_rec rec;
729 | int err;
730 | char *err_info;
731 |
732 | ws_assert(prefix_length == (int)ws_buffer_length(&prefix_buf))do { if ((1) && !(prefix_length == (int)ws_buffer_length (&prefix_buf))) ws_log_fatal_full("Main", LOG_LEVEL_ERROR , "ui/text_import.c", 732, __func__, "assertion failed: %s", "prefix_length == (int)ws_buffer_length(&prefix_buf)" ); } while (0);
733 |
734 | data_length = prefix_length + curr_offset + eth_trailer_length;
735 | wtap_rec_init(&rec, data_length);
736 |
737 | if (info_p->encapsulation == WTAP_ENCAP_SYSTEMD_JOURNAL203) {
738 | wtap_setup_systemd_journal_export_rec(&rec);
739 | rec.block = wtap_block_create(WTAP_BLOCK_SYSTEMD_JOURNAL_EXPORT);
740 | rec.rec_header.systemd_journal_export_header.record_len = data_length;
741 | rec.presence_flags = WTAP_HAS_CAP_LEN0x00000002|WTAP_HAS_TS0x00000001;
742 | /* XXX: Ignore our direction, packet id, and timestamp. For a
743 | * systemd Journal Export Block the timestamp comes from the
744 | * __REALTIME_TIMESTAMP= field. We don't check to see if that
745 | * field is there (it MUST be, but we don't check whether our
746 | * input is malformed in general), but since the presence flags
747 | * aren't really used when writing, it doesn't matter.
748 | */
749 | } else {
750 | wtap_setup_packet_rec(&rec, info_p->encapsulation);
751 | rec.block = wtap_block_create(WTAP_BLOCK_PACKET);
752 | rec.rec_header.packet_header.caplen = rec.rec_header.packet_header.len = data_length;
753 | rec.ts.secs = ts_sec;
754 | rec.ts.nsecs = ts_nsec;
755 | rec.presence_flags = WTAP_HAS_CAP_LEN0x00000002|WTAP_HAS_INTERFACE_ID0x00000004|WTAP_HAS_TS0x00000001;
756 | if (has_direction) {
757 | wtap_block_add_uint32_option(rec.block, OPT_PKT_FLAGS2, direction);
758 | }
759 | if (has_seqno) {
760 | wtap_block_add_uint64_option(rec.block, OPT_PKT_PACKETID5, seqno);
761 | }
762 | }
763 |
764 | ws_buffer_append_buffer(&rec.data, &prefix_buf);
765 | ws_buffer_append(&rec.data, packet_buf, curr_offset);
766 |
767 | /* Write Ethernet trailer */
768 | if (hdr_ethernet && eth_trailer_length > 0) {
769 | ws_buffer_assure_space(&rec.data, eth_trailer_length);
770 | memset(ws_buffer_end_ptr(&rec.data), 0, eth_trailer_length);
771 | ws_buffer_increase_length(&rec.data, eth_trailer_length);
772 | }
773 |
774 |
775 | if (!wtap_dump(info_p->wdh, &rec, &err, &err_info)) {
776 | report_cfile_write_failure(info_p->import_text_filename,
777 | info_p->output_filename, err, err_info,
778 | info_p->num_packets_read,
779 | wtap_dump_file_type_subtype(info_p->wdh));
780 | wtap_rec_cleanup(&rec);
781 | return IMPORT_FAILURE;
782 | }
783 | wtap_rec_cleanup(&rec);
784 | info_p->num_packets_written++;
785 | }
786 |
787 | packet_start += curr_offset;
788 | curr_offset = 0;
789 | return IMPORT_SUCCESS;
790 | }
791 |
792 |
793 | /*----------------------------------------------------------------------
794 | * Append a token to the packet preamble.
795 | */
796 | static import_status_t
797 | append_to_preamble(char *str)
798 | {
799 | size_t toklen;
800 |
801 | if (packet_preamble_len != 0) {
802 | if (packet_preamble_len == PACKET_PREAMBLE_MAX_LEN2048)
803 | return IMPORT_SUCCESS; /* no room to add more preamble */
804 | /* XXX: Just keep going? This is probably not a problem, unless
805 | * someone had >2000 bytes of whitespace before the timestamp... */
806 | /* Add a blank separator between the previous token and this token. */
807 | packet_preamble[packet_preamble_len++] = ' ';
808 | }
809 | if(str == NULL((void*)0)){
810 | report_failure("FATAL ERROR: str is NULL");
811 | return IMPORT_FAILURE;
812 | }
813 | toklen = strlen(str);
814 | if (toklen != 0) {
815 | if (packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN2048)
816 | return IMPORT_SUCCESS; /* no room to add token to the preamble */
817 | /* XXX: Just keep going? This is probably not a problem, as above.*/
818 | (void) g_strlcpy((char*)&packet_preamble[packet_preamble_len], str, PACKET_PREAMBLE_MAX_LEN2048);
819 | packet_preamble_len += (int) toklen;
820 | if (ws_log_get_level() >= LOG_LEVEL_NOISY) {
821 | char *c;
822 | char xs[PACKET_PREAMBLE_MAX_LEN2048];
823 | (void) g_strlcpy(xs, (const char*)packet_preamble, PACKET_PREAMBLE_MAX_LEN2048);
824 | while ((c = strchr(xs, '\r')) != NULL((void*)0)) *c=' ';
825 | ws_noisy("[[append_to_preamble: \"%s\"]]", xs)do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 825, __func__, "[[append_to_preamble: \"%s\"]]", xs); } } while (0);
826 | }
827 | }
828 |
829 | return IMPORT_SUCCESS;
830 | }
831 |
832 | #define INVALID_VALUE(-1) (-1)
833 |
834 | /*
835 | * This includes not just true whitespace values, but also any other
836 | * character silently ignored if part of the data group match, such as
837 | * byte separators or the '=' used for padding at the end of Base64.
838 | */
839 | #define WHITESPACE_VALUE(-2) (-2)
840 |
841 | /*
842 | * Information on how to parse any plainly encoded binary data
843 | *
844 | * one Unit is least_common_multiple(bits_per_char, 8) bits.
845 | */
846 | struct plain_decoding_data {
847 | const char* name;
848 | unsigned chars_per_unit;
849 | unsigned bytes_per_unit : 3; /* Internally a uint64_t is used to hold units */
850 | unsigned bits_per_char : 6;
851 | int8_t table[256];
852 | };
853 |
854 | #define _INVALID_INIT2(-1), (-1) INVALID_VALUE(-1), INVALID_VALUE(-1)
855 | #define _INVALID_INIT4(-1), (-1), (-1), (-1) _INVALID_INIT2(-1), (-1), _INVALID_INIT2(-1), (-1)
856 | #define _INVALID_INIT8(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) _INVALID_INIT4(-1), (-1), (-1), (-1), _INVALID_INIT4(-1), (-1), (-1), (-1)
857 | #define _INVALID_INIT16(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1) _INVALID_INIT8(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), _INVALID_INIT8(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1)
858 | #define _INVALID_INIT32(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1) _INVALID_INIT16(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), _INVALID_INIT16(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1)
859 | #define _INVALID_INIT64(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1) _INVALID_INIT32(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), _INVALID_INIT32(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1)
860 | #define _INVALID_INIT128(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1) _INVALID_INIT64(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), _INVALID_INIT64(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1)
861 | #define _INVALID_INIT256(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) _INVALID_INIT128(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), _INVALID_INIT128(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1)
862 |
863 | #define INVALID_INIT(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) _INVALID_INIT256(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1)
864 | // this is a gcc/clang extension:
865 | // [0 ... 255] = INVALID_VALUE
866 |
867 | #define WHITESPACE_INIT[' '] = (-2), ['\t'] = (-2), ['\n'] = (-2), ['\v'] = (-2), ['\f' ] = (-2), ['\r'] = (-2) \
868 | [' '] = WHITESPACE_VALUE(-2), \
869 | ['\t'] = WHITESPACE_VALUE(-2), \
870 | ['\n'] = WHITESPACE_VALUE(-2), \
871 | ['\v'] = WHITESPACE_VALUE(-2), \
872 | ['\f'] = WHITESPACE_VALUE(-2), \
873 | ['\r'] = WHITESPACE_VALUE(-2)
874 |
875 |
876 | /*
877 | * Some compilers warn about initializing the same subobject
878 | * more than once with designated initializers.
879 | *
880 | * We're doing that - INVALID_INIT initializes everything to
881 | * INVALID_VALUE, but then we override selected elements -
882 | * but we know what we're doing, so just suppress that
883 | * warning.
884 | */
885 | DIAG_OFF_INIT_TWICEclang diagnostic push clang diagnostic ignored "-Winitializer-overrides"
886 |
887 | static const struct plain_decoding_data hex_decode_info = {
888 | .chars_per_unit = 2,
889 | .bytes_per_unit = 1,
890 | .bits_per_char = 4,
891 | .table = {
892 | INVALID_INIT(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1),
893 | WHITESPACE_INIT[' '] = (-2), ['\t'] = (-2), ['\n'] = (-2), ['\v'] = (-2), ['\f' ] = (-2), ['\r'] = (-2),
894 | [':'] = WHITESPACE_VALUE(-2),
895 | ['0'] = 0,1,2,3,4,5,6,7,8,9,
896 | ['A'] = 10,11,12,13,14,15,
897 | ['a'] = 10,11,12,13,14,15
898 | }
899 | };
900 |
901 | static const struct plain_decoding_data bin_decode_info = {
902 | .chars_per_unit = 8,
903 | .bytes_per_unit = 1,
904 | .bits_per_char = 1,
905 | .table = {
906 | INVALID_INIT(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1),
907 | WHITESPACE_INIT[' '] = (-2), ['\t'] = (-2), ['\n'] = (-2), ['\v'] = (-2), ['\f' ] = (-2), ['\r'] = (-2),
908 | ['0'] = 0, 1
909 | }
910 | };
911 |
912 | static const struct plain_decoding_data oct_decode_info = {
913 | .chars_per_unit = 8,
914 | .bytes_per_unit = 3,
915 | .bits_per_char = 3,
916 | .table = {
917 | INVALID_INIT(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1),
918 | WHITESPACE_INIT[' '] = (-2), ['\t'] = (-2), ['\n'] = (-2), ['\v'] = (-2), ['\f' ] = (-2), ['\r'] = (-2),
919 | ['0'] = 0,1,2,3,4,5,6,7
920 | }
921 | };
922 |
923 | static const struct plain_decoding_data base64_decode_info = {
924 | .chars_per_unit = 4,
925 | .bytes_per_unit = 3,
926 | .bits_per_char = 6,
927 | .table = {
928 | INVALID_INIT(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), ( -1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (- 1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1 ), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1) , (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1),
929 | WHITESPACE_INIT[' '] = (-2), ['\t'] = (-2), ['\n'] = (-2), ['\v'] = (-2), ['\f' ] = (-2), ['\r'] = (-2),
930 | ['A'] = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
931 | ['a'] = 26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
932 | ['0'] = 52,53,54,55,56,57,58,59,60,61,
933 | ['+'] = 62,
934 | ['/'] = 63,
935 | ['='] = WHITESPACE_VALUE(-2) /* padding at the end, the decoder doesn't need this, so just ignores it */
936 | }
937 | };
938 |
939 | DIAG_ON_INIT_TWICEclang diagnostic pop
940 |
941 | /*******************************************************************************
942 | * The modularized part of this mess, used by the wrapper around the regex
943 | * engine in text_import_regex.c to hook into this state-machine backend.
944 | *
945 | * Should the rest be modularized as well? Maybe, but then start with pcap2text.c
946 | */
947 |
948 | /**
949 | * This function parses encoded data according to <encoding> into binary data.
950 | * It will continue until one of the following conditions is met:
951 | * - src is depleted
952 | * - dest cannot hold another full unit of data
953 | * - an invalid character is read
954 | * When this happens any complete bytes will be recovered from the remaining
955 | * possibly incomplete unit and stored to dest (there will be no incomplete unit
956 | * if dest is full). Any remaining bits will be discarded.
957 | * src and dest will be advanced to where parsing including this last incomplete
958 | * unit stopped.
959 | * If you want to continue parsing (meaning incomplete units were due to call
960 | * fragmentation and not actually due to EOT) you have to resume the parser at
961 | * *src_last_unit and dest - result % bytes_per_unit
962 | */
963 | static int parse_plain_data(unsigned char** src, const unsigned char* src_end,
964 | uint8_t** dest, const uint8_t* dest_end, const struct plain_decoding_data* encoding,
965 | unsigned char** src_last_unit) {
966 | int status = 1;
967 | int units = 0;
968 | /* unit buffer */
969 | uint64_t c_val = 0;
970 | unsigned c_chars = 0;
971 | /**
972 | * Src data |- - -|- - -|- - -|- - -|- - -|- - -|- - -|- - -|
973 | * Bytes |- - - - - - - -|- - - - - - - -|- - - - - - - -|
974 | * Units |- - - - - - - - - - - - - - - - - - - - - - - -|
975 | */
976 | uint64_t val;
977 | int j;
978 | if (ws_log_get_level() >= LOG_LEVEL_NOISY) {
979 | char* debug_str = wmem_strndup(NULL((void*)0), (const char*)*src, (src_end-*src));
980 | ws_noisy("parsing data: %s", debug_str)do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 980, __func__, "parsing data: %s", debug_str); } } while (0 );
981 | wmem_free(NULL((void*)0), debug_str);
982 | }
983 | while (*src < src_end && *dest + encoding->bytes_per_unit <= dest_end) {
984 | /*
985 | * XXX - This reads one octet at a time. If the GRegex compile flag
986 | * G_REGEX_RAW wasn't given, the match was done using UTF-8 characters.
987 | * That's useful, I suppose, if the input file has UTF-8 text (comments,
988 | * etc.) that ought to be ignored - but it means that character classes
989 | * like \d and \s can match Unicode characters that might (but probably
990 | * aren't) in the data. Those will cause an invalid value warning and
991 | * abort, which is easier than adding full UTF-8 support here.
992 | */
993 | val = encoding->table[**src];
994 | switch (val) {
995 | case INVALID_VALUE(-1):
996 | report_failure("Unexpected char %d in data", **src);
997 | status = -1;
998 | goto remainder;
999 | case WHITESPACE_VALUE(-2):
1000 | break;
1001 | default:
1002 | c_val = c_val << encoding->bits_per_char | val;
1003 | ++c_chars;
1004 | /* another full unit */
1005 | if (c_chars == encoding->chars_per_unit) {
1006 | ++units;
1007 | if (src_last_unit)
1008 | *src_last_unit = *src;
1009 | c_chars = 0;
1010 | for (j = encoding->bytes_per_unit; j > 0; --j) {
1011 | **dest = (char) (c_val >> (j * 8 - 8));
1012 | *dest += 1;
1013 | }
1014 | }
1015 | }
1016 | *src += 1;
1017 | }
1018 | remainder:
1019 | for (j = c_chars * encoding->bits_per_char; j >= 8; j -= 8) {
1020 | **dest = (char) (c_val >> (j - 8));
1021 | *dest += 1;
1022 | }
1023 | return status * units;
1024 | }
1025 |
1026 | void parse_data(unsigned char* start_field, unsigned char* end_field, enum data_encoding encoding) {
1027 | uint8_t* dest = &packet_buf[curr_offset];
1028 | uint8_t* dest_end = &packet_buf[info_p->max_frame_length];
1029 |
1030 | const struct plain_decoding_data* table; /* should be further down */
1031 | switch (encoding) {
1032 | case ENCODING_PLAIN_HEX:
1033 | case ENCODING_PLAIN_OCT:
1034 | case ENCODING_PLAIN_BIN:
1035 | case ENCODING_BASE64:
1036 | /* const struct plain_decoding_data* table; // This can't be here because gcc says no */
1037 | switch (encoding) {
1038 | case ENCODING_PLAIN_HEX:
1039 | table = &hex_decode_info;
1040 | break;
1041 | case ENCODING_PLAIN_OCT:
1042 | table = &oct_decode_info;
1043 | break;
1044 | case ENCODING_PLAIN_BIN:
1045 | table = &bin_decode_info;
1046 | break;
1047 | case ENCODING_BASE64:
1048 | table = &base64_decode_info;
1049 | break;
1050 | default:
1051 | return;
1052 | }
1053 | info_p->num_packets_read++;
1054 | while (1) {
1055 | parse_plain_data(&start_field, end_field, &dest, dest_end, table, NULL((void*)0));
1056 | curr_offset = (int) (dest - packet_buf);
1057 | if (curr_offset == info_p->max_frame_length) {
1058 | write_current_packet(true1);
1059 | dest = &packet_buf[curr_offset];
1060 | } else
1061 | break;
1062 | }
1063 | break;
1064 | default:
1065 | ws_critical("not implemented/invalid encoding type")do { if (1) { ws_log_full("Main", LOG_LEVEL_CRITICAL, "ui/text_import.c" , 1065, __func__, "not implemented/invalid encoding type"); } } while (0);
1066 | return;
1067 | }
1068 | }
1069 |
1070 | #define setFlags(VAL, MASK, FLAGS)((VAL) & ~(MASK)) | ((FLAGS) & (MASK)) \
1071 | ((VAL) & ~(MASK)) | ((FLAGS) & (MASK))
1072 |
1073 | static void _parse_dir(const unsigned char* start_field, const unsigned char* end_field _U___attribute__((unused)), const char* in_indicator, const char* out_indicator, uint32_t* dir) {
1074 |
1075 | for (; *in_indicator && *start_field != *in_indicator; ++in_indicator);
1076 | if (*in_indicator) {
1077 | *dir = setFlags(*dir, PACK_FLAGS_DIRECTION_MASK << PACK_FLAGS_DIRECTION_SHIFT, PACK_FLAGS_DIRECTION_INBOUND)((*dir) & ~(0x00000003 << 0)) | ((1) & (0x00000003 << 0));
1078 | return;
1079 | }
1080 | for (; *out_indicator && *start_field != *out_indicator; ++out_indicator);
1081 | if (*out_indicator) {
1082 | *dir = setFlags(*dir, PACK_FLAGS_DIRECTION_MASK << PACK_FLAGS_DIRECTION_SHIFT, PACK_FLAGS_DIRECTION_OUTBOUND)((*dir) & ~(0x00000003 << 0)) | ((2) & (0x00000003 << 0));
1083 | return;
1084 | }
1085 | *dir = setFlags(*dir, PACK_FLAGS_DIRECTION_MASK << PACK_FLAGS_DIRECTION_SHIFT, PACK_FLAGS_DIRECTION_UNKNOWN)((*dir) & ~(0x00000003 << 0)) | ((0) & (0x00000003 << 0));
1086 | }
1087 |
1088 | void parse_dir(const unsigned char* start_field, const unsigned char* end_field, const char* in_indicator, const char* out_indicator) {
1089 | _parse_dir(start_field, end_field, in_indicator, out_indicator, &direction);
1090 | }
1091 |
1092 | #define PARSE_BUF64 64
1093 |
1094 | /* Attempt to parse a time according to the given format. If the conversion
1095 | * succeeds, set sec and nsec appropriately and return true. If it fails,
1096 | * leave sec and nsec unchanged and return false.
1097 | */
1098 | static bool_Bool
1099 | _parse_time(const unsigned char* start_field, const unsigned char* end_field, const char* _format, time_t* sec, unsigned* nsec) {
1100 | struct tm timecode;
1101 | time_t sec_buf;
1102 | int nsec_buf = 0;
1103 |
1104 | char field[PARSE_BUF64];
1105 | char format[PARSE_BUF64];
1106 |
1107 | char* subsecs_fmt;
1108 | int subseclen = -1;
1109 |
1110 | char *cursor;
1111 | char *p;
1112 | int i;
1113 |
1114 | (void) g_strlcpy(field, (const char*)start_field, MIN(end_field - start_field + 1, PARSE_BUF)(((end_field - start_field + 1) < (64)) ? (end_field - start_field + 1) : (64)));
1115 | if (ts_fmt_iso) {
1116 | nstime_t ts_iso;
1117 | if (!iso8601_to_nstime(&ts_iso, field, ISO8601_DATETIME_AUTO)) {
1118 | return false0;
1119 | }
1120 | *sec = ts_iso.secs;
1121 | *nsec = (unsigned)ts_iso.nsecs;
1122 | } else {
1123 | (void) g_strlcpy(format, _format, PARSE_BUF64);
1124 |
1125 | /*
1126 | * Initialize to today, local time, just in case not all fields
1127 | * of the date and time are specified.
1128 | */
1129 | timecode = timecode_default;
1130 | cursor = &field[0];
1131 |
1132 | /*
1133 | * %f is for fractions of seconds not supported by strptime
1134 | */
1135 | subsecs_fmt = g_strrstr(format, "%f");
1136 | if (subsecs_fmt) {
1137 | *subsecs_fmt = 0;
1138 | }
1139 |
1140 | cursor = ws_strptime_p(cursor, format, &timecode);
1141 |
1142 | if (cursor == NULL((void*)0)) {
1143 | return false0;
1144 | }
1145 |
1146 | if (subsecs_fmt != NULL((void*)0)) {
1147 | /*
1148 | * Parse subsecs and any following format
1149 | */
1150 | nsec_buf = (unsigned) strtol(cursor, &p, 10);
1151 | if (p == cursor) {
1152 | return false0;
1153 | }
1154 |
1155 | subseclen = (int) (p - cursor);
1156 | cursor = p;
1157 | cursor = ws_strptime_p(cursor, subsecs_fmt + 2, &timecode);
1158 | if (cursor == NULL((void*)0)) {
1159 | return false0;
1160 | }
1161 | }
1162 |
1163 | if (subseclen > 0) {
1164 | /*
1165 | * Convert that number to a number
1166 | * of nanoseconds; if it's N digits
1167 | * long, it's in units of 10^(-N) seconds,
1168 | * so, to convert it to units of
1169 | * 10^-9 seconds, we multiply by
1170 | * 10^(9-N).
1171 | */
1172 | if (subseclen > SUBSEC_PREC9) {
1173 | /*
1174 | * *More* than 9 digits; 9-N is
1175 | * negative, so we divide by
1176 | * 10^(N-9).
1177 | */
1178 | for (i = subseclen - SUBSEC_PREC9; i != 0; i--)
1179 | nsec_buf /= 10;
1180 | } else if (subseclen < SUBSEC_PREC9) {
1181 | for (i = SUBSEC_PREC9 - subseclen; i != 0; i--)
1182 | nsec_buf *= 10;
1183 | }
1184 | }
1185 |
1186 | if ( -1 == (sec_buf = mktime(&timecode)) ) {
1187 | return false0;
1188 | }
1189 |
1190 | *sec = sec_buf;
1191 | *nsec = (unsigned)nsec_buf;
1192 | }
1193 |
1194 | ws_noisy("parsed time %s Format(%s), time(%ju), subsecs(%u)\n", field, _format, (uintmax_t)*sec, (uint32_t)*nsec)do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 1194, __func__, "parsed time %s Format(%s), time(%ju), subsecs(%u)\n" , field, _format, (uintmax_t)*sec, (uint32_t)*nsec); } } while (0);
1195 |
1196 | return true1;
1197 | }
1198 |
1199 | void parse_time(const unsigned char* start_field, const unsigned char* end_field, const char* format) {
1200 | if (format == NULL((void*)0) || !_parse_time(start_field, end_field, format, &ts_sec, &ts_nsec)) {
1201 | ts_nsec += ts_tick;
1202 | }
1203 | }
1204 |
1205 | void parse_seqno(const unsigned char* start_field, const unsigned char* end_field) {
1206 | /* Note the start and end are from g_match_info_fetch_named_pos(); the end
1207 | * position is the byte after the final byte of the match, so no adding 1.
1208 | */
1209 | if (!ws_buftou64(start_field, end_field - start_field, NULL((void*)0), &seqno)) {
1210 | const char* errstr = g_strerror(errno(*__errno_location ()));
1211 | report_warning("seqno parsing failed (%s)", errstr);
1212 | ws_warning("seqno parsing failed for input packet %d (%s).", info_p->num_packets_read, errstr)do { if (1) { ws_log_full("Main", LOG_LEVEL_WARNING, "ui/text_import.c" , 1212, __func__, "seqno parsing failed for input packet %d (%s)." , info_p->num_packets_read, errstr); } } while (0);
1213 | }
1214 | }
1215 |
1216 | void flush_packet(void) {
1217 | write_current_packet(false0);
1218 | }
1219 |
1220 | /*----------------------------------------------------------------------
1221 | * Parse the preamble to get the timecode.
1222 | */
1223 |
1224 | static void
1225 | parse_preamble (void)
1226 | {
1227 | int i;
1228 | bool_Bool got_time = false0;
1229 |
1230 | /*
1231 | * Null-terminate the preamble.
1232 | */
1233 | packet_preamble[packet_preamble_len] = '\0';
1234 |
1235 | if (has_direction) {
1236 | _parse_dir(&packet_preamble[0], &packet_preamble[1], "iI", "oO", &direction);
1237 | i = (direction == PACK_FLAGS_DIRECTION_UNKNOWN0) ? 0 : 1;
1238 | while (packet_preamble[i] == ' ' ||
1239 | packet_preamble[i] == '\r' ||
1240 | packet_preamble[i] == '\t') {
1241 | i++;
1242 | }
1243 | packet_preamble_len -= i;
1244 | /* Also move the trailing '\0'. */
1245 | memmove(packet_preamble, packet_preamble + i, packet_preamble_len + 1);
1246 | }
1247 |
1248 | /*
1249 | * If no time stamp format was specified, don't attempt to parse
1250 | * the packet preamble to extract a time stamp.
1251 | */
1252 |
1253 | /* Ensure preamble has more than two chars before attempting to parse.
1254 | * This should cover line breaks etc that get counted.
1255 | */
1256 | if ( info_p->timestamp_format != NULL((void*)0) && strlen((const char*)packet_preamble) > 2 ) {
1257 | got_time = _parse_time(packet_preamble, packet_preamble + strlen((const char*)packet_preamble), info_p->timestamp_format, &ts_sec, &ts_nsec);
1258 | if (!got_time) {
1259 | /* Let's only have a possible GUI popup once, other messages to log
1260 | */
1261 | if (!timecode_warned) {
1262 | report_warning("Time conversions (%s) failed, advancing time by %d ns from previous packet on failure. First failure was for %s on input packet %d.", info_p->timestamp_format, ts_tick, packet_preamble, info_p->num_packets_read);
1263 | timecode_warned = true1;
1264 | }
1265 | ws_warning("Time conversion (%s) failed for %s on input packet %d.", info_p->timestamp_format, packet_preamble, info_p->num_packets_read)do { if (1) { ws_log_full("Main", LOG_LEVEL_WARNING, "ui/text_import.c" , 1265, __func__, "Time conversion (%s) failed for %s on input packet %d." , info_p->timestamp_format, packet_preamble, info_p->num_packets_read ); } } while (0);
1266 | }
1267 | }
1268 | if (ws_log_get_level() >= LOG_LEVEL_NOISY) {
1269 | char *c;
1270 | while ((c = strchr((const char*)packet_preamble, '\r')) != NULL((void*)0)) *c=' ';
1271 | ws_noisy("[[parse_preamble: \"%s\"]]", packet_preamble)do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 1271, __func__, "[[parse_preamble: \"%s\"]]", packet_preamble ); } } while (0);
1272 | ws_noisy("Format(%s), time(%ju), subsecs(%u)", info_p->timestamp_format, (uintmax_t)ts_sec, ts_nsec)do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 1272, __func__, "Format(%s), time(%ju), subsecs(%u)", info_p ->timestamp_format, (uintmax_t)ts_sec, ts_nsec); } } while (0);
1273 | }
1274 |
1275 | if (!got_time) {
1276 | ts_nsec += ts_tick;
1277 | }
1278 |
1279 | /* Clear Preamble */
1280 | packet_preamble_len = 0;
1281 | }
1282 |
1283 | /*----------------------------------------------------------------------
1284 | * Start a new packet
1285 | *
1286 | * @param cont [IN] true if a new packet is starting because the max frame
1287 | * length was reached on the current packet, and the original packet from the
1288 | * input file is continued in a later frame. Passed to write_current_packet,
1289 | * where it is used to set fragmentation fields in dummy headers (currently
1290 | * only implemented for SCTP; IPv4 could be added later.)
1291 | */
1292 | static import_status_t
1293 | start_new_packet(bool_Bool cont)
1294 | {
1295 | ws_debug("Start new packet (cont = %s).", cont ? "true" : "false")do { if (1) { ws_log_full("Main", LOG_LEVEL_DEBUG, "ui/text_import.c" , 1295, __func__, "Start new packet (cont = %s).", cont ? "true" : "false"); } } while (0);
1296 |
1297 | /* Write out the current packet, if required */
1298 | if (write_current_packet(cont) != IMPORT_SUCCESS)
1299 | return IMPORT_FAILURE;
1300 | info_p->num_packets_read++;
1301 |
1302 | /* Ensure we parse the packet preamble as it may contain the time */
1303 | /* THIS IMPLIES A STATE TRANSITION OUTSIDE THE STATE MACHINE */
1304 | parse_preamble();
1305 |
1306 | return IMPORT_SUCCESS;
1307 | }
1308 |
1309 | /*----------------------------------------------------------------------
1310 | * Process a directive
1311 | */
1312 | static void
1313 | process_directive (char *str _U___attribute__((unused)))
1314 | {
1315 | char **tokens;
1316 | tokens = g_strsplit_set(str+10, "\r\n", 2);
12 | ← | Addition of a null pointer (from variable 'str') and a nonzero integer value results in undefined behavior
1317 | ws_message("--- Directive [%s] currently unsupported ---", tokens[0])do { if (1) { ws_log_full("Main", LOG_LEVEL_MESSAGE, ((void*) 0), -1, ((void*)0), "--- Directive [%s] currently unsupported ---" , tokens[0]); } } while (0);
1318 | g_strfreev(tokens);
1319 | }
1320 |
1321 | /*----------------------------------------------------------------------
1322 | * If this is a hex+ASCII dump, after finishing a line of packet bytes,
1323 | * test if the beginning of the hex portion would produce ASCII that
1324 | * would be treated as byte tokens (e.g., "61 62 20 ... ab "), and if so,
1325 | * look for the bytes and remove them from the output.
1326 | */
1327 | static void
1328 | process_rollback(bool_Bool by_eol)
1329 | {
1330 | int rollback = 0;
1331 | int pending_rollback = 0;
1332 | int line_size;
1333 | int i;
1334 | GString *s2;
1335 | char tmp_str[3];
1336 |
1337 | /* Here a line of pkt bytes reading is finished */
1338 | rollback = 0;
1339 | /* s2 is the ASCII string, s1 is the HEX string, e.g, when
1340 | s2 = "ab ", s1 = "616220"
1341 | we should find out the largest tail of s1 matches the head
1342 | of s2, it means the matched part in tail is the ASCII dump
1343 | of the head byte. Those matched should be rolled back. */
1344 | line_size = curr_offset-(int)(pkt_lnstart-packet_buf);
1345 | s2 = g_string_new(NULL((void*)0));
1346 | /* gather the possible pattern */
1347 | /* This is a simplified version of the lexical analysis done by the scanner
1348 | * and has to produce the same tokens. (Simpler because we only match bytes,
1349 | * space, and everything else.) Perhaps we should do lexical analysis with
1350 | * yy_scan_bytes. */
1351 | /* Note we have the bytes after any swapping of little endian byte groups
1352 | * has been done. That's what we want; various hexdump programs (hexdump,
1353 | * od, xxd) always output the ASCII dump in the natural order even if
1354 | * byte groups are little endian. */
1355 | i = 0;
1356 | while (i + 1 + rollback < line_size) {
1357 | if (pkt_lnstart[i] == ' ') {
1358 | /* Skip any spaces. We don't skip '\t', because in the ASCII dump
1359 | * those are converted to '.' and so wouldn't create extra byte
1360 | * tokens. */
1361 | i++;
1362 | continue;
1363 | }
1364 | tmp_str[0] = pkt_lnstart[i];
1365 | tmp_str[1] = pkt_lnstart[i+1];
1366 | tmp_str[2] = '\0';
1367 | /* it is a valid convertible string */
1368 | if (!g_ascii_isxdigit(tmp_str[0])((g_ascii_table[(guchar) (tmp_str[0])] & G_ASCII_XDIGIT) != 0) || !g_ascii_isxdigit(tmp_str[1])((g_ascii_table[(guchar) (tmp_str[1])] & G_ASCII_XDIGIT) != 0)) {
1369 | break;
1370 | }
1371 | g_string_append_c(s2, (char)strtoul(tmp_str, (char **)NULL, 16))g_string_append_c_inline (s2, (char)strtoul(tmp_str, (char ** )((void*)0), 16));
1372 | i += 2;
1373 | if (by_eol) {
1374 | rollback++;
1375 | } else {
1376 | pending_rollback++;
1377 | /* If we had a text token before EOL, then without ' ' after the
1378 | * byte it won't parse as a byte token in the ASCII dump.
1379 | * If we transitioned straight from T_BYTE to T_EOL, then we already
1380 | * know the entire ASCII dump parsed as bytes. */
1381 | if (!(i + rollback < line_size)) {
1382 | break;
1383 | }
1384 | if (pkt_lnstart[i] == ' ') {
1385 | rollback += pending_rollback;
1386 | pending_rollback = 0;
1387 | i++;
1388 | } else if (pending_rollback >= 4) {
1389 | break;
1390 | }
1391 | }
1392 | }
1393 | /* If the packet line start contains a possible byte pattern, the line end
1394 | should contain the matched pattern if the user gave the -a flag.
1395 | The line will be considered invalid if the byte pattern cannot find
1396 | a matched one in the line of packet buffer.
1397 |
1398 | XXX - We could instead do nothing (or warn) if the pattern isn't found.
1399 | That's probably better than dropping the entire line if the -a flag was
1400 | given despite there being no ASCII dump or if there is an ASCII dump but
1401 | separated by a delimiter like '|' that would prevent detecting it as
1402 | bytes. It's still better to avoid passing the flag if there is no ASCII
1403 | dump to avoid the extremely rare false detection where the actual bytes
1404 | look like a matching ASCII dump.
1405 | */
1406 | if (rollback > 0) {
1407 | if (strncmp((const char*)(pkt_lnstart+line_size-rollback), s2->str, rollback) == 0) {
1408 | unwrite_bytes(rollback);
1409 | } else {
1410 | /* Not matched. This line contains invalid packet bytes, so
1411 | discard the whole line */
1412 | /* The GUI only reports identical warnings once to save lots of pop-ups.
1413 | * Keep the unique information in a console message. */
1414 | report_warning("Expected ASCII rollback not found. Was ASCII identification enabled unnecessarily?");
1415 | ws_message("Expected %i byte%s to rollback at the end of line offset 0x%0X in packet %u.", rollback, plurality(rollback, "", "s"), curr_offset - line_size, info_p->num_packets_read)do { if (1) { ws_log_full("Main", LOG_LEVEL_MESSAGE, ((void*) 0), -1, ((void*)0), "Expected %i byte%s to rollback at the end of line offset 0x%0X in packet %u." , rollback, ((rollback) == 1 ? ("") : ("s")), curr_offset - line_size , info_p->num_packets_read); } } while (0);
1416 | unwrite_bytes(line_size);
1417 | }
1418 | }
1419 | g_string_free(s2, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (s2), ((!(0)))) : g_string_free_and_steal (s2)) : (g_string_free ) ((s2), ((!(0)))));
1420 | }
1421 |
1422 | /*----------------------------------------------------------------------
1423 | * Parse a single token (called from the scanner)
1424 | */
1425 | import_status_t
1426 | parse_token(token_t token, char *str)
1427 | {
1428 | uint32_t num;
1429 | char **tokens;
1430 |
1431 | /*
1432 | * This is implemented as a simple state machine of five states.
1433 | * State transitions are caused by tokens being received from the
1434 | * scanner. The code should be self_documenting.
1435 | */
1436 |
1437 | if (ws_log_get_level() >= LOG_LEVEL_NOISY) {
1 | Assuming the condition is true | →
2 | ← | Taking true branch | →
1438 | /* Sanitize - remove all '\r' */
1439 | char *c;
1440 | if (str!=NULL((void*)0)) { while ((c = strchr(str, '\r')) != NULL((void*)0)) *c=' '; }
3 | ← | Assuming 'str' is equal to NULL | →
4 | ← | Taking false branch | →
1441 |
1442 | ws_noisy("(%s, %s \"%s\") -> (",do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 1443, __func__, "(%s, %s \"%s\") -> (", state_str[state] , token_str[token], str ? str : ""); } } while (0)
5 | ← | Taking true branch | →
6 | ← | '?' condition is false | →
7 | ← | Loop condition is false. Exiting loop | →
1443 | state_str[state], token_str[token], str ? str : "")do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 1443, __func__, "(%s, %s \"%s\") -> (", state_str[state] , token_str[token], str ? str : ""); } } while (0);
1444 | }
1445 |
1446 | switch(state) {
8 | ← | Control jumps to 'case START_OF_LINE:' at line 1521 | →
1447 |
1448 | /* ----- Waiting for new packet -------------------------------------------*/
1449 | case INIT:
1450 | switch(token) {
1451 | case T_TEXT:
1452 | append_to_preamble(str);
1453 | break;
1454 | case T_DIRECTIVE:
1455 | process_directive(str);
1456 | break;
1457 | case T_OFFSET:
1458 | case T_BYTES:
1459 | if (offset_base == 0) {
1460 | append_to_preamble(str);
1461 | /* If we're still in the INIT state, maybe there's something
1462 | * odd like a time format with no separators. That wouldn't
1463 | * work in a mode with an offset, but give it a try.
1464 | */
1465 | tokens = g_strsplit_set(str, ": \t\r\n", 2);
1466 | if (!offset_warned) {
1467 | report_warning("Running in no offset mode but read offset (%s) at start of file, treating as preamble", tokens[0]);
1468 | offset_warned = true1;
1469 | }
1470 | ws_warning("Running in no offset mode but read offset (%s) at start of file, treating as preamble", tokens[0])do { if (1) { ws_log_full("Main", LOG_LEVEL_WARNING, "ui/text_import.c" , 1470, __func__, "Running in no offset mode but read offset (%s) at start of file, treating as preamble" , tokens[0]); } } while (0);
1471 | g_strfreev(tokens);
1472 | break;
1473 | }
1474 | if (parse_num(str, true1, &num) != IMPORT_SUCCESS)
1475 | return IMPORT_FAILURE;
1476 | if (num == 0) {
1477 | /* New packet starts here */
1478 | /* XXX - This could just be any other run of three or more
1479 | * zeros in a preamble. That only creates a problem if followed
1480 | * by something that looks like bytes (otherwise a zero length
1481 | * packet is ignored.)
1482 | */
1483 | if (start_new_packet(false0) != IMPORT_SUCCESS)
1484 | return IMPORT_FAILURE;
1485 | packet_start = 0;
1486 | state = READ_OFFSET;
1487 | pkt_lnstart = packet_buf + num;
1488 | } else {
1489 | /* Not a new packet; assume it's part of a preamble that
1490 | * looks like an offset token. (#17140)
1491 | */
1492 | append_to_preamble(str);
1493 | }
1494 | break;
1495 | case T_BYTE:
1496 | if (offset_base == 0) {
1497 | /* In no offset mode, assume this starts our packet */
1498 | if (start_new_packet(false0) != IMPORT_SUCCESS)
1499 | return IMPORT_FAILURE;
1500 | if (write_byte(str) != IMPORT_SUCCESS)
1501 | return IMPORT_FAILURE;
1502 | state = READ_BYTE;
1503 | pkt_lnstart = packet_buf;
1504 | break;
1505 | }
1506 | /* Otherwise, this is probably text that looks like a byte,
1507 | * e.g. a day or month with certain timestamp formats.
1508 | */
1509 | append_to_preamble(str);
1510 | break;
1511 | case T_EOF:
1512 | if (write_current_packet(false0) != IMPORT_SUCCESS)
1513 | return IMPORT_FAILURE;
1514 | break;
1515 | default:
1516 | break;
1517 | }
1518 | break;
1519 |
1520 | /* ----- Processing packet, start of new line -----------------------------*/
1521 | case START_OF_LINE:
1522 | switch(token) {
9 | ← | Control jumps to 'case T_DIRECTIVE:' at line 1534 | →
1523 | case T_TEXT:
1524 | /* If the only text allowed on the same line before an offset (other
1525 | * than the zero offset that begins a packet) were mailfwd ('>') and
1526 | * blanks, we could ignore those, and and switch back to INIT state
1527 | * here to decrease ambiguity. (That is, assume that other text at
1528 | * line start indicates the end of an old packet and start of new.)
1529 | */
1530 | if (offset_base != 0) {
1531 | append_to_preamble(str);
1532 | }
1533 | break;
1534 | case T_DIRECTIVE:
1535 | process_directive(str);
10 | ← | Passing null pointer value via 1st parameter 'str' | →
11 | ← | Calling 'process_directive' | →
1536 | break;
1537 | case T_OFFSET:
1538 | case T_BYTES:
1539 | if (offset_base == 0) {
1540 | /* After starting the packet there's no point adding it to
1541 | * the preamble in this mode (we only do one packet.)
1542 | * Use a generic warning message to suppress the many
1543 | * expected duplicates. */
1544 | tokens = g_strsplit_set(str, ": \t\r\n", 2);
1545 | if (!offset_warned) {
1546 | report_warning("Running in no offset mode but read offset (%s) at start of line, ignoring", tokens[0]);
1547 | offset_warned = true1;
1548 | }
1549 | ws_warning("Running in no offset mode but read offset (%s) at start of line, ignoring.", tokens[0])do { if (1) { ws_log_full("Main", LOG_LEVEL_WARNING, "ui/text_import.c" , 1549, __func__, "Running in no offset mode but read offset (%s) at start of line, ignoring." , tokens[0]); } } while (0);
1550 | g_strfreev(tokens);
1551 | break;
1552 | }
1553 | if (parse_num(str, true1, &num) != IMPORT_SUCCESS)
1554 | return IMPORT_FAILURE;
1555 | if (num == 0) {
1556 | /* New packet starts here */
1557 | /* XXX - This could just be any other run of three or more
1558 | * zeros in a preamble. That only creates a problem if followed
1559 | * by something that looks like bytes (otherwise a zero length
1560 | * packet is ignored.) */
1561 | if (start_new_packet(false0) != IMPORT_SUCCESS)
1562 | return IMPORT_FAILURE;
1563 | packet_start = 0;
1564 | state = READ_OFFSET;
1565 | } else if ((num - packet_start) != curr_offset) {
1566 | /*
1567 | * The offset we read isn't the one we expected.
1568 | * This may only mean that we mistakenly interpreted
1569 | * some text as byte values (e.g., if the text dump
1570 | * of packet data included a number with spaces around
1571 | * it). If the offset is less than what we expected,
1572 | * assume that's the problem, and throw away the putative
1573 | * extra byte values. (If identify_ascii is true, then
1574 | * process_rollback does something similar, except that
1575 | * it actually looks at the relevant bytes of the last
1576 | * line and works if the mistaken text is on the last
1577 | * line with an offset.)
1578 | *
1579 | * hexdump and od (but not xxd or tcpdump) print an extra
1580 | * offset with the total length followed by no bytes. This
1581 | * is necessary when those programs print multiple byte
1582 | * units instead of individual bytes. They will zero pad
1583 | * the last byte group, and the offset on the extra line
1584 | * is used to remove the excess null bytes. This also
1585 | * works for that case.
1586 | *
1587 | * In both of the above cases, the true offset should be
1588 | * between the previous line offset start and the current
1589 | * offset, as we only add bytes when a line started with
1590 | * the correct offset (except in no offset mode, where we
1591 | * don't get here.)
1592 | *
1593 | * XXX - It could be part of a preamble. There is a narrow
1594 | * window for false detection here, but it's possible if the
1595 | * line has, e.g., the packet length for the next packet.
1596 | */
1597 | if (num < curr_offset && (num >= (uint32_t)(pkt_lnstart - packet_buf))) {
1598 | unwrite_bytes(curr_offset - num);
1599 | state = READ_OFFSET;
1600 | } else {
1601 | /* Bad offset; switch to INIT state */
1602 | report_warning("Inconsistent offset. Ending current packet.");
1603 | ws_message("Inconsistent offset. Expecting %0X, got %0X. Ending current packet (%i).",do { if (1) { ws_log_full("Main", LOG_LEVEL_MESSAGE, ((void*) 0), -1, ((void*)0), "Inconsistent offset. Expecting %0X, got %0X. Ending current packet (%i)." , curr_offset, num, info_p->num_packets_read); } } while ( 0)
1604 | curr_offset, num, info_p->num_packets_read)do { if (1) { ws_log_full("Main", LOG_LEVEL_MESSAGE, ((void*) 0), -1, ((void*)0), "Inconsistent offset. Expecting %0X, got %0X. Ending current packet (%i)." , curr_offset, num, info_p->num_packets_read); } } while ( 0);
1605 | if (write_current_packet(false0) != IMPORT_SUCCESS)
1606 | return IMPORT_FAILURE;
1607 |
1608 | /* Instead of being an offset, it might be part of the preamble
1609 | * that looks like an offset, e.g. a year. (#17140)
1610 | */
1611 | append_to_preamble(str);
1612 | state = INIT;
1613 | }
1614 | } else {
1615 | /* Continues the previous packet at the correct offset */
1616 |
1617 | /* Clear Preamble (text in the middle of a packet isn't preamble) */
1618 | packet_preamble_len = 0;
1619 |
1620 | state = READ_OFFSET;
1621 | }
1622 | pkt_lnstart = packet_buf + num;
1623 | break;
1624 | case T_BYTE:
1625 | if (offset_base == 0) {
1626 | if (write_byte(str) != IMPORT_SUCCESS)
1627 | return IMPORT_FAILURE;
1628 | state = READ_BYTE;
1629 | pkt_lnstart = packet_buf;
1630 | break;
1631 | }
1632 | /* Since we expect an offset, assume this is text between packets
1633 | * that looks like a byte, e.g. a month or day.
1634 | */
1635 | append_to_preamble(str);
1636 | break;
1637 | case T_EOF:
1638 | if (write_current_packet(false0) != IMPORT_SUCCESS)
1639 | return IMPORT_FAILURE;
1640 | break;
1641 | default:
1642 | break;
1643 | }
1644 | break;
1645 |
1646 | /* ----- Processing packet, read offset -----------------------------------*/
1647 | case READ_OFFSET:
1648 | switch(token) {
1649 | case T_BYTE:
1650 | /* Record the byte */
1651 | state = READ_BYTE;
1652 | if (write_byte(str) != IMPORT_SUCCESS)
1653 | return IMPORT_FAILURE;
1654 | break;
1655 | case T_BYTES:
1656 | state = READ_BYTE;
1657 | if (write_bytes(str) != IMPORT_SUCCESS)
1658 | return IMPORT_FAILURE;
1659 | break;
1660 | case T_TEXT:
1661 | case T_DIRECTIVE:
1662 | case T_OFFSET:
1663 | state = READ_TEXT;
1664 | break;
1665 | case T_EOL:
1666 | state = START_OF_LINE;
1667 | break;
1668 | case T_EOF:
1669 | if (write_current_packet(false0) != IMPORT_SUCCESS)
1670 | return IMPORT_FAILURE;
1671 | break;
1672 | default:
1673 | break;
1674 | }
1675 | break;
1676 |
1677 | /* ----- Processing packet, read byte -------------------------------------*/
1678 | case READ_BYTE:
1679 | switch(token) {
1680 | case T_BYTE:
1681 | /* Record the byte */
1682 | if (write_byte(str) != IMPORT_SUCCESS)
1683 | return IMPORT_FAILURE;
1684 | break;
1685 | case T_BYTES:
1686 | if (write_bytes(str) != IMPORT_SUCCESS)
1687 | return IMPORT_FAILURE;
1688 | break;
1689 | case T_TEXT:
1690 | case T_DIRECTIVE:
1691 | case T_OFFSET:
1692 | state = READ_TEXT;
1693 | if (info_p->hexdump.identify_ascii) {
1694 | process_rollback(false0);
1695 | }
1696 | break;
1697 | case T_EOL:
1698 | state = START_OF_LINE;
1699 | if (info_p->hexdump.identify_ascii) {
1700 | process_rollback(true1);
1701 | }
1702 | break;
1703 | case T_EOF:
1704 | if (write_current_packet(false0) != IMPORT_SUCCESS)
1705 | return IMPORT_FAILURE;
1706 | break;
1707 | default:
1708 | break;
1709 | }
1710 | break;
1711 |
1712 | /* ----- Processing packet, read text -------------------------------------*/
1713 | case READ_TEXT:
1714 | switch(token) {
1715 | case T_EOL:
1716 | state = START_OF_LINE;
1717 | break;
1718 | case T_EOF:
1719 | if (write_current_packet(false0) != IMPORT_SUCCESS)
1720 | return IMPORT_FAILURE;
1721 | break;
1722 | default:
1723 | break;
1724 | }
1725 | break;
1726 |
1727 | default:
1728 | report_failure("FATAL ERROR: Bad state (%d)", state);
1729 | return IMPORT_FAILURE;
1730 | }
1731 |
1732 | ws_noisy(", %s)", state_str[state])do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "ui/text_import.c" , 1732, __func__, ", %s)", state_str[state]); } } while (0);
1733 |
1734 | return IMPORT_SUCCESS;
1735 | }
1736 |
1737 | /*----------------------------------------------------------------------
1738 | * Import a text file.
1739 | */
1740 | int
1741 | text_import(text_import_info_t * const info)
1742 | {
1743 | import_status_t status;
1744 | int ret;
1745 | struct tm *now_tm;
1746 |
1747 | /* Lets start from the beginning */
1748 | state = INIT;
1749 | curr_offset = 0;
1750 | packet_start = 0;
1751 | packet_preamble_len = 0;
1752 | direction = PACK_FLAGS_DIRECTION_UNKNOWN0;
1753 | ts_sec = time(0); /* initialize to current time */
1754 | now_tm = localtime(&ts_sec);
1755 | if (now_tm == NULL((void*)0)) {
1756 | /*
1757 | * This shouldn't happen - on UN*X, this should Just Work, and
1758 | * on 32 bit Windows built with 32 bit time_t, it won't work if ts_sec
1759 | * is before the Epoch, but it's long after 1970 (and even 32 bit
1760 | * Windows builds with 64 bit time_t by default now), so....
1761 | */
1762 | report_failure("localtime(right now) failed");
1763 | return WS_EXIT_INIT_FAILED8;
1764 | }
1765 | timecode_default = *now_tm;
1766 | timecode_default.tm_isdst = -1; /* Unknown for now, depends on time given to the strptime() function */
1767 | ts_nsec = 0;
1768 |
1769 | /* Get input parameters. */
1770 | info_p = info;
1771 |
1772 | if (info_p->max_frame_length > WTAP_MAX_PACKET_SIZE_STANDARD262144U) {
1773 | /* Our callers should guarantee this. */
1774 | report_failure("max frame length too large (%u > %u)", info_p->max_frame_length, WTAP_MAX_PACKET_SIZE_STANDARD262144U);
1775 | return WS_EXIT_INIT_FAILED8;
1776 | }
1777 |
1778 | /* Dummy headers */
1779 | hdr_ethernet = false0;
1780 | hdr_ip = false0;
1781 | hdr_udp = false0;
1782 | hdr_tcp = false0;
1783 | hdr_sctp = false0;
1784 | hdr_data_chunk = false0;
1785 | hdr_export_pdu = false0;
1786 |
1787 | if (info->mode == TEXT_IMPORT_HEXDUMP) {
1788 | switch (info->hexdump.offset_type)
1789 | {
1790 | case OFFSET_NONE:
1791 | offset_base = 0;
1792 | break;
1793 | case OFFSET_HEX:
1794 | offset_base = 16;
1795 | break;
1796 | case OFFSET_OCT:
1797 | offset_base = 8;
1798 | break;
1799 | case OFFSET_DEC:
1800 | offset_base = 10;
1801 | break;
1802 | }
1803 | has_direction = info->hexdump.has_direction;
1804 |
1805 | } else if (info->mode == TEXT_IMPORT_REGEX) {
1806 | has_direction = g_regex_get_string_number(info->regex.format, "dir") >= 0;
1807 | has_seqno = g_regex_get_string_number(info->regex.format, "seqno") >= 0;
1808 | }
1809 |
1810 | if (info->timestamp_format == NULL((void*)0) || g_ascii_strcasecmp(info->timestamp_format, "ISO")) {
1811 | ts_fmt_iso = false0;
1812 | } else {
1813 | ts_fmt_iso = true1;
1814 | }
1815 | offset_warned = false0;
1816 | timecode_warned = false0;
1817 |
1818 | /* XXX: It would be good to know the time precision of the file,
1819 | * to use for the time delta for packets without timestamps. (ts_tick)
1820 | * That could either be added to text_import_info_t or a method
1821 | * added to get it from wtap_dumper (which is opaque.)
1822 | */
1823 |
1824 | switch (info->dummy_header_type)
1825 | {
1826 | case HEADER_ETH:
1827 | hdr_ethernet = true1;
1828 | hdr_ethernet_proto = info->pid;
1829 | break;
1830 |
1831 | case HEADER_IPV4:
1832 | hdr_ip = true1;
1833 | hdr_ip_proto = info->protocol;
1834 | break;
1835 |
1836 | case HEADER_UDP:
1837 | hdr_udp = true1;
1838 | hdr_tcp = false0;
1839 | hdr_ip = true1;
1840 | hdr_ip_proto = 17;
1841 | break;
1842 |
1843 | case HEADER_TCP:
1844 | hdr_tcp = true1;
1845 | hdr_udp = false0;
1846 | hdr_ip = true1;
1847 | hdr_ip_proto = 6;
1848 | break;
1849 |
1850 | case HEADER_SCTP:
1851 | hdr_sctp = true1;
1852 | hdr_ip = true1;
1853 | hdr_ip_proto = 132;
1854 | break;
1855 |
1856 | case HEADER_SCTP_DATA:
1857 | hdr_sctp = true1;
1858 | hdr_data_chunk = true1;
1859 | hdr_ip = true1;
1860 | hdr_ip_proto = 132;
1861 | break;
1862 |
1863 | case HEADER_EXPORT_PDU:
1864 | hdr_export_pdu = true1;
1865 | break;
1866 |
1867 | default:
1868 | break;
1869 | }
1870 |
1871 | if (hdr_ip) {
1872 | if (info->ipv6) {
1873 | hdr_ipv6 = true1;
1874 | hdr_ip = false0;
1875 | hdr_ethernet_proto = 0x86DD;
1876 | } else {
1877 | hdr_ethernet_proto = 0x0800;
1878 | }
1879 |
1880 | switch (info->encapsulation) {
1881 |
1882 | case (WTAP_ENCAP_ETHERNET1):
1883 | hdr_ethernet = true1;
1884 | break;
1885 |
1886 | case (WTAP_ENCAP_RAW_IP7):
1887 | break;
1888 |
1889 | case (WTAP_ENCAP_RAW_IP4129):
1890 | if (info->ipv6) {
1891 | report_failure("Encapsulation %s only supports IPv4 headers, not IPv6", wtap_encap_name(info->encapsulation));
1892 | return WS_EXIT_INVALID_OPTION1;
1893 | }
1894 | break;
1895 |
1896 | case (WTAP_ENCAP_RAW_IP6130):
1897 | if (!info->ipv6) {
1898 | report_failure("Encapsulation %s only supports IPv6 headers, not IPv4", wtap_encap_name(info->encapsulation));
1899 | return WS_EXIT_INVALID_OPTION1;
1900 | }
1901 | break;
1902 |
1903 | default:
1904 | report_failure("Dummy IP header not supported with encapsulation: %s (%s)", wtap_encap_name(info->encapsulation), wtap_encap_description(info->encapsulation));
1905 | return WS_EXIT_INVALID_OPTION1;
1906 | }
1907 | }
1908 |
1909 | info->num_packets_read = 0;
1910 | info->num_packets_written = 0;
1911 |
1912 | packet_buf = (uint8_t *)g_malloc(WTAP_MAX_PACKET_SIZE_STANDARD262144U);
1913 |
1914 | ws_buffer_init(&prefix_buf, 2048);
1915 |
1916 | if (!packet_buf)
1917 | {
1918 | /* XXX: This doesn't happen, because g_malloc aborts the program on
1919 | * error, unlike malloc or g_try_malloc.
1920 | */
1921 | report_failure("FATAL ERROR: no memory for packet buffer");
1922 | return WS_EXIT_INIT_FAILED8;
1923 | }
1924 |
1925 | if (info->mode == TEXT_IMPORT_HEXDUMP) {
1926 | status = text_import_scan(info->hexdump.import_text_FILE);
1927 | switch(status) {
1928 | case (IMPORT_SUCCESS):
1929 | ret = 0;
1930 | break;
1931 | case (IMPORT_FAILURE):
1932 | ret = WS_EXIT_INVALID_FILE3;
1933 | break;
1934 | case (IMPORT_INIT_FAILED):
1935 | report_failure("Can't initialize scanner: %s", g_strerror(errno(*__errno_location ())));
1936 | ret = WS_EXIT_INIT_FAILED8;
1937 | break;
1938 | default:
1939 | ret = 0;
1940 | }
1941 | } else if (info->mode == TEXT_IMPORT_REGEX) {
1942 | ret = text_import_regex(info);
1943 | if (ret > 0) {
1944 | info->num_packets_read = ret;
1945 | ret = 0;
1946 | } else if (ret < 0) {
1947 | ret = WS_EXIT_INVALID_FILE3;
1948 | }
1949 | } else {
1950 | ret = WS_EXIT_INVALID_OPTION1;
1951 | }
1952 | g_free(packet_buf)(__builtin_object_size ((packet_buf), 0) != ((size_t) - 1)) ? g_free_sized (packet_buf, __builtin_object_size ((packet_buf ), 0)) : (g_free) (packet_buf);
1953 | ws_buffer_free(&prefix_buf);
1954 | return ret;
1955 | }
1956 |
1957 | /* Write the SHB and IDB to the wtap_dump_params before opening the wtap dump
1958 | * file. While dummy headers can be written automatically, this writes out
1959 | * some extra information including an optional interface name.
1960 | */
1961 | int
1962 | text_import_pre_open(wtap_dump_params * const params, int file_type_subtype, const char* const input_filename, const char* const interface_name)
1963 | {
1964 | wtap_block_t shb_hdr;
1965 | wtap_block_t int_data;
1966 | wtapng_if_descr_mandatory_t *int_data_mand;
1967 | char *comment;
1968 | GString *info_str;
1969 |
1970 | if (wtap_file_type_subtype_supports_block(file_type_subtype, WTAP_BLOCK_SECTION) != BLOCK_NOT_SUPPORTED &&
1971 | wtap_file_type_subtype_supports_option(file_type_subtype, WTAP_BLOCK_SECTION, OPT_COMMENT1) != OPTION_NOT_SUPPORTED) {
1972 |
1973 | shb_hdr = wtap_block_create(WTAP_BLOCK_SECTION);
1974 |
1975 | comment = ws_strdup_printf("Generated from input file %s.", input_filename)wmem_strdup_printf(((void*)0), "Generated from input file %s." , input_filename);
1976 | wtap_block_add_string_option(shb_hdr, OPT_COMMENT1, comment, strlen(comment));
1977 | g_free(comment)(__builtin_object_size ((comment), 0) != ((size_t) - 1)) ? g_free_sized (comment, __builtin_object_size ((comment), 0)) : (g_free) ( comment);
1978 |
1979 | info_str = g_string_new("");
1980 | get_cpu_info(info_str);
1981 | if (info_str->str) {
1982 | wtap_block_add_string_option(shb_hdr, OPT_SHB_HARDWARE2, info_str->str, info_str->len);
1983 | }
1984 | g_string_free(info_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (info_str), ((!(0)))) : g_string_free_and_steal (info_str)) : (g_string_free) ((info_str), ((!(0)))));
1985 |
1986 | info_str = g_string_new("");
1987 | get_os_version_info(info_str);
1988 | if (info_str->str) {
1989 | wtap_block_add_string_option(shb_hdr, OPT_SHB_OS3, info_str->str, info_str->len);
1990 | }
1991 | g_string_free(info_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (info_str), ((!(0)))) : g_string_free_and_steal (info_str)) : (g_string_free) ((info_str), ((!(0)))));
1992 |
1993 | wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL4, "%s", get_appname_and_version());
1994 |
1995 | params->shb_hdrs = g_array_new(false0, false0, sizeof(wtap_block_t));
1996 | g_array_append_val(params->shb_hdrs, shb_hdr)g_array_append_vals (params->shb_hdrs, &(shb_hdr), 1);
1997 | }
1998 |
1999 | /* wtap_dump_init_dumper() will create a interface block if the file type
2000 | * supports it and one isn't created already, but since we have the
2001 | * option of including the interface name, create it ourself.
2002 | *
2003 | * (XXX: IDBs should be optional for wtap_dump_init_dumper(), e.g. if
2004 | * the encap type is WTAP_ENCAP_SYSTEMD_JOURNAL, which doesn't use
2005 | * interfaces. But it's not, so always create it here.)
2006 | */
2007 | if (wtap_file_type_subtype_supports_block(file_type_subtype, WTAP_BLOCK_IF_ID_AND_INFO) != BLOCK_NOT_SUPPORTED) {
2008 | int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
2009 | int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
2010 |
2011 | int_data_mand->wtap_encap = params->encap;
2012 | int_data_mand->time_units_per_second = 1000000000;
2013 | int_data_mand->snap_len = params->snaplen;
2014 |
2015 | if (interface_name != NULL((void*)0)) {
2016 | wtap_block_add_string_option(int_data, OPT_IDB_NAME2, interface_name, strlen(interface_name));
2017 | } else {
2018 | wtap_block_add_string_option(int_data, OPT_IDB_NAME2, "Fake IF, text2pcap", strlen("Fake IF, text2pcap"));
2019 | }
2020 | if (params->tsprec >= 0 && params->tsprec <= WS_TSPREC_MAX9) {
2021 | /*
2022 | * This is a valid time precision.
2023 | */
2024 |
2025 | /*
2026 | * Compute 10^{params->tsprec}.
2027 | */
2028 | int_data_mand->time_units_per_second = 1;
2029 | for (int i = 0; i < params->tsprec; i++)
2030 | int_data_mand->time_units_per_second *= 10;
2031 |
2032 | if (params->tsprec != WTAP_TSPREC_USEC6) {
2033 | /*
2034 | * Microsecond precision is the default, so we only
2035 | * add an option if the precision isn't microsecond
2036 | * precision.
2037 | */
2038 | wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL9, params->tsprec);
2039 | }
2040 | } else {
2041 | /*
2042 | * Either WTAP_TSPREC_PER_PACKET, WTAP_TSPREC_UNKNOWN,
2043 | * or not a valid precision.
2044 | *
2045 | * Don't do this.
2046 | */
2047 | ws_assert_not_reached()ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "ui/text_import.c" , 2047, __func__, "assertion \"not reached\" failed");
2048 | }
2049 |
2050 | params->idb_inf = g_new(wtapng_iface_descriptions_t,1)((wtapng_iface_descriptions_t *) g_malloc_n ((1), sizeof (wtapng_iface_descriptions_t )));
2051 | params->idb_inf->interface_data = g_array_new(false0, false0, sizeof(wtap_block_t));
2052 | g_array_append_val(params->idb_inf->interface_data, int_data)g_array_append_vals (params->idb_inf->interface_data, & (int_data), 1);
2053 |
2054 | }
2055 |
2056 | return EXIT_SUCCESS0;
2057 | }