2012-09-14 20:23:18 +00:00
/* text_import.c
* State machine for text import
* November 2010 , Jaap Keuter < jaap . keuter @ xs4all . nl >
2021-03-25 14:30:35 +00:00
* Modified March 2021 , Paul Weiß < paulniklasweiss @ gmail . com >
2012-09-14 20:23:18 +00:00
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
* Based on text2pcap . c by Ashok Narayanan < ashokn @ cisco . com >
*
2018-02-18 21:40:50 +00:00
* SPDX - License - Identifier : GPL - 2.0 - or - later
*/
2012-09-14 20:23:18 +00:00
/*******************************************************************************
*
2019-03-20 16:44:48 +00:00
* This code reads in an ASCII hexdump of this common format :
2012-09-14 20:23:18 +00:00
*
* 00000000 00 E0 1 E A7 05 6F 00 10 5 A A0 B9 12 08 00 46 00 . . . . . o . . Z . . . . . F .
* 00000010 03 68 00 00 00 00 0 A 2 E EE 33 0F 19 08 7F 0F 19 . h . . . . . . .3 . . . . . .
* 00000020 03 80 94 04 00 00 10 01 16 A2 0 A 00 03 50 00 0 C . . . . . . . . . . . . . P . .
* 00000030 01 01 0F 19 03 80 11 01 1 E 61 00 0 C 03 01 0F 19 . . . . . . . . . a . . . . . .
*
* Each bytestring line consists of an offset , one or more bytes , and
* text at the end . An offset is defined as a hex string of more than
* two characters . A byte is defined as a hex string of exactly two
* characters . The text at the end is ignored , as is any text before
* the offset . Bytes read from a bytestring line are added to the
* current packet only if all the following conditions are satisfied :
*
* - No text appears between the offset and the bytes ( any bytes appearing after
* such text would be ignored )
*
2019-01-20 18:35:19 +00:00
* - The offset must be arithmetically correct , i . e . if the offset is 00000020 ,
* then exactly 32 bytes must have been read into this packet before this .
* If the offset is wrong , the packet is immediately terminated
2012-09-14 20:23:18 +00:00
*
2019-01-20 18:35:19 +00:00
* A packet start is signaled by a zero offset .
2012-09-14 20:23:18 +00:00
*
* Lines starting with # TEXT2PCAP are directives . These allow the user
* to embed instructions into the capture file which allows text2pcap
* to take some actions ( e . g . specifying the encapsulation
* etc . ) . Currently no directives are implemented .
*
* Lines beginning with # which are not directives are ignored as
* comments . Currently all non - hexdump text is ignored by text2pcap ;
* in the future , text processing may be added , but lines prefixed
* with ' # ' will still be ignored .
*
* The output is a libpcap packet containing Ethernet frames by
* default . This program takes options which allow the user to add
2019-01-20 18:35:19 +00:00
* dummy Ethernet , IP and UDP , TCP or SCTP headers to the packets in order
2012-09-14 20:23:18 +00:00
* to allow dumps of L3 or higher protocols to be decoded .
*
* Considerable flexibility is built into this code to read hexdumps
* of slightly different formats . For example , any text prefixing the
* hexdump line is dropped ( including mail forwarding ' > ' ) . The offset
* can be any hex number of four digits or greater .
*
2018-12-06 16:36:43 +00:00
* This converter cannot read a single packet greater than
* WTAP_MAX_PACKET_SIZE_STANDARD . The snapshot length is automatically
* set to WTAP_MAX_PACKET_SIZE_STANDARD .
2012-09-14 20:23:18 +00:00
*/
2021-02-15 18:38:23 +00:00
/*******************************************************************************
* Alternatively this parses a Textfile based on a prel regex containing named
* capturing groups like so :
* ( ? < seqno > \ d + ) \ s * ( ? < dir > < | > ) \ s * ( ? < time > \ d + : \ d \ d : \ d \ d . \ d + ) \ s + ( ? < data > [ 0 - 9 a - fA - F ] + ) \ \ s +
*
* Fields are decoded using a leanient parser , but only one attempt is made .
* Except for in data invalid values will be replaced by default ones .
* data currently only accepts plain HEX , OCT or BIN encoded data .
* common field seperators are ignored . Note however that 0 x or 0 b prefixing is
* not supported and no automatic format detection is attempted .
*/
2012-09-20 01:48:30 +00:00
# include "config.h"
2021-10-16 09:33:34 +00:00
# include "text_import.h"
2012-09-14 20:23:18 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <wsutil/file_util.h>
# include <time.h>
# include <glib.h>
# include <errno.h>
# include <assert.h>
# include <epan/tvbuff.h>
# include <wsutil/crc32.h>
# include <epan/in_cksum.h>
2021-12-23 02:09:03 +00:00
# include <ui/exit_codes.h>
2021-12-23 04:43:45 +00:00
# include <wsutil/report_message.h>
2021-08-20 21:58:44 +00:00
# include <wsutil/exported_pdu_tlvs.h>
2021-12-23 16:19:35 +00:00
# include <wsutil/nstime.h>
2021-12-27 02:03:26 +00:00
# include <wsutil/time_util.h>
2012-09-14 20:23:18 +00:00
# include "text_import_scanner.h"
2016-03-31 01:44:01 +00:00
# include "text_import_scanner_lex.h"
2021-02-15 18:38:23 +00:00
# include "text_import_regex.h"
2012-09-14 20:23:18 +00:00
/*--- Options --------------------------------------------------------------------*/
2021-12-17 01:19:23 +00:00
/* maximum time precision we can handle = 10^(-SUBSEC_PREC) */
2021-02-15 18:38:23 +00:00
# define SUBSEC_PREC 9
# define debug_printf(level, ...) \
2021-12-25 18:39:12 +00:00
if ( info_p - > debug > = ( level ) ) { \
2021-02-15 18:38:23 +00:00
printf ( __VA_ARGS__ ) ; \
}
2021-12-24 12:39:13 +00:00
static text_import_info_t * info_p ;
2012-09-14 20:23:18 +00:00
/* Dummy Ethernet header */
2019-01-23 19:03:59 +00:00
static gboolean hdr_ethernet = FALSE ;
2019-03-11 00:29:50 +00:00
static guint8 hdr_eth_dest_addr [ 6 ] = { 0x20 , 0x52 , 0x45 , 0x43 , 0x56 , 0x00 } ;
static guint8 hdr_eth_src_addr [ 6 ] = { 0x20 , 0x53 , 0x45 , 0x4E , 0x44 , 0x00 } ;
2012-12-26 05:57:06 +00:00
static guint32 hdr_ethernet_proto = 0 ;
2012-09-14 20:23:18 +00:00
/* Dummy IP header */
2019-01-23 19:03:59 +00:00
static gboolean hdr_ip = FALSE ;
2021-12-22 04:43:19 +00:00
static gboolean hdr_ipv6 = FALSE ;
2014-11-19 16:25:17 +00:00
static guint hdr_ip_proto = 0 ;
2012-09-14 20:23:18 +00:00
2021-12-22 02:09:27 +00:00
/* Destination and source addresses for IP header */
2021-12-27 15:28:44 +00:00
/* XXX: Add default destination and source addresses for IPv6 when :: is
* passed in ? */
#if 0
2021-12-22 04:43:19 +00:00
static ws_in6_addr NO_IPv6_ADDRESS = { { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ;
2021-12-27 15:28:44 +00:00
# endif
2021-12-22 02:09:27 +00:00
2012-09-14 20:23:18 +00:00
/* Dummy UDP header */
2019-01-23 19:03:59 +00:00
static gboolean hdr_udp = FALSE ;
2012-09-14 20:23:18 +00:00
/* Dummy TCP header */
2019-01-23 19:03:59 +00:00
static gboolean hdr_tcp = FALSE ;
2012-09-14 20:23:18 +00:00
2019-03-11 00:29:50 +00:00
/* TCP sequence numbers when has_direction is true */
static guint32 tcp_in_seq_num = 0 ;
static guint32 tcp_out_seq_num = 0 ;
2012-09-14 20:23:18 +00:00
/* Dummy SCTP header */
2019-01-23 19:03:59 +00:00
static gboolean hdr_sctp = FALSE ;
2012-09-14 20:23:18 +00:00
/* Dummy DATA chunk header */
2019-01-23 19:03:59 +00:00
static gboolean hdr_data_chunk = FALSE ;
2012-12-26 05:57:06 +00:00
static guint8 hdr_data_chunk_type = 0 ;
2021-12-19 01:23:15 +00:00
static guint8 hdr_data_chunk_bits = 0 ;
2012-12-26 05:57:06 +00:00
static guint32 hdr_data_chunk_tsn = 0 ;
static guint16 hdr_data_chunk_sid = 0 ;
static guint16 hdr_data_chunk_ssn = 0 ;
2012-09-14 20:23:18 +00:00
2018-10-28 22:04:23 +00:00
/* Dummy ExportPdu header */
2019-01-23 19:03:59 +00:00
static gboolean hdr_export_pdu = FALSE ;
2018-10-28 22:04:23 +00:00
2021-12-23 01:01:42 +00:00
/* Hex+ASCII text dump identification, to handle an edge case where
* the ASCII representation contains patterns that look like bytes . */
static guint8 * pkt_lnstart ;
2013-04-02 12:15:42 +00:00
static gboolean has_direction = FALSE ;
2019-02-13 18:42:29 +00:00
static guint32 direction = PACK_FLAGS_RECEPTION_TYPE_UNSPECIFIED ;
2021-02-15 18:38:23 +00:00
static gboolean has_seqno = FALSE ;
static guint64 seqno = 0 ;
2012-09-14 20:23:18 +00:00
/*--- Local data -----------------------------------------------------------------*/
/* This is where we store the packet currently being built */
2012-12-26 05:57:06 +00:00
static guint8 * packet_buf ;
static guint32 curr_offset = 0 ;
static guint32 packet_start = 0 ;
2021-12-23 02:09:03 +00:00
static import_status_t start_new_packet ( gboolean ) ;
2012-09-14 20:23:18 +00:00
/* This buffer contains strings present before the packet offset 0 */
2012-10-24 15:52:08 +00:00
# define PACKET_PREAMBLE_MAX_LEN 2048
2012-12-26 05:57:06 +00:00
static guint8 packet_preamble [ PACKET_PREAMBLE_MAX_LEN + 1 ] ;
2012-09-14 20:23:18 +00:00
static int packet_preamble_len = 0 ;
/* Time code of packet, derived from packet_preamble */
2021-12-23 16:19:35 +00:00
static time_t ts_sec = 0 ;
static guint32 ts_nsec = 0 ;
static gboolean ts_fmt_iso = FALSE ;
2012-09-14 20:23:18 +00:00
static struct tm timecode_default ;
2021-12-23 02:09:03 +00:00
static gboolean timecode_warned = FALSE ;
2021-12-17 00:42:09 +00:00
/* The time delta to add to packets without a valid time code.
* This can be no smaller than the time resolution of the dump
* file , so the default is 1000 nanoseconds , or 1 microsecond .
* XXX : We should at least get this from the resolution of the file we ' re
* writing to , and possibly allow the user to set a different value .
*/
static guint32 ts_tick = 1000 ;
2012-09-14 20:23:18 +00:00
/* HDR_ETH Offset base to parse */
2012-12-26 05:57:06 +00:00
static guint32 offset_base = 16 ;
2012-09-14 20:23:18 +00:00
/* ----- State machine -----------------------------------------------------------*/
/* Current state of parser */
typedef enum {
INIT , /* Waiting for start of new packet */
START_OF_LINE , /* Starting from beginning of line */
READ_OFFSET , /* Just read the offset */
READ_BYTE , /* Just read a byte */
READ_TEXT /* Just read text - ignore until EOL */
} parser_state_t ;
static parser_state_t state = INIT ;
static const char * state_str [ ] = { " Init " ,
" Start-of-line " ,
" Offset " ,
" Byte " ,
" Text "
} ;
static const char * token_str [ ] = { " " ,
" Byte " ,
" Offset " ,
" Directive " ,
" Text " ,
" End-of-line "
} ;
/* ----- Skeleton Packet Headers --------------------------------------------------*/
typedef struct {
guint8 dest_addr [ 6 ] ;
guint8 src_addr [ 6 ] ;
guint16 l3pid ;
} hdr_ethernet_t ;
2019-03-11 00:29:50 +00:00
static hdr_ethernet_t HDR_ETHERNET ;
2012-09-14 20:23:18 +00:00
typedef struct {
guint8 ver_hdrlen ;
guint8 dscp ;
guint16 packet_length ;
guint16 identification ;
guint8 flags ;
guint8 fragment ;
guint8 ttl ;
guint8 protocol ;
guint16 hdr_checksum ;
guint32 src_addr ;
guint32 dest_addr ;
} hdr_ip_t ;
2021-12-28 15:59:03 +00:00
/* Default IPv4 addresses if none supplied */
2019-03-11 00:29:50 +00:00
# if G_BYTE_ORDER == G_BIG_ENDIAN
# define IP_ID 0x1234
2021-12-28 15:59:03 +00:00
# define IP_SRC 0x0a010101
# define IP_DST 0x0a020202
2019-03-11 00:29:50 +00:00
# else
# define IP_ID 0x3412
2021-12-28 15:59:03 +00:00
# define IP_SRC 0x0101010a
# define IP_DST 0x0202020a
2019-03-11 00:29:50 +00:00
# endif
2012-09-14 20:23:18 +00:00
static hdr_ip_t HDR_IP =
2019-03-11 00:29:50 +00:00
{ 0x45 , 0 , 0 , IP_ID , 0 , 0 , 0xff , 0 , 0 , IP_SRC , IP_DST } ;
2012-09-14 20:23:18 +00:00
static struct { /* pseudo header for checksum calculation */
guint32 src_addr ;
guint32 dest_addr ;
guint8 zero ;
guint8 protocol ;
guint16 length ;
} pseudoh ;
2021-12-22 04:43:19 +00:00
/* headers taken from glibc */
typedef struct {
union {
struct ip6_hdrctl {
guint32 ip6_un1_flow ; /* 24 bits of flow-ID */
guint16 ip6_un1_plen ; /* payload length */
guint8 ip6_un1_nxt ; /* next header */
guint8 ip6_un1_hlim ; /* hop limit */
} ip6_un1 ;
guint8 ip6_un2_vfc ; /* 4 bits version, 4 bits priority */
} ip6_ctlun ;
ws_in6_addr ip6_src ; /* source address */
ws_in6_addr ip6_dst ; /* destination address */
} hdr_ipv6_t ;
static hdr_ipv6_t HDR_IPv6 ;
/* https://tools.ietf.org/html/rfc2460#section-8.1 */
static struct { /* pseudo header ipv6 for checksum calculation */
struct e_in6_addr src_addr6 ;
struct e_in6_addr dst_addr6 ;
guint32 length ;
guint8 zero [ 3 ] ;
guint8 next_header ;
} pseudoh6 ;
2012-09-14 20:23:18 +00:00
typedef struct {
guint16 source_port ;
guint16 dest_port ;
guint16 length ;
guint16 checksum ;
} hdr_udp_t ;
static hdr_udp_t HDR_UDP = { 0 , 0 , 0 , 0 } ;
typedef struct {
guint16 source_port ;
guint16 dest_port ;
guint32 seq_num ;
guint32 ack_num ;
guint8 hdr_length ;
guint8 flags ;
guint16 window ;
guint16 checksum ;
guint16 urg ;
} hdr_tcp_t ;
static hdr_tcp_t HDR_TCP = { 0 , 0 , 0 , 0 , 0x50 , 0 , 0 , 0 , 0 } ;
typedef struct {
guint16 src_port ;
guint16 dest_port ;
guint32 tag ;
guint32 checksum ;
} hdr_sctp_t ;
static hdr_sctp_t HDR_SCTP = { 0 , 0 , 0 , 0 } ;
typedef struct {
guint8 type ;
guint8 bits ;
guint16 length ;
guint32 tsn ;
guint16 sid ;
guint16 ssn ;
guint32 ppid ;
} hdr_data_chunk_t ;
static hdr_data_chunk_t HDR_DATA_CHUNK = { 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2018-10-28 22:04:23 +00:00
typedef struct {
guint16 tag_type ;
guint16 payload_len ;
} hdr_export_pdu_t ;
static hdr_export_pdu_t HDR_EXPORT_PDU = { 0 , 0 } ;
# define EXPORT_PDU_END_OF_OPTIONS_SIZE 4
2012-09-14 20:23:18 +00:00
/*----------------------------------------------------------------------
* Parse a single hex number
* Will abort the program if it can ' t parse the number
* Pass in TRUE if this is an offset , FALSE if not
*/
2021-12-23 02:09:03 +00:00
static import_status_t
parse_num ( const char * str , int offset , guint32 * num )
2012-09-14 20:23:18 +00:00
{
char * c ;
2014-07-29 12:15:01 +00:00
if ( str = = NULL ) {
2021-12-23 02:09:03 +00:00
report_failure ( " FATAL ERROR: str is NULL " ) ;
return IMPORT_FAILURE ;
2014-07-29 12:15:01 +00:00
}
2021-12-23 02:09:03 +00:00
errno = 0 ;
2021-12-25 18:24:08 +00:00
unsigned long ulnum = strtoul ( str , & c , offset ? offset_base : 16 ) ;
2021-12-23 02:09:03 +00:00
if ( errno ! = 0 ) {
report_failure ( " Unable to convert %s to base %u: %s " , str ,
offset ? offset_base : 16 , g_strerror ( errno ) ) ;
return IMPORT_FAILURE ;
}
2019-03-20 16:44:48 +00:00
if ( c = = str ) {
2021-12-23 02:09:03 +00:00
report_failure ( " Unable to convert %s to base %u " , str ,
offset ? offset_base : 16 ) ;
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
}
2021-12-25 02:50:14 +00:00
if ( ulnum > G_MAXUINT32 ) {
report_failure ( " %s too large " , str ) ;
return IMPORT_FAILURE ;
}
* num = ( guint32 ) ulnum ;
2021-12-23 02:09:03 +00:00
return IMPORT_SUCCESS ;
2012-09-14 20:23:18 +00:00
}
/*----------------------------------------------------------------------
* Write this byte into current packet
*/
2021-12-23 02:09:03 +00:00
static import_status_t
write_byte ( const char * str )
2012-09-14 20:23:18 +00:00
{
2012-12-26 05:57:06 +00:00
guint32 num ;
2012-09-14 20:23:18 +00:00
2021-12-23 02:09:03 +00:00
if ( parse_num ( str , FALSE , & num ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2012-12-26 05:57:06 +00:00
packet_buf [ curr_offset ] = ( guint8 ) num ;
2021-12-23 02:09:03 +00:00
curr_offset + + ;
2021-12-24 12:39:13 +00:00
if ( curr_offset > = info_p - > max_frame_length ) /* packet full */
2021-12-23 02:09:03 +00:00
if ( start_new_packet ( TRUE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
return IMPORT_SUCCESS ;
2012-09-14 20:23:18 +00:00
}
/*----------------------------------------------------------------------
* Remove bytes from the current packet
*/
static void
2012-12-26 05:57:06 +00:00
unwrite_bytes ( guint32 nbytes )
2012-09-14 20:23:18 +00:00
{
curr_offset - = nbytes ;
}
/*----------------------------------------------------------------------
2019-01-20 18:35:19 +00:00
* Determine SCTP chunk padding length
2012-09-14 20:23:18 +00:00
*/
2012-12-26 05:57:06 +00:00
static guint32
number_of_padding_bytes ( guint32 length )
2012-09-14 20:23:18 +00:00
{
2012-12-26 05:57:06 +00:00
guint32 remainder ;
2012-09-14 20:23:18 +00:00
remainder = length % 4 ;
if ( remainder = = 0 )
return 0 ;
else
return 4 - remainder ;
}
/*----------------------------------------------------------------------
* Write current packet out
2021-12-19 01:23:15 +00:00
*
* @ param cont [ IN ] TRUE if a packet is being written because the max frame
* length was reached , and the original packet from the input file is
* continued in a later frame . Used to set fragmentation fields in dummy
* headers ( currently only implemented for SCTP ; IPv4 could be added later . )
2012-09-14 20:23:18 +00:00
*/
2021-12-23 02:09:03 +00:00
static import_status_t
2021-12-19 01:23:15 +00:00
write_current_packet ( gboolean cont )
2012-09-14 20:23:18 +00:00
{
int prefix_length = 0 ;
int proto_length = 0 ;
int ip_length = 0 ;
int eth_trailer_length = 0 ;
int prefix_index = 0 ;
int i , padding_length ;
if ( curr_offset > 0 ) {
/* Write the packet */
2019-03-11 00:29:50 +00:00
/* Is direction indication on with an inbound packet? */
gboolean isOutbound = has_direction & & ( direction = = PACK_FLAGS_DIRECTION_OUTBOUND ) ;
2012-09-14 20:23:18 +00:00
/* Compute packet length */
prefix_length = 0 ;
2018-10-28 22:04:23 +00:00
if ( hdr_export_pdu ) {
2021-12-24 12:39:13 +00:00
prefix_length + = ( int ) sizeof ( HDR_EXPORT_PDU ) + ( int ) strlen ( info_p - > payload ) + EXPORT_PDU_END_OF_OPTIONS_SIZE ;
2018-10-28 22:04:23 +00:00
proto_length = prefix_length + curr_offset ;
}
2012-12-26 05:57:06 +00:00
if ( hdr_data_chunk ) { prefix_length + = ( int ) sizeof ( HDR_DATA_CHUNK ) ; }
if ( hdr_sctp ) { prefix_length + = ( int ) sizeof ( HDR_SCTP ) ; }
if ( hdr_udp ) { prefix_length + = ( int ) sizeof ( HDR_UDP ) ; proto_length = prefix_length + curr_offset ; }
if ( hdr_tcp ) { prefix_length + = ( int ) sizeof ( HDR_TCP ) ; proto_length = prefix_length + curr_offset ; }
2012-09-14 20:23:18 +00:00
if ( hdr_ip ) {
2012-12-26 05:57:06 +00:00
prefix_length + = ( int ) sizeof ( HDR_IP ) ;
2012-09-14 20:23:18 +00:00
ip_length = prefix_length + curr_offset + ( ( hdr_data_chunk ) ? number_of_padding_bytes ( curr_offset ) : 0 ) ;
2021-12-22 04:43:19 +00:00
} else if ( hdr_ipv6 ) {
ip_length = prefix_length + curr_offset + ( ( hdr_data_chunk ) ? number_of_padding_bytes ( curr_offset ) : 0 ) ;
2021-12-22 19:05:34 +00:00
/* IPv6 payload length field does not include the header itself.
* It does include extension headers , but we don ' t put any
* ( if we later do fragments , that would change . )
*/
prefix_length + = ( int ) sizeof ( HDR_IPv6 ) ;
2012-09-14 20:23:18 +00:00
}
2012-12-26 05:57:06 +00:00
if ( hdr_ethernet ) { prefix_length + = ( int ) sizeof ( HDR_ETHERNET ) ; }
2012-09-14 20:23:18 +00:00
/* Make room for dummy header */
memmove ( & packet_buf [ prefix_length ] , packet_buf , curr_offset ) ;
if ( hdr_ethernet ) {
/* Pad trailer */
if ( prefix_length + curr_offset < 60 ) {
eth_trailer_length = 60 - ( prefix_length + curr_offset ) ;
}
}
/* Write Ethernet header */
if ( hdr_ethernet ) {
2019-03-11 00:29:50 +00:00
if ( isOutbound )
{
memcpy ( HDR_ETHERNET . dest_addr , hdr_eth_src_addr , 6 ) ;
memcpy ( HDR_ETHERNET . src_addr , hdr_eth_dest_addr , 6 ) ;
} else {
memcpy ( HDR_ETHERNET . dest_addr , hdr_eth_dest_addr , 6 ) ;
memcpy ( HDR_ETHERNET . src_addr , hdr_eth_src_addr , 6 ) ;
}
2012-09-14 20:23:18 +00:00
HDR_ETHERNET . l3pid = g_htons ( hdr_ethernet_proto ) ;
memcpy ( & packet_buf [ prefix_index ] , & HDR_ETHERNET , sizeof ( HDR_ETHERNET ) ) ;
2012-12-26 05:57:06 +00:00
prefix_index + = ( int ) sizeof ( HDR_ETHERNET ) ;
2012-09-14 20:23:18 +00:00
}
/* Write IP header */
if ( hdr_ip ) {
vec_t cksum_vector [ 1 ] ;
2019-03-11 00:29:50 +00:00
if ( isOutbound ) {
2021-12-24 12:39:13 +00:00
HDR_IP . src_addr = info_p - > ip_dest_addr . ipv4 ? info_p - > ip_dest_addr . ipv4 : IP_DST ;
HDR_IP . dest_addr = info_p - > ip_src_addr . ipv4 ? info_p - > ip_src_addr . ipv4 : IP_SRC ;
2021-12-22 02:09:27 +00:00
}
else {
2021-12-24 12:39:13 +00:00
HDR_IP . src_addr = info_p - > ip_src_addr . ipv4 ? info_p - > ip_src_addr . ipv4 : IP_SRC ;
HDR_IP . dest_addr = info_p - > ip_dest_addr . ipv4 ? info_p - > ip_dest_addr . ipv4 : IP_DST ;
2019-03-11 00:29:50 +00:00
}
2012-09-14 20:23:18 +00:00
HDR_IP . packet_length = g_htons ( ip_length ) ;
HDR_IP . protocol = ( guint8 ) hdr_ip_proto ;
HDR_IP . hdr_checksum = 0 ;
cksum_vector [ 0 ] . ptr = ( guint8 * ) & HDR_IP ; cksum_vector [ 0 ] . len = sizeof ( HDR_IP ) ;
HDR_IP . hdr_checksum = in_cksum ( cksum_vector , 1 ) ;
memcpy ( & packet_buf [ prefix_index ] , & HDR_IP , sizeof ( HDR_IP ) ) ;
2012-12-26 05:57:06 +00:00
prefix_index + = ( int ) sizeof ( HDR_IP ) ;
2012-09-14 20:23:18 +00:00
2021-12-22 04:43:19 +00:00
/* initialize pseudo header for checksum calculation */
pseudoh . src_addr = HDR_IP . src_addr ;
pseudoh . dest_addr = HDR_IP . dest_addr ;
pseudoh . zero = 0 ;
pseudoh . protocol = ( guint8 ) hdr_ip_proto ;
pseudoh . length = g_htons ( proto_length ) ;
} else if ( hdr_ipv6 ) {
2021-12-27 15:28:44 +00:00
if ( isOutbound ) {
memcpy ( & HDR_IPv6 . ip6_src , & info_p - > ip_dest_addr . ipv6 , sizeof ( ws_in6_addr ) ) ;
memcpy ( & HDR_IPv6 . ip6_dst , & info_p - > ip_src_addr . ipv6 , sizeof ( ws_in6_addr ) ) ;
} else {
memcpy ( & HDR_IPv6 . ip6_src , & info_p - > ip_src_addr . ipv6 , sizeof ( ws_in6_addr ) ) ;
memcpy ( & HDR_IPv6 . ip6_dst , & info_p - > ip_dest_addr . ipv6 , sizeof ( ws_in6_addr ) ) ;
}
2021-12-22 04:43:19 +00:00
HDR_IPv6 . ip6_ctlun . ip6_un2_vfc & = 0x0F ;
HDR_IPv6 . ip6_ctlun . ip6_un2_vfc | = ( 6 < < 4 ) ;
HDR_IPv6 . ip6_ctlun . ip6_un1 . ip6_un1_plen = g_htons ( ip_length ) ;
HDR_IPv6 . ip6_ctlun . ip6_un1 . ip6_un1_nxt = ( guint8 ) hdr_ip_proto ;
HDR_IPv6 . ip6_ctlun . ip6_un1 . ip6_un1_hlim = 32 ;
memcpy ( & packet_buf [ prefix_index ] , & HDR_IPv6 , sizeof ( HDR_IPv6 ) ) ;
prefix_index + = ( int ) sizeof ( HDR_IPv6 ) ;
/* initialize pseudo ipv6 header for checksum calculation */
pseudoh6 . src_addr6 = HDR_IPv6 . ip6_src ;
pseudoh6 . dst_addr6 = HDR_IPv6 . ip6_dst ;
memset ( pseudoh6 . zero , 0 , sizeof ( pseudoh6 . zero ) ) ;
pseudoh6 . next_header = ( guint8 ) hdr_ip_proto ;
pseudoh6 . length = g_htons ( proto_length ) ;
}
2012-09-14 20:23:18 +00:00
/* Write UDP header */
if ( hdr_udp ) {
vec_t cksum_vector [ 3 ] ;
2021-12-24 12:39:13 +00:00
HDR_UDP . source_port = isOutbound ? g_htons ( info_p - > dst_port ) : g_htons ( info_p - > src_port ) ;
HDR_UDP . dest_port = isOutbound ? g_htons ( info_p - > src_port ) : g_htons ( info_p - > dst_port ) ;
2012-09-14 20:23:18 +00:00
HDR_UDP . length = g_htons ( proto_length ) ;
HDR_UDP . checksum = 0 ;
2021-12-22 04:43:19 +00:00
if ( hdr_ipv6 ) {
cksum_vector [ 0 ] . ptr = ( guint8 * ) & pseudoh6 ; cksum_vector [ 0 ] . len = sizeof ( pseudoh6 ) ;
} else {
cksum_vector [ 0 ] . ptr = ( guint8 * ) & pseudoh ; cksum_vector [ 0 ] . len = sizeof ( pseudoh ) ;
}
2012-09-14 20:23:18 +00:00
cksum_vector [ 1 ] . ptr = ( guint8 * ) & HDR_UDP ; cksum_vector [ 1 ] . len = sizeof ( HDR_UDP ) ;
cksum_vector [ 2 ] . ptr = & packet_buf [ prefix_length ] ; cksum_vector [ 2 ] . len = curr_offset ;
HDR_UDP . checksum = in_cksum ( cksum_vector , 3 ) ;
memcpy ( & packet_buf [ prefix_index ] , & HDR_UDP , sizeof ( HDR_UDP ) ) ;
2012-12-26 05:57:06 +00:00
prefix_index + = ( int ) sizeof ( HDR_UDP ) ;
2012-09-14 20:23:18 +00:00
}
/* Write TCP header */
if ( hdr_tcp ) {
vec_t cksum_vector [ 3 ] ;
2021-12-24 12:39:13 +00:00
HDR_TCP . source_port = isOutbound ? g_htons ( info_p - > dst_port ) : g_htons ( info_p - > src_port ) ;
HDR_TCP . dest_port = isOutbound ? g_htons ( info_p - > src_port ) : g_htons ( info_p - > dst_port ) ;
2019-03-11 00:29:50 +00:00
/* set ack number if we have direction */
if ( has_direction ) {
HDR_TCP . flags = 0x10 ;
HDR_TCP . ack_num = g_ntohl ( isOutbound ? tcp_out_seq_num : tcp_in_seq_num ) ;
HDR_TCP . ack_num = g_htonl ( HDR_TCP . ack_num ) ;
}
else {
HDR_TCP . flags = 0 ;
HDR_TCP . ack_num = 0 ;
}
HDR_TCP . seq_num = isOutbound ? tcp_in_seq_num : tcp_out_seq_num ;
2012-09-14 20:23:18 +00:00
HDR_TCP . window = g_htons ( 0x2000 ) ;
HDR_TCP . checksum = 0 ;
2021-12-22 04:43:19 +00:00
if ( hdr_ipv6 ) {
cksum_vector [ 0 ] . ptr = ( guint8 * ) & pseudoh6 ; cksum_vector [ 0 ] . len = sizeof ( pseudoh6 ) ;
} else {
cksum_vector [ 0 ] . ptr = ( guint8 * ) & pseudoh ; cksum_vector [ 0 ] . len = sizeof ( pseudoh ) ;
}
2012-09-14 20:23:18 +00:00
cksum_vector [ 1 ] . ptr = ( guint8 * ) & HDR_TCP ; cksum_vector [ 1 ] . len = sizeof ( HDR_TCP ) ;
cksum_vector [ 2 ] . ptr = & packet_buf [ prefix_length ] ; cksum_vector [ 2 ] . len = curr_offset ;
HDR_TCP . checksum = in_cksum ( cksum_vector , 3 ) ;
memcpy ( & packet_buf [ prefix_index ] , & HDR_TCP , sizeof ( HDR_TCP ) ) ;
2012-12-26 05:57:06 +00:00
prefix_index + = ( int ) sizeof ( HDR_TCP ) ;
2019-03-11 00:29:50 +00:00
if ( isOutbound ) {
tcp_in_seq_num = g_ntohl ( tcp_in_seq_num ) + curr_offset ;
tcp_in_seq_num = g_htonl ( tcp_in_seq_num ) ;
}
else {
tcp_out_seq_num = g_ntohl ( tcp_out_seq_num ) + curr_offset ;
tcp_out_seq_num = g_htonl ( tcp_out_seq_num ) ;
}
2012-09-14 20:23:18 +00:00
}
/* Compute DATA chunk header and append padding */
if ( hdr_data_chunk ) {
2021-12-19 01:23:15 +00:00
hdr_data_chunk_bits = 0 ;
if ( packet_start = = 0 ) {
hdr_data_chunk_bits | = 0x02 ;
}
if ( ! cont ) {
hdr_data_chunk_bits | = 0x01 ;
}
2012-09-14 20:23:18 +00:00
HDR_DATA_CHUNK . type = hdr_data_chunk_type ;
HDR_DATA_CHUNK . bits = hdr_data_chunk_bits ;
HDR_DATA_CHUNK . length = g_htons ( curr_offset + sizeof ( HDR_DATA_CHUNK ) ) ;
HDR_DATA_CHUNK . tsn = g_htonl ( hdr_data_chunk_tsn ) ;
HDR_DATA_CHUNK . sid = g_htons ( hdr_data_chunk_sid ) ;
HDR_DATA_CHUNK . ssn = g_htons ( hdr_data_chunk_ssn ) ;
2021-12-24 12:39:13 +00:00
HDR_DATA_CHUNK . ppid = g_htonl ( info_p - > ppi ) ;
2021-12-19 01:23:15 +00:00
hdr_data_chunk_tsn + + ;
if ( ! cont ) {
hdr_data_chunk_ssn + + ;
}
2012-09-14 20:23:18 +00:00
padding_length = number_of_padding_bytes ( curr_offset ) ;
for ( i = 0 ; i < padding_length ; i + + )
packet_buf [ prefix_length + curr_offset + i ] = 0 ;
curr_offset + = padding_length ;
}
/* Write SCTP header */
if ( hdr_sctp ) {
2021-12-24 12:39:13 +00:00
HDR_SCTP . src_port = isOutbound ? g_htons ( info_p - > dst_port ) : g_htons ( info_p - > src_port ) ;
HDR_SCTP . dest_port = isOutbound ? g_htons ( info_p - > src_port ) : g_htons ( info_p - > dst_port ) ;
HDR_SCTP . tag = g_htonl ( info_p - > tag ) ;
2012-09-14 20:23:18 +00:00
HDR_SCTP . checksum = g_htonl ( 0 ) ;
HDR_SCTP . checksum = crc32c_calculate ( & HDR_SCTP , sizeof ( HDR_SCTP ) , CRC32C_PRELOAD ) ;
if ( hdr_data_chunk )
HDR_SCTP . checksum = crc32c_calculate ( & HDR_DATA_CHUNK , sizeof ( HDR_DATA_CHUNK ) , HDR_SCTP . checksum ) ;
HDR_SCTP . checksum = g_htonl ( ~ crc32c_calculate ( & packet_buf [ prefix_length ] , curr_offset , HDR_SCTP . checksum ) ) ;
memcpy ( & packet_buf [ prefix_index ] , & HDR_SCTP , sizeof ( HDR_SCTP ) ) ;
2012-12-26 05:57:06 +00:00
prefix_index + = ( int ) sizeof ( HDR_SCTP ) ;
2012-09-14 20:23:18 +00:00
}
/* Write DATA chunk header */
if ( hdr_data_chunk ) {
memcpy ( & packet_buf [ prefix_index ] , & HDR_DATA_CHUNK , sizeof ( HDR_DATA_CHUNK ) ) ;
2013-09-02 23:15:50 +00:00
/*prefix_index += (int)sizeof(HDR_DATA_CHUNK);*/
2012-09-14 20:23:18 +00:00
}
2018-10-28 22:04:23 +00:00
/* Write ExportPDU header */
if ( hdr_export_pdu ) {
2021-12-24 12:39:13 +00:00
guint payload_len = ( guint ) strlen ( info_p - > payload ) ;
2021-08-20 21:58:44 +00:00
HDR_EXPORT_PDU . tag_type = g_htons ( EXP_PDU_TAG_PROTO_NAME ) ;
2018-10-28 22:04:23 +00:00
HDR_EXPORT_PDU . payload_len = g_htons ( payload_len ) ;
memcpy ( & packet_buf [ prefix_index ] , & HDR_EXPORT_PDU , sizeof ( HDR_EXPORT_PDU ) ) ;
prefix_index + = sizeof ( HDR_EXPORT_PDU ) ;
2021-12-24 12:39:13 +00:00
memcpy ( & packet_buf [ prefix_index ] , info_p - > payload , payload_len ) ;
2018-10-31 14:38:00 +00:00
prefix_index + = payload_len ;
2018-10-28 22:04:23 +00:00
/* Add end-of-options tag */
memset ( & packet_buf [ prefix_index ] , 0x00 , 4 ) ;
}
2012-09-14 20:23:18 +00:00
/* Write Ethernet trailer */
if ( hdr_ethernet & & eth_trailer_length > 0 ) {
memset ( & packet_buf [ prefix_length + curr_offset ] , 0 , eth_trailer_length ) ;
}
2012-12-05 15:56:36 +00:00
HDR_TCP . seq_num = g_ntohl ( HDR_TCP . seq_num ) + curr_offset ;
HDR_TCP . seq_num = g_htonl ( HDR_TCP . seq_num ) ;
2012-09-14 20:23:18 +00:00
2021-12-23 04:43:45 +00:00
/* Write the packet */
wtap_rec rec ;
int err ;
gchar * err_info ;
memset ( & rec , 0 , sizeof rec ) ;
rec . rec_type = REC_TYPE_PACKET ;
rec . block = wtap_block_create ( WTAP_BLOCK_PACKET ) ;
rec . ts . secs = ts_sec ;
rec . ts . nsecs = ts_nsec ;
rec . rec_header . packet_header . caplen = rec . rec_header . packet_header . len = prefix_length + curr_offset + eth_trailer_length ;
2021-12-24 12:39:13 +00:00
rec . rec_header . packet_header . pkt_encap = info_p - > encapsulation ;
2021-12-23 04:43:45 +00:00
rec . presence_flags = WTAP_HAS_CAP_LEN | WTAP_HAS_INTERFACE_ID | WTAP_HAS_TS ;
if ( has_direction ) {
wtap_block_add_uint32_option ( rec . block , OPT_PKT_FLAGS , direction ) ;
}
if ( has_seqno ) {
wtap_block_add_uint64_option ( rec . block , OPT_PKT_PACKETID , seqno ) ;
}
2014-12-18 00:02:50 +00:00
2021-12-24 12:39:13 +00:00
if ( ! wtap_dump ( info_p - > wdh , & rec , packet_buf , & err , & err_info ) ) {
report_cfile_write_failure ( info_p - > import_text_filename ,
info_p - > output_filename , err , err_info ,
info_p - > num_packets_read ,
wtap_dump_file_type_subtype ( info_p - > wdh ) ) ;
2021-12-23 02:09:03 +00:00
wtap_block_unref ( rec . block ) ;
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
}
2021-12-23 04:43:45 +00:00
wtap_block_unref ( rec . block ) ;
2021-12-24 12:39:13 +00:00
info_p - > num_packets_written + + ;
2012-09-14 20:23:18 +00:00
}
packet_start + = curr_offset ;
curr_offset = 0 ;
2021-12-23 02:09:03 +00:00
return IMPORT_SUCCESS ;
2012-09-14 20:23:18 +00:00
}
/*----------------------------------------------------------------------
* Append a token to the packet preamble .
*/
2021-12-23 02:09:03 +00:00
static import_status_t
2012-09-14 20:23:18 +00:00
append_to_preamble ( char * str )
{
size_t toklen ;
if ( packet_preamble_len ! = 0 ) {
if ( packet_preamble_len = = PACKET_PREAMBLE_MAX_LEN )
2021-12-23 02:09:03 +00:00
return IMPORT_SUCCESS ; /* no room to add more preamble */
/* XXX: Just keep going? This is probably not a problem, unless
* someone had > 2000 bytes of whitespace before the timestamp . . . */
2012-09-14 20:23:18 +00:00
/* Add a blank separator between the previous token and this token. */
packet_preamble [ packet_preamble_len + + ] = ' ' ;
}
2015-12-03 18:31:55 +00:00
if ( str = = NULL ) {
2021-12-23 02:09:03 +00:00
report_failure ( " FATAL ERROR: str is NULL " ) ;
return IMPORT_FAILURE ;
2015-12-03 18:31:55 +00:00
}
2012-09-14 20:23:18 +00:00
toklen = strlen ( str ) ;
if ( toklen ! = 0 ) {
if ( packet_preamble_len + toklen > PACKET_PREAMBLE_MAX_LEN )
2021-12-23 02:09:03 +00:00
return IMPORT_SUCCESS ; /* no room to add token to the preamble */
/* XXX: Just keep going? This is probably not a problem, as above.*/
2021-04-30 10:18:25 +00:00
( void ) g_strlcpy ( & packet_preamble [ packet_preamble_len ] , str , PACKET_PREAMBLE_MAX_LEN ) ;
2012-09-14 20:23:18 +00:00
packet_preamble_len + = ( int ) toklen ;
2021-12-25 18:39:12 +00:00
if ( info_p - > debug > = 2 ) {
2012-09-14 20:23:18 +00:00
char * c ;
char xs [ PACKET_PREAMBLE_MAX_LEN ] ;
2021-04-30 10:18:25 +00:00
( void ) g_strlcpy ( xs , packet_preamble , PACKET_PREAMBLE_MAX_LEN ) ;
2012-09-14 20:23:18 +00:00
while ( ( c = strchr ( xs , ' \r ' ) ) ! = NULL ) * c = ' ' ;
fprintf ( stderr , " [[append_to_preamble: \" %s \" ]] " , xs ) ;
}
}
2021-12-23 02:09:03 +00:00
return IMPORT_SUCCESS ;
2012-09-14 20:23:18 +00:00
}
2021-02-15 18:38:23 +00:00
# define INVALID_VALUE (-1)
# define WHITESPACE_VALUE (-2)
/*
* Information on how to parse any plainly encoded binary data
*
* one Unit is least_common_mmultiple ( bits_per_char , 8 ) bits .
*/
struct plain_decoding_data {
const gchar * name ;
guint chars_per_unit ;
guint bytes_per_unit : 3 ; /* Internally a guint64 is used to hold units */
guint bits_per_char : 6 ;
gint8 table [ 256 ] ;
} ;
2021-03-25 14:30:35 +00:00
# define _INVALID_INIT2 INVALID_VALUE, INVALID_VALUE
# define _INVALID_INIT4 _INVALID_INIT2, _INVALID_INIT2
# define _INVALID_INIT8 _INVALID_INIT4, _INVALID_INIT4
# define _INVALID_INIT16 _INVALID_INIT8, _INVALID_INIT8
# define _INVALID_INIT32 _INVALID_INIT16, _INVALID_INIT16
# define _INVALID_INIT64 _INVALID_INIT32, _INVALID_INIT32
# define _INVALID_INIT128 _INVALID_INIT64, _INVALID_INIT64
2021-03-27 20:18:34 +00:00
# define _INVALID_INIT256 _INVALID_INIT128, _INVALID_INIT128
2021-03-25 14:30:35 +00:00
2021-03-27 20:18:34 +00:00
# define INVALID_INIT _INVALID_INIT256
// this is a gcc/clang extension:
// [0 ... 255] = INVALID_VALUE
2021-02-15 18:38:23 +00:00
# define WHITESPACE_INIT \
2021-03-27 20:18:34 +00:00
[ ' ' ] = WHITESPACE_VALUE , \
2021-02-15 18:38:23 +00:00
[ ' \t ' ] = WHITESPACE_VALUE , \
[ ' \n ' ] = WHITESPACE_VALUE , \
[ ' \v ' ] = WHITESPACE_VALUE , \
[ ' \f ' ] = WHITESPACE_VALUE , \
[ ' \r ' ] = WHITESPACE_VALUE
2021-03-27 20:18:34 +00:00
/*
* Some compilers warn about initializing the same subobject
* more than once with designated initializers .
*
* We ' re doing that - INVALID_INIT iniitalizes everything to
* INVALID_VALUE , but then we override selected elements -
* but we know what we ' re doing , so just suppress that
* warning .
*/
DIAG_OFF_INIT_TWICE
2021-02-15 18:38:23 +00:00
const struct plain_decoding_data hex_decode_info = {
. chars_per_unit = 2 ,
. bytes_per_unit = 1 ,
. bits_per_char = 4 ,
. table = {
INVALID_INIT ,
WHITESPACE_INIT ,
2021-03-27 20:18:34 +00:00
[ ' : ' ] = WHITESPACE_VALUE ,
[ ' 0 ' ] = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ,
[ ' A ' ] = 10 , 11 , 12 , 13 , 14 , 15 ,
[ ' a ' ] = 10 , 11 , 12 , 13 , 14 , 15
2021-02-15 18:38:23 +00:00
}
} ;
const struct plain_decoding_data bin_decode_info = {
. chars_per_unit = 8 ,
. bytes_per_unit = 1 ,
. bits_per_char = 1 ,
. table = {
INVALID_INIT ,
WHITESPACE_INIT ,
2021-03-27 20:18:34 +00:00
[ ' 0 ' ] = 0 , 1
2021-02-15 18:38:23 +00:00
}
} ;
const struct plain_decoding_data oct_decode_info = {
. chars_per_unit = 8 ,
. bytes_per_unit = 3 ,
. bits_per_char = 3 ,
. table = {
INVALID_INIT ,
WHITESPACE_INIT ,
2021-03-27 20:18:34 +00:00
[ ' 0 ' ] = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7
2021-02-15 18:38:23 +00:00
}
} ;
const struct plain_decoding_data base64_decode_info = {
. chars_per_unit = 4 ,
. bytes_per_unit = 3 ,
. bits_per_char = 6 ,
. table = {
INVALID_INIT ,
WHITESPACE_INIT ,
[ ' 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 ,
[ ' 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 ,
[ ' 0 ' ] = 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 ,
[ ' + ' ] = 62 ,
[ ' / ' ] = 63 ,
[ ' = ' ] = WHITESPACE_VALUE /* padding at the end, the decoder doesn't need this, so just ignores it */
}
} ;
2021-03-27 20:18:34 +00:00
DIAG_ON_INIT_TWICE
2021-02-15 18:38:23 +00:00
/*******************************************************************************
* The modularized part of this mess , used by the wrapper around the regex
* engine in text_import_regex . c to hook into this state - machine backend .
*
* Should the rest be modularized aswell ? Maybe , but then start with pcap2text . c
*/
/**
* This function parses encoded data according to < encoding > into binary data .
* It will continue until one of the following conditions is met :
* - src is depletetd
* - dest cannot hold another full unit of data
* - an invalid character is read
* When this happens any complete bytes will be recovered from the remaining
* possibly incomplete unit and stored to dest ( there will be no incomplete unit
* if dest is full ) . Any remaining bits will be discarded .
* src and dest will be advanced to where parsing including this last incomplete
* unit stopped .
* If you want to continue parsing ( meaning incomplete units were due to call
* fragmentation and not actually due to EOT ) you have to resume the parser at
* * src_last_unit and dest - result % bytes_per_unit
*/
static int parse_plain_data ( guchar * * src , const guchar * src_end ,
guint8 * * dest , const guint8 * dest_end , const struct plain_decoding_data * encoding ,
guchar * * src_last_unit ) {
int status = 1 ;
int units = 0 ;
/* unit buffer */
guint64 c_val = 0 ;
guint c_chars = 0 ;
/**
* Src data | - - - | - - - | - - - | - - - | - - - | - - - | - - - | - - - |
* Bytes | - - - - - - - - | - - - - - - - - | - - - - - - - - |
* Units | - - - - - - - - - - - - - - - - - - - - - - - - |
*/
guint64 val ;
int j ;
debug_printf ( 3 , " parsing data: " ) ;
while ( * src < src_end & & * dest + encoding - > bytes_per_unit < = dest_end ) {
debug_printf ( 3 , " %c " , * * src ) ;
val = encoding - > table [ * * src ] ;
switch ( val ) {
case INVALID_VALUE :
status = - 1 ;
goto remainder ;
case WHITESPACE_VALUE :
fprintf ( stderr , " Unexpected char %d in data \n " , * * src ) ;
break ;
default :
c_val = c_val < < encoding - > bits_per_char | val ;
+ + c_chars ;
/* another full unit */
if ( c_chars = = encoding - > chars_per_unit ) {
+ + units ;
if ( src_last_unit )
* src_last_unit = * src ;
c_chars = 0 ;
for ( j = encoding - > bytes_per_unit ; j > 0 ; - - j ) {
* * dest = ( gchar ) ( c_val > > ( j * 8 - 8 ) ) ;
* dest + = 1 ;
}
}
}
* src + = 1 ;
}
remainder :
for ( j = c_chars * encoding - > bits_per_char ; j > = 8 ; j - = 8 ) {
* * dest = ( gchar ) ( c_val > > ( j - 8 ) ) ;
* dest + = 1 ;
}
debug_printf ( 3 , " \n " ) ;
return status * units ;
}
void parse_data ( guchar * start_field , guchar * end_field , enum data_encoding encoding ) {
guint8 * dest = & packet_buf [ curr_offset ] ;
2021-12-24 12:39:13 +00:00
guint8 * dest_end = & packet_buf [ info_p - > max_frame_length ] ;
2021-02-15 18:38:23 +00:00
const struct plain_decoding_data * table ; /* should be further down */
switch ( encoding ) {
case ENCODING_PLAIN_HEX :
case ENCODING_PLAIN_OCT :
case ENCODING_PLAIN_BIN :
case ENCODING_BASE64 :
/* const struct plain_decoding_data* table; // This can't be here because gcc says no */
switch ( encoding ) {
case ENCODING_PLAIN_HEX :
table = & hex_decode_info ;
break ;
case ENCODING_PLAIN_OCT :
table = & oct_decode_info ;
break ;
case ENCODING_PLAIN_BIN :
table = & bin_decode_info ;
break ;
case ENCODING_BASE64 :
table = & base64_decode_info ;
break ;
default :
return ;
}
2021-12-24 12:39:13 +00:00
info_p - > num_packets_read + + ;
2021-02-15 18:38:23 +00:00
while ( 1 ) {
parse_plain_data ( & start_field , end_field , & dest , dest_end , table , NULL ) ;
curr_offset = ( int ) ( dest - packet_buf ) ;
2021-12-24 12:39:13 +00:00
if ( curr_offset = = info_p - > max_frame_length ) {
2021-12-19 01:23:15 +00:00
write_current_packet ( TRUE ) ;
2021-02-15 18:38:23 +00:00
dest = & packet_buf [ curr_offset ] ;
} else
break ;
}
break ;
default :
fprintf ( stderr , " not implemented/invalid encoding type \n " ) ;
return ;
}
}
# define setFlags(VAL, MASK, FLAGS) \
( ( VAL ) & ~ ( MASK ) ) | ( ( FLAGS ) & ( MASK ) )
2021-03-25 14:30:35 +00:00
static void _parse_dir ( const guchar * start_field , const guchar * end_field _U_ , const gchar * in_indicator , const gchar * out_indicator , guint32 * dir ) {
2021-02-15 18:38:23 +00:00
for ( ; * in_indicator & & * start_field ! = * in_indicator ; + + in_indicator ) ;
if ( * in_indicator ) {
* dir = setFlags ( * dir , PACK_FLAGS_DIRECTION_MASK < < PACK_FLAGS_DIRECTION_SHIFT , PACK_FLAGS_DIRECTION_INBOUND ) ;
return ;
}
for ( ; * out_indicator & & * start_field ! = * out_indicator ; + + out_indicator ) ;
if ( * out_indicator ) {
* dir = setFlags ( * dir , PACK_FLAGS_DIRECTION_MASK < < PACK_FLAGS_DIRECTION_SHIFT , PACK_FLAGS_DIRECTION_OUTBOUND ) ;
return ;
}
* dir = setFlags ( * dir , PACK_FLAGS_DIRECTION_MASK < < PACK_FLAGS_DIRECTION_SHIFT , PACK_FLAGS_DIRECTION_UNKNOWN ) ;
}
void parse_dir ( const guchar * start_field , const guchar * end_field , const gchar * in_indicator , const gchar * out_indicator ) {
_parse_dir ( start_field , end_field , in_indicator , out_indicator , & direction ) ;
}
# define PARSE_BUF 64
2021-12-17 00:42:09 +00:00
/* Attempt to parse a time according to the given format. If the conversion
* succeeds , set sec and nsec appropriately and return TRUE . If it fails ,
* leave sec and nsec unchanged and return FALSE .
*/
static gboolean
_parse_time ( const guchar * start_field , const guchar * end_field , const gchar * _format , time_t * sec , gint * nsec ) {
2021-02-15 18:38:23 +00:00
struct tm timecode ;
time_t sec_buf ;
2021-12-17 00:42:09 +00:00
gint nsec_buf = 0 ;
2021-02-15 18:38:23 +00:00
char field [ PARSE_BUF ] ;
char format [ PARSE_BUF ] ;
char * subsecs_fmt ;
int subseclen = - 1 ;
char * cursor ;
char * p ;
int i ;
2021-04-30 10:18:25 +00:00
( void ) g_strlcpy ( field , start_field , MIN ( end_field - start_field + 1 , PARSE_BUF ) ) ;
2021-12-23 16:19:35 +00:00
if ( ts_fmt_iso ) {
nstime_t ts_iso ;
if ( ! iso8601_to_nstime ( & ts_iso , field , ISO8601_DATETIME_AUTO ) ) {
return FALSE ;
}
* sec = ts_iso . secs ;
* nsec = ts_iso . nsecs ;
} else {
( void ) g_strlcpy ( format , _format , PARSE_BUF ) ;
2021-02-15 18:38:23 +00:00
2021-12-23 16:19:35 +00:00
/*
* Initialize to today localtime , just in case not all fields
* of the date and time are specified .
*/
timecode = timecode_default ;
cursor = & field [ 0 ] ;
2021-12-17 00:42:09 +00:00
2021-02-15 18:38:23 +00:00
/*
2021-12-23 16:19:35 +00:00
* % f is for fractions of seconds not supported by strptime
* BTW : what is this function name ? is this some russian joke ?
2021-02-15 18:38:23 +00:00
*/
2021-12-23 16:19:35 +00:00
subsecs_fmt = g_strrstr ( format , " %f " ) ;
if ( subsecs_fmt ) {
* subsecs_fmt = 0 ;
2021-12-17 00:42:09 +00:00
}
2021-12-27 02:03:26 +00:00
cursor = ws_strptime ( cursor , format , & timecode ) ;
2021-12-23 16:19:35 +00:00
2021-12-17 00:42:09 +00:00
if ( cursor = = NULL ) {
return FALSE ;
2021-02-15 18:38:23 +00:00
}
2021-12-23 16:19:35 +00:00
if ( subsecs_fmt ! = NULL ) {
2021-02-15 18:38:23 +00:00
/*
2021-12-23 16:19:35 +00:00
* Parse subsecs and any following format
2021-02-15 18:38:23 +00:00
*/
2021-12-23 16:19:35 +00:00
nsec_buf = ( guint ) strtol ( cursor , & p , 10 ) ;
if ( p = = cursor ) {
return FALSE ;
}
subseclen = ( int ) ( p - cursor ) ;
cursor = p ;
2021-12-27 02:03:26 +00:00
cursor = ws_strptime ( cursor , subsecs_fmt + 2 , & timecode ) ;
2021-12-23 16:19:35 +00:00
if ( cursor = = NULL ) {
return FALSE ;
}
2021-02-15 18:38:23 +00:00
}
2021-12-23 16:19:35 +00:00
if ( subseclen > 0 ) {
/*
* Convert that number to a number
* of nanoseconds ; if it ' s N digits
* long , it ' s in units of 10 ^ ( - N ) seconds ,
* so , to convert it to units of
* 10 ^ - 9 seconds , we multiply by
* 10 ^ ( 9 - N ) .
*/
if ( subseclen > SUBSEC_PREC ) {
/*
* * More * than 9 digits ; 9 - N is
* negative , so we divide by
* 10 ^ ( N - 9 ) .
*/
for ( i = subseclen - SUBSEC_PREC ; i ! = 0 ; i - - )
nsec_buf / = 10 ;
} else if ( subseclen < SUBSEC_PREC ) {
for ( i = SUBSEC_PREC - subseclen ; i ! = 0 ; i - - )
nsec_buf * = 10 ;
}
}
if ( - 1 = = ( sec_buf = mktime ( & timecode ) ) ) {
return FALSE ;
}
2021-12-17 00:42:09 +00:00
2021-12-23 16:19:35 +00:00
* sec = sec_buf ;
* nsec = nsec_buf ;
}
2021-12-17 00:42:09 +00:00
2021-02-15 18:38:23 +00:00
debug_printf ( 3 , " parsed time %s Format(%s), time(%u), subsecs(%u) \n " , field , _format , ( guint32 ) * sec , ( guint32 ) * nsec ) ;
2021-12-17 00:42:09 +00:00
return TRUE ;
2021-02-15 18:38:23 +00:00
}
void parse_time ( const guchar * start_field , const guchar * end_field , const gchar * format ) {
2021-12-17 00:42:09 +00:00
if ( format = = NULL | | ! _parse_time ( start_field , end_field , format , & ts_sec , & ts_nsec ) ) {
ts_nsec + = ts_tick ;
}
2021-02-15 18:38:23 +00:00
}
void parse_seqno ( const guchar * start_field , const guchar * end_field ) {
char * buf = ( char * ) g_alloca ( end_field - start_field + 1 ) ;
2021-04-30 10:18:25 +00:00
( void ) g_strlcpy ( buf , start_field , end_field - start_field + 1 ) ;
2021-02-15 18:38:23 +00:00
seqno = g_ascii_strtoull ( buf , NULL , 10 ) ;
}
void flush_packet ( void ) {
2021-12-19 01:23:15 +00:00
write_current_packet ( FALSE ) ;
2021-02-15 18:38:23 +00:00
}
2012-09-14 20:23:18 +00:00
/*----------------------------------------------------------------------
* Parse the preamble to get the timecode .
*/
static void
parse_preamble ( void )
{
2012-10-24 15:52:08 +00:00
int i ;
2021-12-17 00:42:09 +00:00
gboolean got_time = FALSE ;
2012-10-24 15:52:08 +00:00
2013-04-02 12:15:42 +00:00
/*
* Null - terminate the preamble .
*/
packet_preamble [ packet_preamble_len ] = ' \0 ' ;
if ( has_direction ) {
2021-02-15 18:38:23 +00:00
_parse_dir ( & packet_preamble [ 0 ] , & packet_preamble [ 1 ] , " iI " , " oO " , & direction ) ;
2021-12-17 23:40:29 +00:00
i = ( direction = = PACK_FLAGS_DIRECTION_UNKNOWN ) ? 0 : 1 ;
2013-04-02 12:15:42 +00:00
while ( packet_preamble [ i ] = = ' ' | |
packet_preamble [ i ] = = ' \r ' | |
packet_preamble [ i ] = = ' \t ' ) {
i + + ;
}
packet_preamble_len - = i ;
2013-04-05 09:56:11 +00:00
/* Also move the trailing '\0'. */
memmove ( packet_preamble , packet_preamble + i , packet_preamble_len + 1 ) ;
2013-04-02 12:15:42 +00:00
}
2012-10-24 15:52:08 +00:00
/*
2019-03-20 16:44:48 +00:00
* If no time stamp format was specified , don ' t attempt to parse
* the packet preamble to extract a time stamp .
2012-10-24 15:52:08 +00:00
*/
2013-12-23 15:53:13 +00:00
/* Ensure preamble has more than two chars before attempting to parse.
2012-10-24 15:52:08 +00:00
* This should cover line breaks etc that get counted .
*/
2021-12-25 00:54:35 +00:00
if ( info_p - > timestamp_format ! = NULL & & strlen ( packet_preamble ) > 2 ) {
got_time = _parse_time ( packet_preamble , packet_preamble + strlen ( packet_preamble ) , info_p - > timestamp_format , & ts_sec , & ts_nsec ) ;
2021-12-23 02:09:03 +00:00
if ( ! got_time ) {
/* Let's only have a possible GUI popup once, other messages to log
*/
if ( ! timecode_warned ) {
2021-12-25 00:54:35 +00:00
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 ) ;
2021-12-23 02:09:03 +00:00
timecode_warned = TRUE ;
}
2021-12-25 00:54:35 +00:00
ws_warning ( " Time conversion (%s) failed for %s on input packet %d. " , info_p - > timestamp_format , packet_preamble , info_p - > num_packets_read ) ;
2021-12-23 02:09:03 +00:00
}
2012-10-24 15:52:08 +00:00
}
2021-12-25 18:39:12 +00:00
if ( info_p - > debug > = 2 ) {
2012-10-24 15:52:08 +00:00
char * c ;
while ( ( c = strchr ( packet_preamble , ' \r ' ) ) ! = NULL ) * c = ' ' ;
fprintf ( stderr , " [[parse_preamble: \" %s \" ]] \n " , packet_preamble ) ;
2021-12-25 00:54:35 +00:00
fprintf ( stderr , " Format(%s), time(%u), subsecs(%u) \n " , info_p - > timestamp_format , ( guint32 ) ts_sec , ts_nsec ) ;
2012-10-24 15:52:08 +00:00
}
2021-12-17 00:42:09 +00:00
if ( ! got_time ) {
ts_nsec + = ts_tick ;
}
2021-12-23 02:09:03 +00:00
/* Clear Preamble */
packet_preamble_len = 0 ;
2012-09-14 20:23:18 +00:00
}
/*----------------------------------------------------------------------
* Start a new packet
2021-12-19 01:23:15 +00:00
*
* @ param cont [ IN ] TRUE if a new packet is starting because the max frame
* length was reached on the current packet , and the original packet from the
* input file is continued in a later frame . Passed to write_current_packet ,
* where it is used to set fragmentation fields in dummy headers ( currently
* only implemented for SCTP ; IPv4 could be added later . )
2012-09-14 20:23:18 +00:00
*/
2021-12-23 02:09:03 +00:00
static import_status_t
2021-12-19 01:23:15 +00:00
start_new_packet ( gboolean cont )
2012-09-14 20:23:18 +00:00
{
2021-12-25 18:39:12 +00:00
if ( info_p - > debug > = 1 )
2021-12-19 01:23:15 +00:00
fprintf ( stderr , " Start new packet (cont = %s). \n " , cont ? " TRUE " : " FALSE " ) ;
2012-09-14 20:23:18 +00:00
/* Write out the current packet, if required */
2021-12-23 02:09:03 +00:00
if ( write_current_packet ( cont ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2021-12-24 12:39:13 +00:00
info_p - > num_packets_read + + ;
2012-09-14 20:23:18 +00:00
/* Ensure we parse the packet preamble as it may contain the time */
2021-12-17 00:42:09 +00:00
/* THIS IMPLIES A STATE TRANSITION OUTSIDE THE STATE MACHINE */
2012-09-14 20:23:18 +00:00
parse_preamble ( ) ;
2021-12-23 02:09:03 +00:00
return IMPORT_SUCCESS ;
2012-09-14 20:23:18 +00:00
}
/*----------------------------------------------------------------------
* Process a directive
*/
static void
process_directive ( char * str )
{
fprintf ( stderr , " \n --- Directive [%s] currently unsupported --- \n " , str + 10 ) ;
}
/*----------------------------------------------------------------------
* Parse a single token ( called from the scanner )
*/
2021-12-23 02:09:03 +00:00
import_status_t
parse_token ( token_t token , char * str )
2012-09-14 20:23:18 +00:00
{
2012-12-26 05:57:06 +00:00
guint32 num ;
2021-12-23 01:01:42 +00:00
/* Variables for the hex+ASCII identification / lookback */
int by_eol ;
int rollback = 0 ;
int line_size ;
int i ;
char * s2 ;
char tmp_str [ 3 ] ;
2012-09-14 20:23:18 +00:00
/*
* This is implemented as a simple state machine of five states .
* State transitions are caused by tokens being received from the
* scanner . The code should be self_documenting .
*/
2021-12-25 18:39:12 +00:00
if ( info_p - > debug > = 2 ) {
2012-09-14 20:23:18 +00:00
/* Sanitize - remove all '\r' */
char * c ;
if ( str ! = NULL ) { while ( ( c = strchr ( str , ' \r ' ) ) ! = NULL ) * c = ' ' ; }
fprintf ( stderr , " (%s, %s \" %s \" ) -> ( " ,
state_str [ state ] , token_str [ token ] , str ? str : " " ) ;
}
switch ( state ) {
/* ----- Waiting for new packet -------------------------------------------*/
case INIT :
switch ( token ) {
case T_TEXT :
append_to_preamble ( str ) ;
break ;
case T_DIRECTIVE :
process_directive ( str ) ;
break ;
case T_OFFSET :
2021-12-25 13:35:08 +00:00
if ( offset_base = = 0 ) {
append_to_preamble ( str ) ;
/* If we're still in the INIT state, maybe there's something
* odd like a time format with no separators . That wouldn ' t
* work in a mode with an offset , but give it a try .
*/
report_warning ( " Running in no offset mode but read offset (%s) at start of file, treating as preamble " , str ) ;
break ;
}
2021-12-23 02:09:03 +00:00
if ( parse_num ( str , TRUE , & num ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2021-12-19 01:23:15 +00:00
if ( num = = 0 ) {
2012-09-14 20:23:18 +00:00
/* New packet starts here */
2021-12-23 02:09:03 +00:00
if ( start_new_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
state = READ_OFFSET ;
2021-12-23 01:01:42 +00:00
pkt_lnstart = packet_buf + num ;
2012-09-14 20:23:18 +00:00
}
break ;
2016-06-05 19:06:51 +00:00
case T_BYTE :
if ( offset_base = = 0 ) {
2021-12-23 02:09:03 +00:00
if ( start_new_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
if ( write_byte ( str ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2016-06-05 19:06:51 +00:00
state = READ_BYTE ;
2021-12-23 01:01:42 +00:00
pkt_lnstart = packet_buf ;
2016-06-05 19:06:51 +00:00
}
break ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
case T_EOF :
2021-12-23 02:09:03 +00:00
if ( write_current_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
break ;
2012-09-14 20:23:18 +00:00
default :
break ;
}
break ;
/* ----- Processing packet, start of new line -----------------------------*/
case START_OF_LINE :
switch ( token ) {
case T_TEXT :
append_to_preamble ( str ) ;
break ;
case T_DIRECTIVE :
process_directive ( str ) ;
break ;
case T_OFFSET :
2021-12-25 13:35:08 +00:00
if ( offset_base = = 0 ) {
/* After starting the packet there's no point adding it to
* the preamble in this mode ( we only do one packet . )
* Use a generic warning message to suppress the many
* expected duplicates . */
report_warning ( " Running in no offset mode but read offset, ignoring " ) ;
break ;
}
2021-12-23 02:09:03 +00:00
if ( parse_num ( str , TRUE , & num ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2021-12-19 01:23:15 +00:00
if ( num = = 0 ) {
2012-09-14 20:23:18 +00:00
/* New packet starts here */
2021-12-23 02:09:03 +00:00
if ( start_new_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
packet_start = 0 ;
state = READ_OFFSET ;
} else if ( ( num - packet_start ) ! = curr_offset ) {
/*
* The offset we read isn ' t the one we expected .
* This may only mean that we mistakenly interpreted
* some text as byte values ( e . g . , if the text dump
* of packet data included a number with spaces around
* it ) . If the offset is less than what we expected ,
* assume that ' s the problem , and throw away the putative
* extra byte values .
*/
if ( num < curr_offset ) {
unwrite_bytes ( curr_offset - num ) ;
state = READ_OFFSET ;
} else {
/* Bad offset; switch to INIT state */
2021-12-25 18:39:12 +00:00
if ( info_p - > debug > = 1 )
2012-12-26 05:57:06 +00:00
fprintf ( stderr , " Inconsistent offset. Expecting %0X, got %0X. Ignoring rest of packet \n " ,
2012-09-14 20:23:18 +00:00
curr_offset , num ) ;
2021-12-23 02:09:03 +00:00
if ( write_current_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
state = INIT ;
}
2021-12-23 01:01:42 +00:00
} else {
2012-09-14 20:23:18 +00:00
state = READ_OFFSET ;
2021-12-23 01:01:42 +00:00
}
pkt_lnstart = packet_buf + num ;
2012-09-14 20:23:18 +00:00
break ;
2016-06-13 08:00:28 +00:00
case T_BYTE :
if ( offset_base = = 0 ) {
2021-12-23 02:09:03 +00:00
if ( write_byte ( str ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2016-06-13 08:00:28 +00:00
state = READ_BYTE ;
2021-12-23 01:01:42 +00:00
pkt_lnstart = packet_buf ;
2016-06-13 08:00:28 +00:00
}
break ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
case T_EOF :
2021-12-23 02:09:03 +00:00
if ( write_current_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
break ;
2012-09-14 20:23:18 +00:00
default :
break ;
}
break ;
/* ----- Processing packet, read offset -----------------------------------*/
case READ_OFFSET :
switch ( token ) {
case T_BYTE :
/* Record the byte */
state = READ_BYTE ;
2021-12-23 02:09:03 +00:00
if ( write_byte ( str ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
break ;
case T_TEXT :
case T_DIRECTIVE :
case T_OFFSET :
state = READ_TEXT ;
break ;
case T_EOL :
state = START_OF_LINE ;
break ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
case T_EOF :
2021-12-23 02:09:03 +00:00
if ( write_current_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
break ;
2012-09-14 20:23:18 +00:00
default :
break ;
}
break ;
/* ----- Processing packet, read byte -------------------------------------*/
case READ_BYTE :
switch ( token ) {
case T_BYTE :
/* Record the byte */
2021-12-23 02:09:03 +00:00
if ( write_byte ( str ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
break ;
case T_TEXT :
case T_DIRECTIVE :
case T_OFFSET :
case T_EOL :
2021-12-23 01:01:42 +00:00
by_eol = 0 ;
state = READ_TEXT ;
if ( token = = T_EOL ) {
by_eol = 1 ;
state = START_OF_LINE ;
}
2021-12-26 22:40:59 +00:00
if ( info_p - > hexdump . identify_ascii ) {
2021-12-23 01:01:42 +00:00
/* Here a line of pkt bytes reading is finished
compare the ascii and hex to avoid such situation :
" 61 62 20 ab " , when ab is ascii dump then it should
not be treat as byte */
rollback = 0 ;
/* s2 is the ASCII string, s1 is the HEX string, e.g, when
s2 = " ab " , s1 = " 616220 "
we should find out the largest tail of s1 matches the head
of s2 , it means the matched part in tail is the ASCII dump
of the head byte . These matched should be rollback */
line_size = curr_offset - ( int ) ( pkt_lnstart - packet_buf ) ;
s2 = ( char * ) g_malloc ( ( line_size + 1 ) / 4 + 1 ) ;
/* gather the possible pattern */
for ( i = 0 ; i < ( line_size + 1 ) / 4 ; i + + ) {
tmp_str [ 0 ] = pkt_lnstart [ i * 3 ] ;
tmp_str [ 1 ] = pkt_lnstart [ i * 3 + 1 ] ;
tmp_str [ 2 ] = ' \0 ' ;
/* it is a valid convertable string */
if ( ! g_ascii_isxdigit ( tmp_str [ 0 ] ) | | ! g_ascii_isxdigit ( tmp_str [ 1 ] ) ) {
break ;
}
s2 [ i ] = ( char ) strtoul ( tmp_str , ( char * * ) NULL , 16 ) ;
rollback + + ;
/* the 3rd entry is not a delimiter, so the possible byte pattern will not shown */
if ( ! ( pkt_lnstart [ i * 3 + 2 ] = = ' ' ) ) {
if ( by_eol ! = 1 )
rollback - - ;
break ;
}
}
/* If packet line start contains possible byte pattern, the line end
should contain the matched pattern if the user open the - a flag .
The packet will be possible invalid if the byte pattern cannot find
a matched one in the line of packet buffer . */
if ( rollback > 0 ) {
if ( strncmp ( pkt_lnstart + line_size - rollback , s2 , rollback ) = = 0 ) {
unwrite_bytes ( rollback ) ;
}
/* Not matched. This line contains invalid packet bytes, so
discard the whole line */
else {
unwrite_bytes ( line_size ) ;
}
}
g_free ( s2 ) ;
}
2012-09-14 20:23:18 +00:00
break ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
case T_EOF :
2021-12-23 02:09:03 +00:00
if ( write_current_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
break ;
2012-09-14 20:23:18 +00:00
default :
break ;
}
break ;
/* ----- Processing packet, read text -------------------------------------*/
case READ_TEXT :
switch ( token ) {
case T_EOL :
state = START_OF_LINE ;
break ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
case T_EOF :
2021-12-23 02:09:03 +00:00
if ( write_current_packet ( FALSE ) ! = IMPORT_SUCCESS )
return IMPORT_FAILURE ;
Put back EOF rule, but without exporting write_current_packet().
Instead, add a new T_EOF token type, call parse_token() with it when we
get an EOF, and, in parse_token(), write the current packet if we get a
T_EOF token.
That's a bit simpler, and would let us treat EOFs in different places
differently, if, for example, we want to report warnings for
half-finished packets.
Change-Id: Ie41a8a1dedf91c34300468e073f18bf806e01892
Reviewed-on: https://code.wireshark.org/review/32489
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2019-03-20 16:06:13 +00:00
break ;
2012-09-14 20:23:18 +00:00
default :
break ;
}
break ;
default :
2021-12-23 02:09:03 +00:00
report_failure ( " FATAL ERROR: Bad state (%d) " , state ) ;
return IMPORT_FAILURE ;
2012-09-14 20:23:18 +00:00
}
2021-12-25 18:39:12 +00:00
if ( info_p - > debug > = 2 )
2012-09-14 20:23:18 +00:00
fprintf ( stderr , " , %s) \n " , state_str [ state ] ) ;
2021-12-23 02:09:03 +00:00
return IMPORT_SUCCESS ;
2012-09-14 20:23:18 +00:00
}
/*----------------------------------------------------------------------
2016-03-27 02:20:51 +00:00
* Import a text file .
2012-09-14 20:23:18 +00:00
*/
2016-03-31 01:44:01 +00:00
int
2021-12-24 12:39:13 +00:00
text_import ( text_import_info_t * const info )
2012-09-14 20:23:18 +00:00
{
2021-12-23 02:09:03 +00:00
import_status_t status ;
2016-03-31 01:44:01 +00:00
int ret ;
2017-04-17 07:48:20 +00:00
struct tm * now_tm ;
2016-03-31 01:44:01 +00:00
2012-12-26 05:57:06 +00:00
packet_buf = ( guint8 * ) g_malloc ( sizeof ( HDR_ETHERNET ) + sizeof ( HDR_IP ) +
sizeof ( HDR_SCTP ) + sizeof ( HDR_DATA_CHUNK ) +
2018-12-06 16:36:43 +00:00
sizeof ( HDR_EXPORT_PDU ) + WTAP_MAX_PACKET_SIZE_STANDARD ) ;
2012-09-14 20:23:18 +00:00
if ( ! packet_buf )
{
2021-12-23 02:09:03 +00:00
/* XXX: This doesn't happen, because g_malloc aborts the program on
* error , unlike malloc or g_try_malloc .
*/
report_failure ( " FATAL ERROR: no memory for packet buffer " ) ;
return INIT_FAILED ;
2012-09-14 20:23:18 +00:00
}
/* Lets start from the beginning */
state = INIT ;
curr_offset = 0 ;
packet_start = 0 ;
packet_preamble_len = 0 ;
2021-12-23 02:09:03 +00:00
direction = PACK_FLAGS_DIRECTION_UNKNOWN ;
2012-09-14 20:23:18 +00:00
ts_sec = time ( 0 ) ; /* initialize to current time */
2017-04-17 07:48:20 +00:00
now_tm = localtime ( & ts_sec ) ;
if ( now_tm = = NULL ) {
/*
* This shouldn ' t happen - on UN * X , this should Just Work , and
2021-12-17 00:42:09 +00:00
* on 32 bit Windows built with 32 bit time_t , it won ' t work if ts_sec
* is before the Epoch , but it ' s long after 1970 ( and even 32 bit
* Windows builds with 64 bit time_t by default now ) , so . . . .
2017-04-17 07:48:20 +00:00
*/
2021-12-23 02:09:03 +00:00
report_failure ( " localtime(right now) failed " ) ;
return INIT_FAILED ;
2017-04-17 07:48:20 +00:00
}
timecode_default = * now_tm ;
2012-09-14 20:23:18 +00:00
timecode_default . tm_isdst = - 1 ; /* Unknown for now, depends on time given to the strptime() function */
2021-02-15 18:38:23 +00:00
ts_nsec = 0 ;
2012-09-14 20:23:18 +00:00
2021-12-24 12:39:13 +00:00
/* Get input parameters. */
info_p = info ;
2012-09-14 20:23:18 +00:00
/* Dummy headers */
hdr_ethernet = FALSE ;
hdr_ip = FALSE ;
hdr_udp = FALSE ;
hdr_tcp = FALSE ;
hdr_sctp = FALSE ;
hdr_data_chunk = FALSE ;
2018-10-28 22:04:23 +00:00
hdr_export_pdu = FALSE ;
2012-09-14 20:23:18 +00:00
2021-02-15 18:38:23 +00:00
if ( info - > mode = = TEXT_IMPORT_HEXDUMP ) {
switch ( info - > hexdump . offset_type )
{
case OFFSET_NONE :
offset_base = 0 ;
break ;
case OFFSET_HEX :
offset_base = 16 ;
break ;
case OFFSET_OCT :
offset_base = 8 ;
break ;
case OFFSET_DEC :
offset_base = 10 ;
break ;
}
has_direction = info - > hexdump . has_direction ;
2012-09-14 20:23:18 +00:00
2021-02-15 18:38:23 +00:00
} else if ( info - > mode = = TEXT_IMPORT_REGEX ) {
has_direction = g_regex_get_string_number ( info - > regex . format , " dir " ) > = 0 ;
has_seqno = g_regex_get_string_number ( info - > regex . format , " seqno " ) > = 0 ;
}
2013-04-02 12:15:42 +00:00
2021-12-25 00:54:35 +00:00
ts_fmt_iso = ! ( g_strcmp0 ( info - > timestamp_format , " ISO " ) ) ;
2021-12-23 02:09:03 +00:00
timecode_warned = FALSE ;
2012-09-14 20:23:18 +00:00
2021-12-17 00:42:09 +00:00
/* XXX: It would be good to know the time precision of the file,
* to use for the time delta for packets without timestamps . ( ts_tick )
* That could either be added to text_import_info_t or a method
* added to get it from wtap_dumper ( which is opaque . )
*/
2012-09-14 20:23:18 +00:00
switch ( info - > dummy_header_type )
{
case HEADER_ETH :
hdr_ethernet = TRUE ;
hdr_ethernet_proto = info - > pid ;
break ;
case HEADER_IPV4 :
hdr_ip = TRUE ;
hdr_ip_proto = info - > protocol ;
hdr_ethernet = TRUE ;
hdr_ethernet_proto = 0x800 ;
break ;
case HEADER_UDP :
hdr_udp = TRUE ;
hdr_tcp = FALSE ;
hdr_ip = TRUE ;
hdr_ip_proto = 17 ;
hdr_ethernet = TRUE ;
hdr_ethernet_proto = 0x800 ;
break ;
case HEADER_TCP :
hdr_tcp = TRUE ;
hdr_udp = FALSE ;
hdr_ip = TRUE ;
hdr_ip_proto = 6 ;
hdr_ethernet = TRUE ;
hdr_ethernet_proto = 0x800 ;
break ;
case HEADER_SCTP :
hdr_sctp = TRUE ;
hdr_ip = TRUE ;
hdr_ip_proto = 132 ;
hdr_ethernet = TRUE ;
hdr_ethernet_proto = 0x800 ;
break ;
case HEADER_SCTP_DATA :
hdr_sctp = TRUE ;
hdr_data_chunk = TRUE ;
hdr_ip = TRUE ;
hdr_ip_proto = 132 ;
hdr_ethernet = TRUE ;
hdr_ethernet_proto = 0x800 ;
break ;
2018-10-28 22:04:23 +00:00
case HEADER_EXPORT_PDU :
hdr_export_pdu = TRUE ;
break ;
2012-09-14 20:23:18 +00:00
default :
break ;
}
2021-12-22 02:09:27 +00:00
if ( hdr_ip ) {
2021-12-22 04:43:19 +00:00
if ( info - > ipv6 ) {
hdr_ipv6 = TRUE ;
hdr_ip = FALSE ;
hdr_ethernet_proto = 0x86DD ;
}
2021-12-22 02:09:27 +00:00
}
2021-12-24 12:39:13 +00:00
info - > num_packets_read = 0 ;
info - > num_packets_written = 0 ;
2012-09-14 20:23:18 +00:00
2021-02-15 18:38:23 +00:00
if ( info - > mode = = TEXT_IMPORT_HEXDUMP ) {
2021-12-23 02:09:03 +00:00
status = text_import_scan ( info - > hexdump . import_text_FILE ) ;
switch ( status ) {
case ( IMPORT_SUCCESS ) :
ret = 0 ;
break ;
case ( IMPORT_FAILURE ) :
ret = INVALID_FILE ;
break ;
case ( IMPORT_INIT_FAILED ) :
2021-12-23 04:43:45 +00:00
report_failure ( " Can't initialize scanner: %s " , g_strerror ( errno ) ) ;
2021-12-23 02:09:03 +00:00
ret = INIT_FAILED ;
break ;
default :
ret = 0 ;
2021-12-23 04:43:45 +00:00
}
2021-02-15 18:38:23 +00:00
} else if ( info - > mode = = TEXT_IMPORT_REGEX ) {
ret = text_import_regex ( info ) ;
2021-12-23 04:43:45 +00:00
if ( ret > 0 ) {
2021-12-24 12:39:13 +00:00
info - > num_packets_read = ret ;
2021-12-23 04:43:45 +00:00
ret = 0 ;
2021-12-23 02:09:03 +00:00
} else if ( ret < 0 ) {
ret = INVALID_FILE ;
2021-12-23 04:43:45 +00:00
}
2021-02-15 18:38:23 +00:00
} else {
2021-12-23 02:09:03 +00:00
ret = INVALID_OPTION ;
2021-02-15 18:38:23 +00:00
}
2012-09-14 20:23:18 +00:00
g_free ( packet_buf ) ;
2018-02-16 22:10:47 +00:00
return ret ;
2012-09-14 20:23:18 +00:00
}