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

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-06-05-132759-3530-1 -x c /builds/wireshark/wireshark/ui/text_import.c
1/* text_import.c
2 * State machine for text import
3 * November 2010, Jaap Keuter <[email protected]>
4 * Modified March 2021, Paul Weiß <[email protected]>
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <[email protected]>
8 * Copyright 1998 Gerald Combs
9 *
10 * Based on text2pcap.c by Ashok Narayanan <[email protected]>
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
120static text_import_info_t *info_p;
121
122/* Dummy Ethernet header */
123static bool_Bool hdr_ethernet;
124static const uint8_t hdr_eth_dest_addr[6] = {0x20, 0x52, 0x45, 0x43, 0x56, 0x00};
125static const uint8_t hdr_eth_src_addr[6] = {0x20, 0x53, 0x45, 0x4E, 0x44, 0x00};
126static uint32_t hdr_ethernet_proto;
127
128/* Dummy IP header */
129static bool_Bool hdr_ip;
130static bool_Bool hdr_ipv6;
131static unsigned hdr_ip_proto;
132
133/* Destination and source addresses for IP header */
134static 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 */
138static const ws_in6_addr IPv6_SRC = {{0xfd, 0xce, 0xd8, 0x62, 0x14, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
139static 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 */
142static bool_Bool hdr_udp;
143
144/* Dummy TCP header */
145static bool_Bool hdr_tcp;
146
147/* TCP sequence numbers when has_direction is true */
148static uint32_t tcp_in_seq_num;
149static uint32_t tcp_out_seq_num;
150
151/* Dummy SCTP header */
152static bool_Bool hdr_sctp;
153
154/* Dummy DATA chunk header */
155static bool_Bool hdr_data_chunk;
156static uint8_t hdr_data_chunk_type;
157static uint8_t hdr_data_chunk_bits;
158static uint32_t hdr_data_chunk_tsn;
159static uint16_t hdr_data_chunk_sid;
160static uint16_t hdr_data_chunk_ssn;
161
162/* Dummy ExportPdu header */
163static 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. */
167static uint8_t* pkt_lnstart;
168
169static bool_Bool has_direction;
170static uint32_t direction = PACK_FLAGS_RECEPTION_TYPE_UNSPECIFIED0;
171static bool_Bool has_seqno;
172static uint64_t seqno;
173/*--- Local data -----------------------------------------------------------------*/
174
175/* This is where we store the packet currently being built */
176static uint8_t *packet_buf;
177static Buffer prefix_buf;
178static uint32_t curr_offset;
179static uint32_t packet_start;
180static bool_Bool offset_warned;
181static 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
185static uint8_t packet_preamble[PACKET_PREAMBLE_MAX_LEN2048+1];
186static int packet_preamble_len;
187
188/* Time code of packet, derived from packet_preamble */
189static time_t ts_sec;
190static uint32_t ts_nsec;
191static bool_Bool ts_fmt_iso;
192static struct tm timecode_default;
193static 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 */
200static uint32_t ts_tick = 1000;
201
202/* HDR_ETH Offset base to parse */
203static uint32_t offset_base = 16;
204
205/* ----- State machine -----------------------------------------------------------*/
206
207/* Current state of parser */
208typedef 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;
215static parser_state_t state = INIT;
216
217static const char * const state_str[] = {
218 "Init",
219 "Start-of-line",
220 "Offset",
221 "Byte",
222 "Text"
223};
224
225static 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
238typedef struct {
239 uint8_t dest_addr[6];
240 uint8_t src_addr[6];
241 uint16_t ethertype;
242} hdr_ethernet_t;
243
244static hdr_ethernet_t HDR_ETHERNET;
245
246typedef 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
271static hdr_ip_t HDR_IP =
272 {0x45, 0, 0, IP_ID0x3412, 0, 0, 0xff, 0, 0, IP_SRC0x0101010a, IP_DST0x0202020a};
273
274static 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
285typedef 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
299static hdr_ipv6_t HDR_IPv6;
300
301/* https://tools.ietf.org/html/rfc2460#section-8.1 */
302static 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
311typedef struct {
312 uint16_t source_port;
313 uint16_t dest_port;
314 uint16_t length;
315 uint16_t checksum;
316} hdr_udp_t;
317
318static hdr_udp_t HDR_UDP = {0, 0, 0, 0};
319
320typedef 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
332static hdr_tcp_t HDR_TCP = {0, 0, 0, 0, 0x50, 0, 0, 0, 0};
333
334typedef struct {
335 uint16_t src_port;
336 uint16_t dest_port;
337 uint32_t tag;
338 uint32_t checksum;
339} hdr_sctp_t;
340
341static hdr_sctp_t HDR_SCTP = {0, 0, 0, 0};
342
343typedef 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
353static hdr_data_chunk_t HDR_DATA_CHUNK = {0, 0, 0, 0, 0, 0, 0};
354
355typedef struct {
356 uint16_t tag_type;
357 uint16_t payload_len;
358} hdr_export_pdu_t;
359
360static 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 */
369static import_status_t
370parse_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 */
402static import_status_t
403write_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
419static import_status_t
420write_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 */
458static void
459unwrite_bytes (uint32_t nbytes)
460{
461 curr_offset -= nbytes;
462}
463
464/*----------------------------------------------------------------------
465 * Determine SCTP chunk padding length
466 */
467static uint32_t
468number_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 */
488static import_status_t
489write_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 */
796static import_status_t
797append_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 */
846struct 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 */
885DIAG_OFF_INIT_TWICEclang diagnostic push clang diagnostic ignored "-Winitializer-overrides"
886
887static 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
901static 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
912static 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
923static 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
939DIAG_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 */
963static 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 }
1018remainder:
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
1026void 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
1073static 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
1088void 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 */
1098static 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
1199void 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
1205void 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
1216void flush_packet(void) {
1217 write_current_packet(false0);
1218}
1219
1220/*----------------------------------------------------------------------
1221 * Parse the preamble to get the timecode.
1222 */
1223
1224static void
1225parse_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 */
1292static import_status_t
1293start_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 */
1312static void
1313process_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 */
1327static void
1328process_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 */
1425import_status_t
1426parse_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 */
1740int
1741text_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 */
1961int
1962text_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}