Bug Summary

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