2008-01-13 21:10:09 +00:00
/* pcapng.c
*
* Wiretap Library
* Copyright ( c ) 1998 by Gilbert Ramirez < gram @ alumni . rice . edu >
*
* File format support for pcap - ng file format
* Copyright ( c ) 2007 by Ulf Lamping < ulf . lamping @ web . de >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2008-01-13 21:10:09 +00:00
*/
2008-01-18 00:59:30 +00:00
/* File format reference:
* http : //www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
2008-01-19 12:09:00 +00:00
* Related Wiki page :
* http : //wiki.wireshark.org/Development/PcapNg
2008-01-18 00:59:30 +00:00
*/
2008-01-13 21:10:09 +00:00
# include "config.h"
# include <stdlib.h>
# include <string.h>
# include <errno.h>
2011-03-24 22:47:57 +00:00
2011-03-24 23:33:38 +00:00
2008-01-13 21:10:09 +00:00
# include "wtap-int.h"
2013-09-22 19:40:02 +00:00
# include <epan/addr_resolv.h>
2008-01-13 21:10:09 +00:00
# include "file_wrappers.h"
2014-07-15 23:40:46 +00:00
# include <wsutil/buffer.h>
2009-04-27 09:28:28 +00:00
# include "libpcap.h"
# include "pcap-common.h"
2010-02-23 03:50:42 +00:00
# include "pcap-encap.h"
# include "pcapng.h"
2014-05-24 20:57:11 +00:00
# include "pcapng_module.h"
2008-01-13 21:10:09 +00:00
2013-09-22 19:43:51 +00:00
#if 0
2008-01-26 14:08:51 +00:00
# define pcapng_debug0(str) g_warning(str)
# define pcapng_debug1(str,p1) g_warning(str,p1)
# define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
# define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
# else
# define pcapng_debug0(str)
# define pcapng_debug1(str,p1)
# define pcapng_debug2(str,p1,p2)
# define pcapng_debug3(str,p1,p2,p3)
# endif
2011-02-04 02:08:47 +00:00
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_read ( wtap * wth , int * err , gchar * * err_info ,
2014-08-05 20:10:44 +00:00
gint64 * data_offset ) ;
2008-01-13 21:10:09 +00:00
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_seek_read ( wtap * wth , gint64 seek_off ,
2014-08-05 20:10:44 +00:00
struct wtap_pkthdr * phdr , Buffer * buf , int * err , gchar * * err_info ) ;
2008-01-13 21:10:09 +00:00
static void
2014-05-09 05:18:49 +00:00
pcapng_close ( wtap * wth ) ;
2008-01-13 21:10:09 +00:00
/* pcapng: common block header for every block type */
typedef struct pcapng_block_header_s {
2014-08-05 20:10:44 +00:00
guint32 block_type ;
guint32 block_total_length ;
/* x bytes block_body */
/* guint32 block_total_length */
2008-01-13 21:10:09 +00:00
} pcapng_block_header_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum block size = size of block header + size of block trailer .
*/
2012-03-12 15:43:59 +00:00
# define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
2012-02-22 18:32:43 +00:00
2013-06-07 08:19:40 +00:00
/*
* In order to keep from trying to allocate large chunks of memory ,
* which could either fail or , even if it succeeds , chew up so much
* address space or memory + backing store as not to leave room for
* anything else , we impose an upper limit on the size of blocks
* we ' re willing to handle .
*
* For now , we pick an arbitrary limit of 16 MB ( OK , fine , 16 MiB , but
* don ' t try saying that on Wikipedia : - ) : - ) : - ) ) .
*/
2014-08-05 20:10:44 +00:00
# define MAX_BLOCK_SIZE (16*1024*1024)
2013-06-07 08:19:40 +00:00
2008-01-13 21:10:09 +00:00
/* pcapng: section header block */
typedef struct pcapng_section_header_block_s {
2014-08-05 20:10:44 +00:00
/* pcapng_block_header_t */
guint32 magic ;
guint16 version_major ;
guint16 version_minor ;
guint64 section_length ; /* might be -1 for unknown */
/* ... Options ... */
2008-01-13 21:10:09 +00:00
} pcapng_section_header_block_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum SHB size = minimum block size + size of fixed length portion of SHB .
*/
2012-03-12 15:43:59 +00:00
# define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
2012-02-22 18:32:43 +00:00
2008-01-13 21:10:09 +00:00
/* pcapng: interface description block */
typedef struct pcapng_interface_description_block_s {
2014-08-05 20:10:44 +00:00
guint16 linktype ;
guint16 reserved ;
guint32 snaplen ;
/* ... Options ... */
2008-01-13 21:10:09 +00:00
} pcapng_interface_description_block_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum IDB size = minimum block size + size of fixed length portion of IDB .
*/
2012-03-12 15:43:59 +00:00
# define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
2012-02-22 18:32:43 +00:00
2008-01-13 21:10:09 +00:00
/* pcapng: packet block (obsolete) */
typedef struct pcapng_packet_block_s {
2014-08-05 20:10:44 +00:00
guint16 interface_id ;
guint16 drops_count ;
guint32 timestamp_high ;
guint32 timestamp_low ;
guint32 captured_len ;
guint32 packet_len ;
/* ... Packet Data ... */
/* ... Padding ... */
/* ... Options ... */
2008-01-13 21:10:09 +00:00
} pcapng_packet_block_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum PB size = minimum block size + size of fixed length portion of PB .
*/
2012-03-12 15:43:59 +00:00
# define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
2012-02-22 18:32:43 +00:00
2008-01-13 21:10:09 +00:00
/* pcapng: enhanced packet block */
typedef struct pcapng_enhanced_packet_block_s {
2014-08-05 20:10:44 +00:00
guint32 interface_id ;
guint32 timestamp_high ;
guint32 timestamp_low ;
guint32 captured_len ;
guint32 packet_len ;
/* ... Packet Data ... */
/* ... Padding ... */
/* ... Options ... */
2008-01-13 21:10:09 +00:00
} pcapng_enhanced_packet_block_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum EPB size = minimum block size + size of fixed length portion of EPB .
*/
2012-03-12 15:43:59 +00:00
# define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
2012-02-22 18:32:43 +00:00
2008-01-19 12:09:00 +00:00
/* pcapng: simple packet block */
typedef struct pcapng_simple_packet_block_s {
2014-08-05 20:10:44 +00:00
guint32 packet_len ;
/* ... Packet Data ... */
/* ... Padding ... */
2008-01-19 12:09:00 +00:00
} pcapng_simple_packet_block_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum SPB size = minimum block size + size of fixed length portion of SPB .
*/
2012-03-12 15:43:59 +00:00
# define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
2012-02-22 18:32:43 +00:00
2012-02-09 22:24:00 +00:00
/* pcapng: name resolution block */
2011-03-24 22:47:57 +00:00
typedef struct pcapng_name_resolution_block_s {
2014-08-05 20:10:44 +00:00
guint16 record_type ;
guint16 record_len ;
/* ... Record ... */
2011-03-24 22:47:57 +00:00
} pcapng_name_resolution_block_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum NRB size = minimum block size + size of smallest NRB record
* ( there must at least be an " end of records " record ) .
*/
2012-03-12 15:43:59 +00:00
# define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
2012-02-22 18:32:43 +00:00
2009-04-25 19:11:35 +00:00
/* pcapng: interface statistics block */
typedef struct pcapng_interface_statistics_block_s {
2014-08-05 20:10:44 +00:00
guint32 interface_id ;
guint32 timestamp_high ;
guint32 timestamp_low ;
/* ... Options ... */
2009-04-25 19:11:35 +00:00
} pcapng_interface_statistics_block_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum ISB size = minimum block size + size of fixed length portion of ISB .
*/
2012-03-12 15:43:59 +00:00
# define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
2012-02-22 18:32:43 +00:00
2008-01-18 10:29:23 +00:00
/* pcapng: common option header for every option type */
typedef struct pcapng_option_header_s {
2014-08-05 20:10:44 +00:00
guint16 option_code ;
guint16 option_length ;
/* ... x bytes Option Body ... */
/* ... Padding ... */
2008-01-18 10:29:23 +00:00
} pcapng_option_header_t ;
2008-01-13 21:10:09 +00:00
2012-02-15 19:44:16 +00:00
struct option {
2014-08-05 20:10:44 +00:00
guint16 type ;
guint16 value_length ;
2012-02-15 19:44:16 +00:00
} ;
2008-01-18 00:59:30 +00:00
/* Block types */
# define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
# define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
# define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
# define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
# define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
# define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
# define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
2008-01-13 21:10:09 +00:00
2012-02-15 19:44:16 +00:00
/* Options */
2012-12-22 20:38:08 +00:00
# define OPT_EOFOPT 0
# define OPT_COMMENT 1
# define OPT_SHB_HARDWARE 2
# define OPT_SHB_OS 3
# define OPT_SHB_USERAPPL 4
# define OPT_EPB_FLAGS 2
# define OPT_EPB_HASH 3
# define OPT_EPB_DROPCOUNT 4
2008-01-18 10:29:23 +00:00
2008-01-13 21:10:09 +00:00
/* Capture section */
2012-02-15 19:44:16 +00:00
#if 0
/* Moved to wtap.h */
2008-01-13 21:10:09 +00:00
typedef struct wtapng_section_s {
2014-08-05 20:10:44 +00:00
/* mandatory */
guint64 section_length ;
/* options */
gchar * opt_comment ; /* NULL if not available */
gchar * shb_hardware ; /* NULL if not available */
gchar * shb_os ; /* NULL if not available */
gchar * shb_user_appl ; /* NULL if not available */
2008-01-13 21:10:09 +00:00
} wtapng_section_t ;
2012-02-15 19:44:16 +00:00
# endif
2012-02-20 20:15:51 +00:00
#if 0
/* Moved to wtap.h */
2012-03-10 00:24:42 +00:00
/* Interface Description
2012-02-20 20:15:51 +00:00
*
* Options :
2012-03-10 00:24:42 +00:00
* if_name 2 A UTF - 8 string containing the name of the device used to capture data . " eth0 " / " \ Device \ NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68} " / . . .
* if_description 3 A UTF - 8 string containing the description of the device used to capture data . " Broadcom NetXtreme " / " First Ethernet Interface " / . . .
* if_IPv4addr 4 Interface network address and netmask . This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface . 192 168 1 1 255 255 255 0
* if_IPv6addr 5 Interface network address and prefix length ( stored in the last byte ) . This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface . 2001 : 0 db8 : 85 a3 : 08 d3 : 1319 : 8 a2e : 0370 : 7344 / 64 is written ( in hex ) as " 20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40 "
* if_MACaddr 6 Interface Hardware MAC address ( 48 bits ) . 00 01 02 03 04 05
* if_EUIaddr 7 Interface Hardware EUI address ( 64 bits ) , if available . TODO : give a good example
* if_speed 8 Interface speed ( in bps ) . 100000000 for 100 Mbps
* if_tsresol 9 Resolution of timestamps . If the Most Significant Bit is equal to zero , the remaining bits indicates the resolution of the timestamp as as a negative power of 10 ( e . g . 6 means microsecond resolution , timestamps are the number of microseconds since 1 / 1 / 1970 ) . If the Most Significant Bit is equal to one , the remaining bits indicates the resolution as as negative power of 2 ( e . g . 10 means 1 / 1024 of second ) . If this option is not present , a resolution of 10 ^ - 6 is assumed ( i . e . timestamps have the same resolution of the standard ' libpcap ' timestamps ) . 6
* if_tzone 10 Time zone for GMT support ( TODO : specify better ) . TODO : give a good example
* if_filter 11 The filter ( e . g . " capture only TCP traffic " ) used to capture traffic . The first byte of the Option Data keeps a code of the filter used ( e . g . if this is a libpcap string , or BPF bytecode , and more ) . More details about this format will be presented in Appendix XXX ( TODO ) . ( TODO : better use different options for different fields ? e . g . if_filter_pcap , if_filter_bpf , . . . ) 00 " tcp port 23 and host 10.0.0.5 "
* if_os 12 A UTF - 8 string containing the name of the operating system of the machine in which this interface is installed . This can be different from the same information that can be contained by the Section Header Block ( Section 3.1 ( Section Header Block ( mandatory ) ) ) because the capture can have been done on a remote machine . " Windows XP SP2 " / " openSUSE 10.2 " / . . .
* if_fcslen 13 An integer value that specified the length of the Frame Check Sequence ( in bits ) for this interface . For link layers whose FCS length can change during time , the Packet Block Flags Word can be used ( see Appendix A ( Packet Block Flags Word ) ) . 4
* if_tsoffset 14 A 64 bits integer value that specifies an offset ( in seconds ) that must be added to the timestamp of each packet to obtain the absolute timestamp of a packet . If the option is missing , the timestamps stored in the packet must be considered absolute timestamps . The time zone of the offset can be specified with the option if_tzone . TODO : won ' t a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems ? 1234
2012-02-20 20:15:51 +00:00
*/
2008-01-13 21:10:09 +00:00
typedef struct wtapng_if_descr_s {
2014-08-05 20:10:44 +00:00
/* mandatory */
guint16 link_type ;
guint encap ;
guint32 snap_len ;
/* options */
gchar * opt_comment ; /* NULL if not available */
gchar * if_name ; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
gchar * if_description ; /* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
/* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
/* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
/* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
/* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
guint64 if_speed ; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
guint8 if_tsresol ; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
* If the Most Significant Bit is equal to zero , the remaining bits indicates the resolution of the timestamp as as a negative power of 10
*/
/* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
gchar * if_filter ; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
* The first byte of the Option Data keeps a code of the filter used ( e . g . if this is a libpcap string , or BPF bytecode , and more ) .
*/
gchar * if_os ; /* NULL if not available, 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. */
gint8 if_fcslen ; /* -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. */
/* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2008-01-13 21:10:09 +00:00
} wtapng_if_descr_t ;
2012-02-20 20:15:51 +00:00
# endif
2008-01-13 21:10:09 +00:00
/* Packets */
typedef struct wtapng_packet_s {
2014-08-05 20:10:44 +00:00
/* mandatory */
guint32 ts_high ; /* seconds since 1.1.1970 */
guint32 ts_low ; /* fraction of seconds, depends on if_tsresol */
guint32 cap_len ; /* data length in the file */
guint32 packet_len ; /* data length on the wire */
guint32 interface_id ; /* identifier of the interface. */
guint16 drops_count ; /* drops count, only valid for packet block */
/* 0xffff if information no available */
/* pack_hash */
/* XXX - put the packet data / pseudo_header here as well? */
2008-01-13 21:10:09 +00:00
} wtapng_packet_t ;
2008-01-19 12:09:00 +00:00
/* Simple Packets */
typedef struct wtapng_simple_packet_s {
2014-08-05 20:10:44 +00:00
/* mandatory */
guint32 cap_len ; /* data length in the file */
guint32 packet_len ; /* data length on the wire */
/* XXX - put the packet data / pseudo_header here as well? */
2008-01-19 12:09:00 +00:00
} wtapng_simple_packet_t ;
2008-01-13 21:10:09 +00:00
/* Name Resolution */
typedef struct wtapng_name_res_s {
2014-08-05 20:10:44 +00:00
/* options */
gchar * opt_comment ; /* NULL if not available */
/* XXX */
2008-01-13 21:10:09 +00:00
} wtapng_name_res_t ;
2012-03-13 08:36:52 +00:00
#if 0
/* Interface Statistics moved to wtap.h*/
2008-01-13 21:10:09 +00:00
typedef struct wtapng_if_stats_s {
2014-08-05 20:10:44 +00:00
/* mandatory */
guint32 interface_id ;
guint32 ts_high ;
guint32 ts_low ;
/* options */
gchar * opt_comment ; /* NULL if not available */
guint64 isb_starttime ;
guint64 isb_endtime ;
guint64 isb_ifrecv ;
guint64 isb_ifdrop ;
guint64 isb_filteraccept ;
guint64 isb_osdrop ;
guint64 isb_usrdeliv ;
2008-01-13 21:10:09 +00:00
} wtapng_if_stats_t ;
2012-03-13 08:36:52 +00:00
# endif
2008-01-13 21:10:09 +00:00
typedef struct wtapng_block_s {
2014-08-05 20:10:44 +00:00
guint32 type ; /* block_type as defined by pcapng */
union {
wtapng_section_t section ;
wtapng_if_descr_t if_descr ;
wtapng_name_res_t name_res ;
wtapng_if_stats_t if_stats ;
} data ;
/*
* XXX - currently don ' t know how to handle these !
*
* For one thing , when we ' re reading a block , they must be
* writable , i . e . not const , so that we can read into them ,
* but , when we ' re writing a block , they can be const , and ,
* in fact , they sometimes point to const values .
*/
struct wtap_pkthdr * packet_header ;
Buffer * frame_buffer ;
2008-01-13 21:10:09 +00:00
} wtapng_block_t ;
2012-02-20 20:15:51 +00:00
/* Interface data in private struct */
2014-05-15 21:39:12 +00:00
typedef struct interface_info_s {
2014-08-05 20:10:44 +00:00
int wtap_encap ;
guint32 snap_len ;
guint64 time_units_per_second ;
2014-09-28 18:37:06 +00:00
int tsprecision ;
2014-05-15 21:39:12 +00:00
} interface_info_t ;
2009-05-03 15:47:41 +00:00
2010-02-26 07:59:54 +00:00
typedef struct {
2014-08-05 20:10:44 +00:00
gboolean shb_read ; /**< Set when first SHB read, second read will fail */
gboolean byte_swapped ;
guint16 version_major ;
guint16 version_minor ;
GArray * interfaces ; /**< Interfaces found in the capture file. */
gint8 if_fcslen ;
wtap_new_ipv4_callback_t add_new_ipv4 ;
wtap_new_ipv6_callback_t add_new_ipv6 ;
2010-02-26 07:59:54 +00:00
} pcapng_t ;
2014-05-24 20:57:11 +00:00
# ifdef HAVE_PLUGINS
/*
* Table for plugins to handle particular block types .
*
* A handler has a " read " routine and a " write " routine .
*
* A " read " routine returns a block as a libwiretap record , filling
* in the wtap_pkthdr structure with the appropriate record type and
* other information , and filling in the supplied Buffer with
* data for which there ' s no place in the wtap_pkthdr structure .
*
* A " write " routine takes a libwiretap record and Buffer and writes
* out a block .
*/
typedef struct {
2014-08-05 20:10:44 +00:00
block_reader read ;
block_writer write ;
2014-05-24 20:57:11 +00:00
} block_handler ;
static GHashTable * block_handlers ;
void
register_pcapng_block_type_handler ( guint block_type , block_reader read ,
block_writer write )
{
2014-08-05 20:10:44 +00:00
block_handler * handler ;
2014-05-24 20:57:11 +00:00
2014-08-05 20:10:44 +00:00
if ( block_handlers = = NULL ) {
/*
* Create the table of block handlers .
*
* XXX - there ' s no " g_uint_hash() " or " g_uint_equal() " ,
* so we use " g_direct_hash() " and " g_direct_equal() " .
*/
block_handlers = g_hash_table_new_full ( g_direct_hash ,
g_direct_equal ,
NULL , g_free ) ;
}
handler = ( block_handler * ) g_malloc ( sizeof * handler ) ;
handler - > read = read ;
handler - > write = write ;
( void ) g_hash_table_insert ( block_handlers , GUINT_TO_POINTER ( block_type ) ,
handler ) ;
2014-05-24 20:57:11 +00:00
}
# endif /* HAVE_PLUGINS */
2008-01-19 12:09:00 +00:00
static int
2008-07-09 20:09:23 +00:00
pcapng_read_option ( FILE_T fh , pcapng_t * pn , pcapng_option_header_t * oh ,
2013-06-07 08:19:40 +00:00
char * content , guint len , guint to_read ,
int * err , gchar * * err_info )
2008-01-19 12:09:00 +00:00
{
2014-08-05 20:10:44 +00:00
int block_read ;
/* sanity check: don't run past the end of the block */
if ( to_read < sizeof ( * oh ) ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup ( " pcapng_read_option: option goes past the end of the block " ) ;
return - 1 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* read option header */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , oh , sizeof ( * oh ) , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_read_option: failed to read option " ) ;
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
return - 1 ;
2014-08-05 20:10:44 +00:00
}
block_read = sizeof ( * oh ) ;
if ( pn - > byte_swapped ) {
oh - > option_code = GUINT16_SWAP_LE_BE ( oh - > option_code ) ;
oh - > option_length = GUINT16_SWAP_LE_BE ( oh - > option_length ) ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* sanity check: don't run past the end of the block */
if ( to_read < sizeof ( * oh ) + oh - > option_length ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup ( " pcapng_read_option: option goes past the end of the block " ) ;
return - 1 ;
}
2013-06-07 08:19:40 +00:00
2014-08-05 20:10:44 +00:00
/* sanity check: option length */
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( len < oh - > option_length ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup ( " pcapng_read_option: option goes past the end of the block " ) ;
return - 1 ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* read option content */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , content , oh - > option_length , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_read_option: failed to read content of option %u " , oh - > option_code ) ;
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
return - 1 ;
2014-08-05 20:10:44 +00:00
}
block_read + = oh - > option_length ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* jump over potential padding bytes at end of option */
if ( ( oh - > option_length % 4 ) ! = 0 ) {
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( ! file_skip ( fh , 4 - ( oh - > option_length % 4 ) , err ) )
return - 1 ;
2014-08-05 20:10:44 +00:00
block_read + = 4 - ( oh - > option_length % 4 ) ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
return block_read ;
2008-01-19 12:09:00 +00:00
}
2014-09-22 11:43:14 +00:00
static void
pcapng_free_wtapng_block_data ( wtapng_block_t * wblock )
{
2014-09-24 13:07:50 +00:00
switch ( wblock - > type ) {
case ( BLOCK_TYPE_SHB ) :
g_free ( wblock - > data . section . opt_comment ) ;
g_free ( wblock - > data . section . shb_hardware ) ;
g_free ( wblock - > data . section . shb_os ) ;
g_free ( wblock - > data . section . shb_user_appl ) ;
break ;
}
2014-09-22 11:43:14 +00:00
}
2014-10-15 23:45:51 +00:00
typedef enum {
2014-10-16 01:15:15 +00:00
PCAPNG_BLOCK_OK ,
PCAPNG_BLOCK_NOT_SHB ,
PCAPNG_BLOCK_ERROR
2014-10-15 23:45:51 +00:00
} block_return_val ;
static block_return_val
pcapng_read_section_header_block ( FILE_T fh , pcapng_block_header_t * bh ,
pcapng_t * pn , wtapng_block_t * wblock ,
int * err , gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
int bytes_read ;
guint to_read , opt_cont_buf_len ;
pcapng_section_header_block_t shb ;
pcapng_option_header_t oh ;
char * option_content = NULL ; /* Allocate as large as the options block */
2014-10-14 23:53:03 +00:00
/* read fixed-length part of the block */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & shb , sizeof shb , err , err_info ) ) {
if ( * err = = WTAP_ERR_SHORT_READ ) {
2014-10-15 23:45:51 +00:00
/*
* This block is too short to be an SHB .
*
* If we ' re reading this as part of an open ,
* the file is too short to be a pcap - ng file .
*
* If we ' re not , we treat PCAPNG_BLOCK_NOT_SHB and
* PCAPNG_BLOCK_ERROR the same , so we can just return
* PCAPNG_BLOCK_NOT_SHB in both cases .
*/
return PCAPNG_BLOCK_NOT_SHB ;
2012-03-12 15:43:59 +00:00
}
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
/* is the magic number one we expect? */
switch ( shb . magic ) {
case ( 0x1A2B3C4D ) :
/* this seems pcapng with correct byte order */
pn - > byte_swapped = FALSE ;
pn - > version_major = shb . version_major ;
pn - > version_minor = shb . version_minor ;
pcapng_debug3 ( " pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u " ,
pn - > version_major , pn - > version_minor , bh - > block_total_length ) ;
break ;
case ( 0x4D3C2B1A ) :
/* this seems pcapng with swapped byte order */
pn - > byte_swapped = TRUE ;
pn - > version_major = GUINT16_SWAP_LE_BE ( shb . version_major ) ;
pn - > version_minor = GUINT16_SWAP_LE_BE ( shb . version_minor ) ;
/* tweak the block length to meet current swapping that we know now */
bh - > block_total_length = GUINT32_SWAP_LE_BE ( bh - > block_total_length ) ;
pcapng_debug3 ( " pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u " ,
pn - > version_major , pn - > version_minor , bh - > block_total_length ) ;
break ;
default :
/* Not a "pcapng" magic number we know about. */
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_section_header_block: unknown byte-order magic number 0x%08x " , shb . magic ) ;
2014-10-15 23:45:51 +00:00
/*
* See above comment about PCAPNG_BLOCK_NOT_SHB .
*/
return PCAPNG_BLOCK_NOT_SHB ;
2014-08-05 20:10:44 +00:00
}
2013-06-07 08:19:40 +00:00
2014-10-14 23:53:03 +00:00
/*
* Is this block long enough to be an SHB ?
*/
if ( bh - > block_total_length < MIN_SHB_SIZE ) {
/*
* No .
*/
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_section_header_block: total block length %u of an SHB is less than the minimum SHB size %u " ,
bh - > block_total_length , MIN_SHB_SIZE ) ;
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-10-14 23:53:03 +00:00
}
2014-08-05 20:10:44 +00:00
/* OK, at this point we assume it's a pcap-ng file.
Don ' t try to allocate memory for a huge number of options , as
that might fail and , even if it succeeds , it might not leave
any address space or memory + backing store for anything else .
We do that by imposing a maximum block size of MAX_BLOCK_SIZE .
We check for this * after * checking the SHB for its byte
order magic number , so that non - pcap - ng files are less
likely to be treated as bad pcap - ng files . */
if ( bh - > block_total_length > MAX_BLOCK_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: total block length %u is too large (> %u) " ,
bh - > block_total_length , MAX_BLOCK_SIZE ) ;
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
2013-06-07 08:19:40 +00:00
2014-08-05 20:10:44 +00:00
/* We currently only suport one SHB */
if ( pn - > shb_read = = TRUE ) {
* err = WTAP_ERR_UNSUPPORTED ;
* err_info = g_strdup_printf ( " pcapng: multiple section header blocks not supported " ) ;
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
2013-06-07 08:19:40 +00:00
2014-08-05 20:10:44 +00:00
/* we currently only understand SHB V1.0 */
if ( pn - > version_major ! = 1 | | pn - > version_minor > 0 ) {
* err = WTAP_ERR_UNSUPPORTED ;
* err_info = g_strdup_printf ( " pcapng_read_section_header_block: unknown SHB version %u.%u " ,
pn - > version_major , pn - > version_minor ) ;
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* 64bit section_length (currently unused) */
if ( pn - > byte_swapped ) {
wblock - > data . section . section_length = GUINT64_SWAP_LE_BE ( shb . section_length ) ;
} else {
wblock - > data . section . section_length = shb . section_length ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Options */
to_read = bh - > block_total_length - MIN_SHB_SIZE ;
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = ( char * ) g_try_malloc ( opt_cont_buf_len ) ;
if ( opt_cont_buf_len ! = 0 & & option_content = = NULL ) {
* err = ENOMEM ; /* we assume we're out of memory */
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
pcapng_debug1 ( " pcapng_read_section_header_block: Options %u bytes " , to_read ) ;
while ( to_read ! = 0 ) {
/* read option */
pcapng_debug1 ( " pcapng_read_section_header_block: Options %u bytes remaining " , to_read ) ;
bytes_read = pcapng_read_option ( fh , pn , & oh , option_content , opt_cont_buf_len , to_read , err , err_info ) ;
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_section_header_block: failed to read option " ) ;
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
to_read - = bytes_read ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* handle option content */
switch ( oh . option_code ) {
case ( OPT_EOFOPT ) :
if ( to_read ! = 0 ) {
pcapng_debug1 ( " pcapng_read_section_header_block: %u bytes after opt_endofopt " , to_read ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( OPT_COMMENT ) :
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2014-09-22 11:43:14 +00:00
g_free ( wblock - > data . section . opt_comment ) ;
2014-08-05 20:10:44 +00:00
wblock - > data . section . opt_comment = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_section_header_block: opt_comment %s " , wblock - > data . section . opt_comment ) ;
} else {
pcapng_debug1 ( " pcapng_read_section_header_block: opt_comment length %u seems strange " , oh . option_length ) ;
}
break ;
case ( OPT_SHB_HARDWARE ) :
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2014-09-22 11:43:14 +00:00
g_free ( wblock - > data . section . shb_hardware ) ;
2014-08-05 20:10:44 +00:00
wblock - > data . section . shb_hardware = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_section_header_block: shb_hardware %s " , wblock - > data . section . shb_hardware ) ;
} else {
pcapng_debug1 ( " pcapng_read_section_header_block: shb_hardware length %u seems strange " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( OPT_SHB_OS ) :
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2014-09-22 11:43:14 +00:00
g_free ( wblock - > data . section . shb_os ) ;
2014-08-05 20:10:44 +00:00
wblock - > data . section . shb_os = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_section_header_block: shb_os %s " , wblock - > data . section . shb_os ) ;
} else {
pcapng_debug2 ( " pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u " , oh . option_length , to_read ) ;
}
break ;
case ( OPT_SHB_USERAPPL ) :
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2014-09-22 11:43:14 +00:00
g_free ( wblock - > data . section . shb_user_appl ) ;
2014-08-05 20:10:44 +00:00
wblock - > data . section . shb_user_appl = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_section_header_block: shb_user_appl %s " , wblock - > data . section . shb_user_appl ) ;
} else {
pcapng_debug1 ( " pcapng_read_section_header_block: shb_user_appl length %u seems strange " , oh . option_length ) ;
}
break ;
default :
pcapng_debug2 ( " pcapng_read_section_header_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
g_free ( option_content ) ;
2012-03-12 15:43:59 +00:00
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_OK ;
2008-01-13 21:10:09 +00:00
}
/* "Interface Description Block" */
2014-10-15 23:45:51 +00:00
static gboolean
2014-09-28 18:37:06 +00:00
pcapng_read_if_descr_block ( wtap * wth , FILE_T fh , pcapng_block_header_t * bh ,
pcapng_t * pn , wtapng_block_t * wblock , int * err ,
gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
2014-09-28 18:37:06 +00:00
guint64 time_units_per_second = 1000000 ; /* default = 10^6 */
int tsprecision = WTAP_TSPREC_USEC ;
2014-08-05 20:10:44 +00:00
int bytes_read ;
guint to_read , opt_cont_buf_len ;
pcapng_interface_description_block_t idb ;
pcapng_option_header_t oh ;
char * option_content = NULL ; /* Allocate as large as the options block */
/*
* Is this block long enough to be an IDB ?
*/
if ( bh - > block_total_length < MIN_IDB_SIZE ) {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* No .
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_if_descr_block: total block length %u of an IDB is less than the minimum IDB size %u " ,
bh - > block_total_length , MIN_IDB_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Don't try to allocate memory for a huge number of options, as
that might fail and , even if it succeeds , it might not leave
any address space or memory + backing store for anything else .
We do that by imposing a maximum block size of MAX_BLOCK_SIZE .
We check for this * after * checking the SHB for its byte
order magic number , so that non - pcap - ng files are less
likely to be treated as bad pcap - ng files . */
if ( bh - > block_total_length > MAX_BLOCK_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: total block length %u is too large (> %u) " ,
bh - > block_total_length , MAX_BLOCK_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2013-06-07 08:19:40 +00:00
2014-08-05 20:10:44 +00:00
/* read block content */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & idb , sizeof idb , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_read_if_descr_block: failed to read IDB " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
/* mandatory values */
if ( pn - > byte_swapped ) {
wblock - > data . if_descr . link_type = GUINT16_SWAP_LE_BE ( idb . linktype ) ;
wblock - > data . if_descr . snap_len = GUINT32_SWAP_LE_BE ( idb . snaplen ) ;
} else {
wblock - > data . if_descr . link_type = idb . linktype ;
wblock - > data . if_descr . snap_len = idb . snaplen ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
wblock - > data . if_descr . wtap_encap = wtap_pcap_encap_to_wtap_encap ( wblock - > data . if_descr . link_type ) ;
wblock - > data . if_descr . time_units_per_second = time_units_per_second ;
2014-09-28 18:37:06 +00:00
wblock - > data . if_descr . tsprecision = tsprecision ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug3 ( " pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u " ,
wblock - > data . if_descr . link_type ,
wtap_encap_string ( wblock - > data . if_descr . wtap_encap ) ,
wblock - > data . if_descr . snap_len ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( wblock - > data . if_descr . snap_len > WTAP_MAX_PACKET_SIZE ) {
/* This is unrealistic, but text2pcap currently uses 102400.
* We do not use this value , maybe we should check the
* snap_len of the packets against it . For now , only warn .
*/
pcapng_debug1 ( " pcapng_read_if_descr_block: snapshot length %u unrealistic. " ,
2012-03-12 15:43:59 +00:00
wblock - > data . if_descr . snap_len ) ;
2014-08-05 20:10:44 +00:00
/*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Option defaults */
wblock - > data . if_descr . opt_comment = NULL ;
wblock - > data . if_descr . if_name = NULL ;
wblock - > data . if_descr . if_description = NULL ;
/* XXX: if_IPv4addr */
/* XXX: if_IPv6addr */
/* XXX: if_MACaddr */
/* XXX: if_EUIaddr */
wblock - > data . if_descr . if_speed = 0 ; /* "unknown" */
wblock - > data . if_descr . if_tsresol = 6 ; /* default is 6 for microsecond resolution */
wblock - > data . if_descr . if_filter_str = NULL ;
wblock - > data . if_descr . bpf_filter_len = 0 ;
wblock - > data . if_descr . if_filter_bpf_bytes = NULL ;
wblock - > data . if_descr . if_os = NULL ;
wblock - > data . if_descr . if_fcslen = - 1 ; /* unknown or changes between packets */
/* XXX: guint64 if_tsoffset; */
/* Options */
to_read = bh - > block_total_length - MIN_IDB_SIZE ;
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = ( char * ) g_try_malloc ( opt_cont_buf_len ) ;
if ( opt_cont_buf_len ! = 0 & & option_content = = NULL ) {
* err = ENOMEM ; /* we assume we're out of memory */
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
while ( to_read ! = 0 ) {
/* read option */
bytes_read = pcapng_read_option ( fh , pn , & oh , option_content , opt_cont_buf_len , to_read , err , err_info ) ;
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_if_descr_block: failed to read option " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
to_read - = bytes_read ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* handle option content */
switch ( oh . option_code ) {
case ( 0 ) : /* opt_endofopt */
if ( to_read ! = 0 ) {
pcapng_debug1 ( " pcapng_read_if_descr_block: %u bytes after opt_endofopt " , to_read ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( 1 ) : /* opt_comment */
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . if_descr . opt_comment = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_if_descr_block: opt_comment %s " , wblock - > data . if_descr . opt_comment ) ;
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: opt_comment length %u seems strange " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( 2 ) : /* if_name */
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . if_descr . if_name = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_if_descr_block: if_name %s " , wblock - > data . if_descr . if_name ) ;
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: if_name length %u seems strange " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( 3 ) : /* if_description */
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . if_descr . if_description = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_if_descr_block: if_description %s " , wblock - > data . if_descr . if_description ) ;
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: if_description length %u seems strange " , oh . option_length ) ;
}
break ;
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* if_IPv4addr 4 Interface network address and netmask . This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface . 192 168 1 1 255 255 255 0
* if_IPv6addr 5 Interface network address and prefix length ( stored in the last byte ) . This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface . 2001 : 0 db8 : 85 a3 : 08 d3 : 1319 : 8 a2e : 0370 : 7344 / 64 is written ( in hex ) as " 20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40 "
* if_MACaddr 6 Interface Hardware MAC address ( 48 bits ) . 00 01 02 03 04 05
* if_EUIaddr 7 Interface Hardware EUI address ( 64 bits ) , if available . TODO : give a good example
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
case ( 8 ) : /* if_speed */
if ( oh . option_length = = 8 ) {
/* Don't cast a char[] into a guint64--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & wblock - > data . if_descr . if_speed , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_descr . if_speed = GUINT64_SWAP_LE_BE ( wblock - > data . if_descr . if_speed ) ;
pcapng_debug1 ( " pcapng_read_if_descr_block: if_speed % " G_GINT64_MODIFIER " u (bps) " , wblock - > data . if_descr . if_speed ) ;
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: if_speed length %u not 8 as expected " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( 9 ) : /* if_tsresol */
if ( oh . option_length = = 1 ) {
guint64 base ;
guint64 result ;
guint8 i , exponent , if_tsresol ;
if_tsresol = option_content [ 0 ] ;
if ( if_tsresol & 0x80 ) {
base = 2 ;
} else {
base = 10 ;
}
exponent = ( guint8 ) ( if_tsresol & 0x7f ) ;
if ( ( ( base = = 2 ) & & ( exponent < 64 ) ) | | ( ( base = = 10 ) & & ( exponent < 20 ) ) ) {
result = 1 ;
for ( i = 0 ; i < exponent ; i + + ) {
result * = base ;
}
time_units_per_second = result ;
} else {
time_units_per_second = G_MAXUINT64 ;
}
if ( time_units_per_second > ( ( ( guint64 ) 1 ) < < 32 ) ) {
pcapng_debug0 ( " pcapng_open: time conversion might be inaccurate " ) ;
}
wblock - > data . if_descr . time_units_per_second = time_units_per_second ;
wblock - > data . if_descr . if_tsresol = if_tsresol ;
2014-09-28 18:37:06 +00:00
if ( time_units_per_second > = 1000000000 )
tsprecision = WTAP_TSPREC_NSEC ;
else if ( time_units_per_second > = 1000000 )
tsprecision = WTAP_TSPREC_USEC ;
else if ( time_units_per_second > = 1000 )
tsprecision = WTAP_TSPREC_MSEC ;
else if ( time_units_per_second > = 100 )
tsprecision = WTAP_TSPREC_CSEC ;
else if ( time_units_per_second > = 10 )
tsprecision = WTAP_TSPREC_DSEC ;
else
tsprecision = WTAP_TSPREC_SEC ;
wblock - > data . if_descr . tsprecision = tsprecision ;
pcapng_debug3 ( " pcapng_read_if_descr_block: if_tsresol %u, units/s % " G_GINT64_MODIFIER " u, tsprecision %d " , wblock - > data . if_descr . if_tsresol , wblock - > data . if_descr . time_units_per_second , tsprecision ) ;
2012-03-12 15:43:59 +00:00
} else {
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* if_tzone 10 Time zone for GMT support ( TODO : specify better ) . TODO : give a good example
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
case ( 11 ) : /* if_filter */
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
/* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
* or BPF bytecode .
*/
if ( option_content [ 0 ] = = 0 ) {
wblock - > data . if_descr . if_filter_str = g_strndup ( option_content + 1 , oh . option_length - 1 ) ;
pcapng_debug2 ( " pcapng_read_if_descr_block: if_filter_str %s oh.option_length %u " , wblock - > data . if_descr . if_filter_str , oh . option_length ) ;
} else if ( option_content [ 0 ] = = 1 ) {
wblock - > data . if_descr . bpf_filter_len = oh . option_length - 1 ;
wblock - > data . if_descr . if_filter_bpf_bytes = ( gchar * ) g_malloc ( oh . option_length - 1 ) ;
memcpy ( & wblock - > data . if_descr . if_filter_bpf_bytes , option_content + 1 , oh . option_length - 1 ) ;
}
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: if_filter length %u seems strange " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( 12 ) : /* if_os */
/*
* if_os 12 A UTF - 8 string containing the name of the operating system of the machine in which this interface is installed .
* This can be different from the same information that can be contained by the Section Header Block ( Section 3.1 ( Section Header Block ( mandatory ) ) )
* because the capture can have been done on a remote machine . " Windows XP SP2 " / " openSUSE 10.2 " / . . .
*/
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . if_descr . if_os = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_if_descr_block: if_os %s " , wblock - > data . if_descr . if_os ) ;
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: if_os length %u seems strange " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( 13 ) : /* if_fcslen */
if ( oh . option_length = = 1 ) {
wblock - > data . if_descr . if_fcslen = option_content [ 0 ] ;
pn - > if_fcslen = wblock - > data . if_descr . if_fcslen ;
pcapng_debug1 ( " pcapng_read_if_descr_block: if_fcslen %u " , wblock - > data . if_descr . if_fcslen ) ;
/* XXX - add sanity check */
2012-03-12 15:43:59 +00:00
} else {
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
/*
* if_tsoffset 14 A 64 bits integer value that specifies an offset ( in seconds ) that must be added to the timestamp of each packet
* to obtain the absolute timestamp of a packet . If the option is missing , the timestamps stored in the packet must be considered absolute timestamps .
* The time zone of the offset can be specified with the option if_tzone .
* TODO : won ' t a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems ? 1234
*/
default :
pcapng_debug2 ( " pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
}
}
g_free ( option_content ) ;
2014-09-28 18:37:06 +00:00
/*
* If the per - file encapsulation isn ' t known , set it to this
* interface ' s encapsulation .
*
* If it * is * known , and it isn ' t this interface ' s encapsulation ,
* set it to WTAP_ENCAP_PER_PACKET , as this file doesn ' t
* have a single encapsulation for all interfaces in the file ,
* so it probably doesn ' t have a single encapsulation for all
* packets in the file .
*/
if ( wth - > file_encap = = WTAP_ENCAP_UNKNOWN ) {
wth - > file_encap = wblock - > data . if_descr . wtap_encap ;
} else {
if ( wth - > file_encap ! = wblock - > data . if_descr . wtap_encap ) {
wth - > file_encap = WTAP_ENCAP_PER_PACKET ;
}
}
/*
* The same applies to the per - file time stamp resolution .
*/
if ( wth - > file_tsprec = = WTAP_TSPREC_UNKNOWN ) {
wth - > file_tsprec = wblock - > data . if_descr . tsprecision ;
2014-08-05 20:10:44 +00:00
} else {
2014-09-28 18:37:06 +00:00
if ( wth - > file_tsprec ! = wblock - > data . if_descr . tsprecision ) {
wth - > file_tsprec = WTAP_TSPREC_PER_PACKET ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2014-10-15 23:45:51 +00:00
return TRUE ;
2014-08-05 20:10:44 +00:00
}
2014-10-15 23:45:51 +00:00
static gboolean
2014-08-05 20:10:44 +00:00
pcapng_read_packet_block ( FILE_T fh , pcapng_block_header_t * bh , pcapng_t * pn , wtapng_block_t * wblock , int * err , gchar * * err_info , gboolean enhanced )
{
int bytes_read ;
guint block_read ;
guint to_read , opt_cont_buf_len ;
pcapng_enhanced_packet_block_t epb ;
pcapng_packet_block_t pb ;
wtapng_packet_t packet ;
guint32 block_total_length ;
guint32 padding ;
interface_info_t iface_info ;
guint64 ts ;
pcapng_option_header_t oh ;
int pseudo_header_len ;
char * option_content = NULL ; /* Allocate as large as the options block */
int fcslen ;
/* Don't try to allocate memory for a huge number of options, as
that might fail and , even if it succeeds , it might not leave
any address space or memory + backing store for anything else .
We do that by imposing a maximum block size of MAX_BLOCK_SIZE .
We check for this * after * checking the SHB for its byte
order magic number , so that non - pcap - ng files are less
likely to be treated as bad pcap - ng files . */
if ( bh - > block_total_length > MAX_BLOCK_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: total block length %u is too large (> %u) " ,
bh - > block_total_length , MAX_BLOCK_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* "(Enhanced) Packet Block" read fixed part */
if ( enhanced ) {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* Is this block long enough to be an EPB ?
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
if ( bh - > block_total_length < MIN_EPB_SIZE ) {
/*
* No .
*/
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u " ,
bh - > block_total_length , MIN_EPB_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & epb , sizeof epb , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_read_packet_block: failed to read packet data " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
block_read = ( guint ) sizeof epb ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( pn - > byte_swapped ) {
packet . interface_id = GUINT32_SWAP_LE_BE ( epb . interface_id ) ;
packet . drops_count = - 1 ; /* invalid */
packet . ts_high = GUINT32_SWAP_LE_BE ( epb . timestamp_high ) ;
packet . ts_low = GUINT32_SWAP_LE_BE ( epb . timestamp_low ) ;
packet . cap_len = GUINT32_SWAP_LE_BE ( epb . captured_len ) ;
packet . packet_len = GUINT32_SWAP_LE_BE ( epb . packet_len ) ;
} else {
packet . interface_id = epb . interface_id ;
packet . drops_count = - 1 ; /* invalid */
packet . ts_high = epb . timestamp_high ;
packet . ts_low = epb . timestamp_low ;
packet . cap_len = epb . captured_len ;
packet . packet_len = epb . packet_len ;
}
pcapng_debug3 ( " pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d " ,
packet . interface_id , packet . cap_len , packet . packet_len ) ;
} else {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* Is this block long enough to be a PB ?
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
if ( bh - > block_total_length < MIN_PB_SIZE ) {
/*
* No .
*/
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u " ,
bh - > block_total_length , MIN_PB_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & pb , sizeof pb , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_read_packet_block: failed to read packet data " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
block_read = ( guint ) sizeof pb ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( pn - > byte_swapped ) {
packet . interface_id = GUINT16_SWAP_LE_BE ( pb . interface_id ) ;
packet . drops_count = GUINT16_SWAP_LE_BE ( pb . drops_count ) ;
packet . ts_high = GUINT32_SWAP_LE_BE ( pb . timestamp_high ) ;
packet . ts_low = GUINT32_SWAP_LE_BE ( pb . timestamp_low ) ;
packet . cap_len = GUINT32_SWAP_LE_BE ( pb . captured_len ) ;
packet . packet_len = GUINT32_SWAP_LE_BE ( pb . packet_len ) ;
} else {
packet . interface_id = pb . interface_id ;
packet . drops_count = pb . drops_count ;
packet . ts_high = pb . timestamp_high ;
packet . ts_low = pb . timestamp_low ;
packet . cap_len = pb . captured_len ;
packet . packet_len = pb . packet_len ;
}
pcapng_debug3 ( " pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d " ,
packet . interface_id , packet . cap_len , packet . packet_len ) ;
}
/*
* How much padding is there at the end of the packet data ?
*/
if ( ( packet . cap_len % 4 ) ! = 0 )
padding = 4 - ( packet . cap_len % 4 ) ;
else
padding = 0 ;
/* add padding bytes to "block total length" */
/* (the "block total length" of some example files don't contain the packet data padding bytes!) */
if ( bh - > block_total_length % 4 ) {
block_total_length = bh - > block_total_length + 4 - ( bh - > block_total_length % 4 ) ;
} else {
block_total_length = bh - > block_total_length ;
}
pcapng_debug1 ( " pcapng_read_packet_block: block_total_length %d " , block_total_length ) ;
/*
* Is this block long enough to hold the packet data ?
*/
if ( enhanced ) {
if ( block_total_length <
MIN_EPB_SIZE + packet . cap_len + padding ) {
/*
* No .
*/
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data " ,
block_total_length , packet . cap_len ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
} else {
if ( block_total_length <
MIN_PB_SIZE + packet . cap_len + padding ) {
/*
* No .
*/
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data " ,
block_total_length , packet . cap_len ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( packet . cap_len > WTAP_MAX_PACKET_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u " ,
packet . cap_len , WTAP_MAX_PACKET_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
pcapng_debug3 ( " pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u " ,
packet . packet_len ,
packet . cap_len ,
packet . interface_id ) ;
if ( packet . interface_id > = pn - > interfaces - > len ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: interface index %u is not less than interface count %u " ,
packet . interface_id , pn - > interfaces - > len ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
iface_info = g_array_index ( pn - > interfaces , interface_info_t ,
packet . interface_id ) ;
wblock - > packet_header - > rec_type = REC_TYPE_PACKET ;
wblock - > packet_header - > presence_flags = WTAP_HAS_TS | WTAP_HAS_CAP_LEN | WTAP_HAS_INTERFACE_ID ;
pcapng_debug3 ( " pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d. " ,
iface_info . wtap_encap ,
wtap_encap_string ( iface_info . wtap_encap ) ,
pcap_get_phdr_size ( iface_info . wtap_encap , & wblock - > packet_header - > pseudo_header ) ) ;
wblock - > packet_header - > interface_id = packet . interface_id ;
wblock - > packet_header - > pkt_encap = iface_info . wtap_encap ;
2014-09-28 18:37:06 +00:00
wblock - > packet_header - > pkt_tsprec = iface_info . tsprecision ;
2014-08-05 20:10:44 +00:00
memset ( ( void * ) & wblock - > packet_header - > pseudo_header , 0 , sizeof ( union wtap_pseudo_header ) ) ;
pseudo_header_len = pcap_process_pseudo_header ( fh ,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG ,
iface_info . wtap_encap ,
packet . cap_len ,
TRUE ,
wblock - > packet_header ,
err ,
err_info ) ;
if ( pseudo_header_len < 0 ) {
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
block_read + = pseudo_header_len ;
if ( pseudo_header_len ! = pcap_get_phdr_size ( iface_info . wtap_encap , & wblock - > packet_header - > pseudo_header ) ) {
pcapng_debug1 ( " pcapng_read_packet_block: Could only read %d bytes for pseudo header. " ,
pseudo_header_len ) ;
}
wblock - > packet_header - > caplen = packet . cap_len - pseudo_header_len ;
wblock - > packet_header - > len = packet . packet_len - pseudo_header_len ;
/* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
ts = ( ( ( guint64 ) packet . ts_high ) < < 32 ) | ( ( guint64 ) packet . ts_low ) ;
wblock - > packet_header - > ts . secs = ( time_t ) ( ts / iface_info . time_units_per_second ) ;
wblock - > packet_header - > ts . nsecs = ( int ) ( ( ( ts % iface_info . time_units_per_second ) * 1000000000 ) / iface_info . time_units_per_second ) ;
/* "(Enhanced) Packet Block" read capture data */
if ( ! wtap_read_packet_bytes ( fh , wblock - > frame_buffer ,
packet . cap_len - pseudo_header_len , err , err_info ) )
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
block_read + = packet . cap_len - pseudo_header_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* jump over potential padding bytes at end of the packet data */
if ( padding ! = 0 ) {
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( ! file_skip ( fh , padding , err ) )
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
block_read + = padding ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Option defaults */
wblock - > packet_header - > opt_comment = NULL ;
wblock - > packet_header - > drop_count = - 1 ;
wblock - > packet_header - > pack_flags = 0 ;
/* FCS length default */
fcslen = pn - > if_fcslen ;
/* Options
* opt_comment 1
* epb_flags 2
* epb_hash 3
* epb_dropcount 4
*/
to_read = block_total_length -
( int ) sizeof ( pcapng_block_header_t ) -
block_read - /* fixed and variable part, including padding */
( int ) sizeof ( bh - > block_total_length ) ;
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = ( char * ) g_try_malloc ( opt_cont_buf_len ) ;
if ( opt_cont_buf_len ! = 0 & & option_content = = NULL ) {
* err = ENOMEM ; /* we assume we're out of memory */
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
while ( to_read ! = 0 ) {
/* read option */
bytes_read = pcapng_read_option ( fh , pn , & oh , option_content , opt_cont_buf_len , to_read , err , err_info ) ;
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_packet_block: failed to read option " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
block_read + = bytes_read ;
to_read - = bytes_read ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* handle option content */
switch ( oh . option_code ) {
case ( OPT_EOFOPT ) :
if ( to_read ! = 0 ) {
pcapng_debug1 ( " pcapng_read_packet_block: %u bytes after opt_endofopt " , to_read ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( OPT_COMMENT ) :
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > packet_header - > presence_flags | = WTAP_HAS_COMMENTS ;
wblock - > packet_header - > opt_comment = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug2 ( " pcapng_read_packet_block: length %u opt_comment '%s' " , oh . option_length , wblock - > packet_header - > opt_comment ) ;
} else {
pcapng_debug1 ( " pcapng_read_packet_block: opt_comment length %u seems strange " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( OPT_EPB_FLAGS ) :
if ( oh . option_length = = 4 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
wblock - > packet_header - > presence_flags | = WTAP_HAS_PACK_FLAGS ;
memcpy ( & wblock - > packet_header - > pack_flags , option_content , sizeof ( guint32 ) ) ;
if ( pn - > byte_swapped )
wblock - > packet_header - > pack_flags = GUINT32_SWAP_LE_BE ( wblock - > packet_header - > pack_flags ) ;
if ( wblock - > packet_header - > pack_flags & 0x000001E0 ) {
/* The FCS length is present */
fcslen = ( wblock - > packet_header - > pack_flags & 0x000001E0 ) > > 5 ;
}
pcapng_debug1 ( " pcapng_read_packet_block: pack_flags %u (ignored) " , wblock - > packet_header - > pack_flags ) ;
} else {
pcapng_debug1 ( " pcapng_read_packet_block: pack_flags length %u not 4 as expected " , oh . option_length ) ;
}
break ;
case ( OPT_EPB_HASH ) :
pcapng_debug2 ( " pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
break ;
case ( OPT_EPB_DROPCOUNT ) :
if ( oh . option_length = = 8 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
wblock - > packet_header - > presence_flags | = WTAP_HAS_DROP_COUNT ;
memcpy ( & wblock - > packet_header - > drop_count , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > packet_header - > drop_count = GUINT64_SWAP_LE_BE ( wblock - > packet_header - > drop_count ) ;
pcapng_debug1 ( " pcapng_read_packet_block: drop_count % " G_GINT64_MODIFIER " u " , wblock - > packet_header - > drop_count ) ;
} else {
pcapng_debug1 ( " pcapng_read_packet_block: drop_count length %u not 8 as expected " , oh . option_length ) ;
}
break ;
default :
pcapng_debug2 ( " pcapng_read_packet_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
g_free ( option_content ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
pcap_read_post_process ( WTAP_FILE_TYPE_SUBTYPE_PCAPNG , iface_info . wtap_encap ,
wblock - > packet_header , ws_buffer_start_ptr ( wblock - > frame_buffer ) ,
pn - > byte_swapped , fcslen ) ;
2014-10-15 23:45:51 +00:00
return TRUE ;
2008-01-19 12:09:00 +00:00
}
2014-10-15 23:45:51 +00:00
static gboolean
2011-04-21 09:41:52 +00:00
pcapng_read_simple_packet_block ( FILE_T fh , pcapng_block_header_t * bh , pcapng_t * pn , wtapng_block_t * wblock , int * err , gchar * * err_info )
2008-01-19 12:09:00 +00:00
{
2014-08-05 20:10:44 +00:00
interface_info_t iface_info ;
pcapng_simple_packet_block_t spb ;
wtapng_simple_packet_t simple_packet ;
guint32 block_total_length ;
guint32 padding ;
int pseudo_header_len ;
/*
* Is this block long enough to be an SPB ?
*/
if ( bh - > block_total_length < MIN_SPB_SIZE ) {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* No .
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_simple_packet_block: total block length %u of an SPB is less than the minimum SPB size %u " ,
bh - > block_total_length , MIN_SPB_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Don't try to allocate memory for a huge number of options, as
that might fail and , even if it succeeds , it might not leave
any address space or memory + backing store for anything else .
We do that by imposing a maximum block size of MAX_BLOCK_SIZE .
We check for this * after * checking the SHB for its byte
order magic number , so that non - pcap - ng files are less
likely to be treated as bad pcap - ng files . */
if ( bh - > block_total_length > MAX_BLOCK_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: total block length %u is too large (> %u) " ,
bh - > block_total_length , MAX_BLOCK_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2013-06-07 08:19:40 +00:00
2014-08-05 20:10:44 +00:00
/* "Simple Packet Block" read fixed part */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & spb , sizeof spb , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_read_simple_packet_block: failed to read packet data " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( 0 > = pn - > interfaces - > len ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: SPB appeared before any IDBs " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
iface_info = g_array_index ( pn - > interfaces , interface_info_t , 0 ) ;
2013-09-28 20:08:39 +00:00
2014-08-05 20:10:44 +00:00
if ( pn - > byte_swapped ) {
simple_packet . packet_len = GUINT32_SWAP_LE_BE ( spb . packet_len ) ;
} else {
simple_packet . packet_len = spb . packet_len ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/*
* The captured length is not a field in the SPB ; it can be
* calculated as the minimum of the snapshot length from the
* IDB and the packet length , as per the pcap - ng spec .
*/
simple_packet . cap_len = simple_packet . packet_len ;
if ( simple_packet . cap_len > iface_info . snap_len )
simple_packet . cap_len = iface_info . snap_len ;
/*
* How much padding is there at the end of the packet data ?
*/
if ( ( simple_packet . cap_len % 4 ) ! = 0 )
padding = 4 - ( simple_packet . cap_len % 4 ) ;
else
padding = 0 ;
/* add padding bytes to "block total length" */
/* (the "block total length" of some example files don't contain the packet data padding bytes!) */
if ( bh - > block_total_length % 4 ) {
block_total_length = bh - > block_total_length + 4 - ( bh - > block_total_length % 4 ) ;
} else {
block_total_length = bh - > block_total_length ;
}
pcapng_debug1 ( " pcapng_read_simple_packet_block: block_total_length %d " , block_total_length ) ;
2013-09-28 21:06:17 +00:00
2014-08-05 20:10:44 +00:00
/*
* Is this block long enough to hold the packet data ?
*/
if ( block_total_length < MIN_SPB_SIZE + simple_packet . cap_len + padding ) {
2013-09-28 21:06:17 +00:00
/*
2014-08-05 20:10:44 +00:00
* No . That means that the problem is with the packet
* length ; the snapshot length can be bigger than the amount
* of packet data in the block , as it ' s a * maximum * length ,
* not a * minimum * length .
2013-09-28 21:06:17 +00:00
*/
2014-08-05 20:10:44 +00:00
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_simple_packet_block: total block length %u of PB is too small for %u bytes of packet data " ,
block_total_length , simple_packet . packet_len ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2013-09-28 21:06:17 +00:00
2014-08-05 20:10:44 +00:00
if ( simple_packet . cap_len > WTAP_MAX_PACKET_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u " ,
simple_packet . cap_len , WTAP_MAX_PACKET_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
pcapng_debug1 ( " pcapng_read_simple_packet_block: packet data: packet_len %u " ,
simple_packet . packet_len ) ;
pcapng_debug1 ( " pcapng_read_simple_packet_block: Need to read pseudo header of size %d " ,
pcap_get_phdr_size ( iface_info . wtap_encap , & wblock - > packet_header - > pseudo_header ) ) ;
/* No time stamp in a simple packet block; no options, either */
wblock - > packet_header - > rec_type = REC_TYPE_PACKET ;
wblock - > packet_header - > presence_flags = WTAP_HAS_CAP_LEN | WTAP_HAS_INTERFACE_ID ;
wblock - > packet_header - > interface_id = 0 ;
wblock - > packet_header - > pkt_encap = iface_info . wtap_encap ;
2014-09-28 18:37:06 +00:00
wblock - > packet_header - > pkt_tsprec = iface_info . tsprecision ;
2014-08-05 20:10:44 +00:00
wblock - > packet_header - > ts . secs = 0 ;
wblock - > packet_header - > ts . nsecs = 0 ;
wblock - > packet_header - > interface_id = 0 ;
wblock - > packet_header - > opt_comment = NULL ;
wblock - > packet_header - > drop_count = 0 ;
wblock - > packet_header - > pack_flags = 0 ;
memset ( ( void * ) & wblock - > packet_header - > pseudo_header , 0 , sizeof ( union wtap_pseudo_header ) ) ;
pseudo_header_len = pcap_process_pseudo_header ( fh ,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG ,
iface_info . wtap_encap ,
simple_packet . cap_len ,
TRUE ,
wblock - > packet_header ,
err ,
err_info ) ;
if ( pseudo_header_len < 0 ) {
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
wblock - > packet_header - > caplen = simple_packet . cap_len - pseudo_header_len ;
wblock - > packet_header - > len = simple_packet . packet_len - pseudo_header_len ;
if ( pseudo_header_len ! = pcap_get_phdr_size ( iface_info . wtap_encap , & wblock - > packet_header - > pseudo_header ) ) {
pcapng_debug1 ( " pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header. " ,
pseudo_header_len ) ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
memset ( ( void * ) & wblock - > packet_header - > pseudo_header , 0 , sizeof ( union wtap_pseudo_header ) ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* "Simple Packet Block" read capture data */
if ( ! wtap_read_packet_bytes ( fh , wblock - > frame_buffer ,
simple_packet . cap_len , err , err_info ) )
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* jump over potential padding bytes at end of the packet data */
if ( ( simple_packet . cap_len % 4 ) ! = 0 ) {
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( ! file_skip ( fh , 4 - ( simple_packet . cap_len % 4 ) , err ) )
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
pcap_read_post_process ( WTAP_FILE_TYPE_SUBTYPE_PCAPNG , iface_info . wtap_encap ,
wblock - > packet_header , ws_buffer_start_ptr ( wblock - > frame_buffer ) ,
pn - > byte_swapped , pn - > if_fcslen ) ;
2014-10-15 23:45:51 +00:00
return TRUE ;
2008-01-13 21:10:09 +00:00
}
2011-03-24 22:47:57 +00:00
# define NRES_ENDOFRECORD 0
# define NRES_IP4RECORD 1
# define NRES_IP6RECORD 2
# define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
/* IPv6 + MAXNAMELEN */
2012-03-04 02:20:25 +00:00
# define INITIAL_NRB_REC_SIZE (16 + 64)
/*
* Find the end of the NUL - terminated name the beginning of which is pointed
* to by p ; record_len is the number of bytes remaining in the record .
*
* Return the length of the name , including the terminating NUL .
*
2013-06-09 02:32:30 +00:00
* If we don ' t find a terminating NUL , return - 1 and set * err and
2012-03-04 02:20:25 +00:00
* * err_info appropriately .
*/
static int
2013-06-21 02:59:54 +00:00
name_resolution_block_find_name_end ( const char * p , guint record_len , int * err ,
2014-08-05 20:10:44 +00:00
gchar * * err_info )
2012-03-04 02:20:25 +00:00
{
2014-08-05 20:10:44 +00:00
int namelen ;
namelen = 0 ;
for ( ; ; ) {
if ( record_len = = 0 ) {
/*
* We ran out of bytes in the record without
* finding a NUL .
*/
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup ( " pcapng_read_name_resolution_block: NRB record has non-null-terminated host name " ) ;
return - 1 ;
}
if ( * p = = ' \0 ' )
break ; /* that's the terminating NUL */
p + + ;
record_len - - ;
namelen + + ; /* count this byte */
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Include the NUL in the name length. */
return namelen + 1 ;
2012-03-04 02:20:25 +00:00
}
2014-10-15 23:45:51 +00:00
static gboolean
2011-04-21 09:41:52 +00:00
pcapng_read_name_resolution_block ( FILE_T fh , pcapng_block_header_t * bh , pcapng_t * pn , wtapng_block_t * wblock _U_ , int * err , gchar * * err_info )
2011-03-24 22:47:57 +00:00
{
2014-10-15 23:45:51 +00:00
int block_read ;
2014-08-05 20:10:44 +00:00
int to_read ;
pcapng_name_resolution_block_t nrb ;
Buffer nrb_rec ;
guint32 v4_addr ;
guint record_len ;
char * namep ;
int namelen ;
/*
* Is this block long enough to be an NRB ?
*/
if ( bh - > block_total_length < MIN_NRB_SIZE ) {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* No .
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_name_resolution_block: total block length %u of an NRB is less than the minimum NRB size %u " ,
bh - > block_total_length , MIN_NRB_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Don't try to allocate memory for a huge number of options, as
that might fail and , even if it succeeds , it might not leave
any address space or memory + backing store for anything else .
We do that by imposing a maximum block size of MAX_BLOCK_SIZE .
We check for this * after * checking the SHB for its byte
order magic number , so that non - pcap - ng files are less
likely to be treated as bad pcap - ng files . */
if ( bh - > block_total_length > MAX_BLOCK_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: total block length %u is too large (> %u) " ,
bh - > block_total_length , MAX_BLOCK_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2013-06-07 08:19:40 +00:00
2014-08-05 20:10:44 +00:00
to_read = bh - > block_total_length - 8 - 4 ; /* We have read the header adn should not read the final block_total_length */
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_read_name_resolution_block, total %d bytes " , bh - > block_total_length ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/*
* Start out with a buffer big enough for an IPv6 address and one
* 64 - byte name ; we ' ll make the buffer bigger if necessary .
*/
ws_buffer_init ( & nrb_rec , INITIAL_NRB_REC_SIZE ) ;
2014-10-15 23:45:51 +00:00
block_read = 0 ;
2014-08-05 20:10:44 +00:00
while ( block_read < to_read ) {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* There must be at least one record ' s worth of data
* here .
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
if ( ( size_t ) ( to_read - block_read ) < sizeof nrb ) {
ws_buffer_free ( & nrb_rec ) ;
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u " ,
to_read - block_read ,
( guint ) sizeof nrb ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & nrb , sizeof nrb , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
ws_buffer_free ( & nrb_rec ) ;
pcapng_debug0 ( " pcapng_read_name_resolution_block: failed to read record header " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
block_read + = ( int ) sizeof nrb ;
2014-08-05 20:10:44 +00:00
if ( pn - > byte_swapped ) {
nrb . record_type = GUINT16_SWAP_LE_BE ( nrb . record_type ) ;
nrb . record_len = GUINT16_SWAP_LE_BE ( nrb . record_len ) ;
}
if ( to_read - block_read < nrb . record_len + PADDING4 ( nrb . record_len ) ) {
ws_buffer_free ( & nrb_rec ) ;
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u " ,
to_read - block_read ,
nrb . record_len + PADDING4 ( nrb . record_len ) ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
switch ( nrb . record_type ) {
case NRES_ENDOFRECORD :
/* There shouldn't be any more data */
to_read = 0 ;
break ;
case NRES_IP4RECORD :
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* The smallest possible record must have
* a 4 - byte IPv4 address , hence a minimum
* of 4 bytes .
*
* ( The pcap - NG spec really indicates
* that it must be at least 5 bytes ,
* as there must be at least one name ,
* and it really must be at least 6
* bytes , as the name mustn ' t be null ,
* but there ' s no need to fail if there
* aren ' t any names at all , and we
* should report a null name as such . )
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
if ( nrb . record_len < 4 ) {
ws_buffer_free ( & nrb_rec ) ;
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4 " ,
nrb . record_len ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
ws_buffer_assure_space ( & nrb_rec , nrb . record_len ) ;
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , ws_buffer_start_ptr ( & nrb_rec ) ,
2014-10-07 07:39:54 +00:00
nrb . record_len , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
ws_buffer_free ( & nrb_rec ) ;
pcapng_debug0 ( " pcapng_read_name_resolution_block: failed to read IPv4 record data " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
block_read + = nrb . record_len ;
2014-08-05 20:10:44 +00:00
if ( pn - > add_new_ipv4 ) {
/*
* Scan through all the names in
* the record and add them .
*/
memcpy ( & v4_addr ,
ws_buffer_start_ptr ( & nrb_rec ) , 4 ) ;
if ( pn - > byte_swapped )
v4_addr = GUINT32_SWAP_LE_BE ( v4_addr ) ;
for ( namep = ( char * ) ws_buffer_start_ptr ( & nrb_rec ) + 4 , record_len = nrb . record_len - 4 ;
record_len ! = 0 ;
namep + = namelen , record_len - = namelen ) {
/*
* Scan forward for a null
* byte .
*/
namelen = name_resolution_block_find_name_end ( namep , record_len , err , err_info ) ;
if ( namelen = = - 1 ) {
ws_buffer_free ( & nrb_rec ) ;
2014-10-15 23:45:51 +00:00
return FALSE ; /* fail */
2014-08-05 20:10:44 +00:00
}
pn - > add_new_ipv4 ( v4_addr , namep ) ;
}
}
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( ! file_skip ( fh , PADDING4 ( nrb . record_len ) , err ) ) {
2014-08-05 20:10:44 +00:00
ws_buffer_free ( & nrb_rec ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
block_read + = PADDING4 ( nrb . record_len ) ;
break ;
case NRES_IP6RECORD :
/*
* The smallest possible record must have
* a 16 - byte IPv6 address , hence a minimum
* of 16 bytes .
*
* ( The pcap - NG spec really indicates
* that it must be at least 17 bytes ,
* as there must be at least one name ,
* and it really must be at least 18
* bytes , as the name mustn ' t be null ,
* but there ' s no need to fail if there
* aren ' t any names at all , and we
* should report a null name as such . )
*/
if ( nrb . record_len < 16 ) {
ws_buffer_free ( & nrb_rec ) ;
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16 " ,
nrb . record_len ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
if ( to_read < nrb . record_len ) {
ws_buffer_free ( & nrb_rec ) ;
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_name_resolution_block: NRB record length for IPv6 record %u > remaining data in NRB " ,
nrb . record_len ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
ws_buffer_assure_space ( & nrb_rec , nrb . record_len ) ;
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , ws_buffer_start_ptr ( & nrb_rec ) ,
2014-10-07 07:39:54 +00:00
nrb . record_len , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
ws_buffer_free ( & nrb_rec ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
block_read + = nrb . record_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( pn - > add_new_ipv6 ) {
for ( namep = ( char * ) ws_buffer_start_ptr ( & nrb_rec ) + 16 , record_len = nrb . record_len - 16 ;
record_len ! = 0 ;
namep + = namelen , record_len - = namelen ) {
/*
* Scan forward for a null
* byte .
*/
namelen = name_resolution_block_find_name_end ( namep , record_len , err , err_info ) ;
if ( namelen = = - 1 ) {
ws_buffer_free ( & nrb_rec ) ;
2014-10-15 23:45:51 +00:00
return FALSE ; /* fail */
2014-08-05 20:10:44 +00:00
}
pn - > add_new_ipv6 ( ws_buffer_start_ptr ( & nrb_rec ) ,
namep ) ;
}
2012-03-12 15:43:59 +00:00
}
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( ! file_skip ( fh , PADDING4 ( nrb . record_len ) , err ) ) {
2014-08-05 20:10:44 +00:00
ws_buffer_free ( & nrb_rec ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
block_read + = PADDING4 ( nrb . record_len ) ;
break ;
default :
pcapng_debug1 ( " pcapng_read_name_resolution_block: unknown record type 0x%x " , nrb . record_type ) ;
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( ! file_skip ( fh , nrb . record_len + PADDING4 ( nrb . record_len ) , err ) ) {
2014-08-05 20:10:44 +00:00
ws_buffer_free ( & nrb_rec ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
block_read + = nrb . record_len + PADDING4 ( nrb . record_len ) ;
break ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
ws_buffer_free ( & nrb_rec ) ;
2014-10-15 23:45:51 +00:00
return TRUE ;
2011-03-24 22:47:57 +00:00
}
2014-10-15 23:45:51 +00:00
static gboolean
2011-04-21 09:41:52 +00:00
pcapng_read_interface_statistics_block ( FILE_T fh , pcapng_block_header_t * bh , pcapng_t * pn , wtapng_block_t * wblock , int * err , gchar * * err_info )
2009-04-25 19:11:35 +00:00
{
2014-08-05 20:10:44 +00:00
int bytes_read ;
guint to_read , opt_cont_buf_len ;
pcapng_interface_statistics_block_t isb ;
pcapng_option_header_t oh ;
char * option_content = NULL ; /* Allocate as large as the options block */
/*
* Is this block long enough to be an ISB ?
*/
if ( bh - > block_total_length < MIN_ISB_SIZE ) {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* No .
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_interface_statistics_block: total block length %u is too small (< %u) " ,
bh - > block_total_length , MIN_ISB_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Don't try to allocate memory for a huge number of options, as
that might fail and , even if it succeeds , it might not leave
any address space or memory + backing store for anything else .
We do that by imposing a maximum block size of MAX_BLOCK_SIZE .
We check for this * after * checking the SHB for its byte
order magic number , so that non - pcap - ng files are less
likely to be treated as bad pcap - ng files . */
if ( bh - > block_total_length > MAX_BLOCK_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: total block length %u is too large (> %u) " ,
bh - > block_total_length , MAX_BLOCK_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2013-06-07 08:19:40 +00:00
2014-08-05 20:10:44 +00:00
/* "Interface Statistics Block" read fixed part */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & isb , sizeof isb , err , err_info ) ) {
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_read_interface_statistics_block: failed to read packet data " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
if ( pn - > byte_swapped ) {
wblock - > data . if_stats . interface_id = GUINT32_SWAP_LE_BE ( isb . interface_id ) ;
wblock - > data . if_stats . ts_high = GUINT32_SWAP_LE_BE ( isb . timestamp_high ) ;
wblock - > data . if_stats . ts_low = GUINT32_SWAP_LE_BE ( isb . timestamp_low ) ;
} else {
wblock - > data . if_stats . interface_id = isb . interface_id ;
wblock - > data . if_stats . ts_high = isb . timestamp_high ;
wblock - > data . if_stats . ts_low = isb . timestamp_low ;
}
pcapng_debug1 ( " pcapng_read_interface_statistics_block: interface_id %u " , wblock - > data . if_stats . interface_id ) ;
/* Option defaults */
wblock - > data . if_stats . opt_comment = NULL ;
wblock - > data . if_stats . isb_ifrecv = - 1 ;
wblock - > data . if_stats . isb_ifdrop = - 1 ;
wblock - > data . if_stats . isb_filteraccept = - 1 ;
wblock - > data . if_stats . isb_osdrop = - 1 ;
wblock - > data . if_stats . isb_usrdeliv = - 1 ;
/* Options */
to_read = bh - > block_total_length -
2014-10-15 23:45:51 +00:00
( MIN_BLOCK_SIZE + ( guint ) sizeof isb ) ; /* fixed and variable part, including padding */
2014-08-05 20:10:44 +00:00
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = ( char * ) g_try_malloc ( opt_cont_buf_len ) ;
if ( opt_cont_buf_len ! = 0 & & option_content = = NULL ) {
* err = ENOMEM ; /* we assume we're out of memory */
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
while ( to_read ! = 0 ) {
/* read option */
bytes_read = pcapng_read_option ( fh , pn , & oh , option_content , opt_cont_buf_len , to_read , err , err_info ) ;
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_interface_statistics_block: failed to read option " ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
to_read - = bytes_read ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* handle option content */
switch ( oh . option_code ) {
case ( 0 ) : /* opt_endofopt */
if ( to_read ! = 0 ) {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: %u bytes after opt_endofopt " , to_read ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( 1 ) : /* opt_comment */
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . if_stats . opt_comment = g_strndup ( option_content , oh . option_length ) ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: opt_comment %s " , wblock - > data . if_stats . opt_comment ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: opt_comment length %u seems strange " , oh . option_length ) ;
}
break ;
case ( 2 ) : /* isb_starttime */
if ( oh . option_length = = 8 ) {
guint32 high , low ;
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & high , option_content , sizeof ( guint32 ) ) ;
memcpy ( & low , option_content + sizeof ( guint32 ) , sizeof ( guint32 ) ) ;
if ( pn - > byte_swapped ) {
high = GUINT32_SWAP_LE_BE ( high ) ;
low = GUINT32_SWAP_LE_BE ( low ) ;
}
wblock - > data . if_stats . isb_starttime = ( guint64 ) high ;
wblock - > data . if_stats . isb_starttime < < = 32 ;
wblock - > data . if_stats . isb_starttime + = ( guint64 ) low ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_starttime % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_starttime ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected " , oh . option_length ) ;
}
break ;
case ( 3 ) : /* isb_endtime */
if ( oh . option_length = = 8 ) {
guint32 high , low ;
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & high , option_content , sizeof ( guint32 ) ) ;
memcpy ( & low , option_content + sizeof ( guint32 ) , sizeof ( guint32 ) ) ;
if ( pn - > byte_swapped ) {
high = GUINT32_SWAP_LE_BE ( high ) ;
low = GUINT32_SWAP_LE_BE ( low ) ;
}
wblock - > data . if_stats . isb_endtime = ( guint64 ) high ;
wblock - > data . if_stats . isb_endtime < < = 32 ;
wblock - > data . if_stats . isb_endtime + = ( guint64 ) low ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_endtime % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_endtime ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected " , oh . option_length ) ;
}
break ;
case ( 4 ) : /* isb_ifrecv */
if ( oh . option_length = = 8 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & wblock - > data . if_stats . isb_ifrecv , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_stats . isb_ifrecv = GUINT64_SWAP_LE_BE ( wblock - > data . if_stats . isb_ifrecv ) ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_ifrecv % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_ifrecv ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected " , oh . option_length ) ;
}
break ;
case ( 5 ) : /* isb_ifdrop */
if ( oh . option_length = = 8 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & wblock - > data . if_stats . isb_ifdrop , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_stats . isb_ifdrop = GUINT64_SWAP_LE_BE ( wblock - > data . if_stats . isb_ifdrop ) ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_ifdrop % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_ifdrop ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected " , oh . option_length ) ;
}
break ;
case ( 6 ) : /* isb_filteraccept 6 */
if ( oh . option_length = = 8 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & wblock - > data . if_stats . isb_filteraccept , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_stats . isb_ifdrop = GUINT64_SWAP_LE_BE ( wblock - > data . if_stats . isb_filteraccept ) ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_filteraccept % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_filteraccept ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected " , oh . option_length ) ;
}
break ;
case ( 7 ) : /* isb_osdrop 7 */
if ( oh . option_length = = 8 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & wblock - > data . if_stats . isb_osdrop , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_stats . isb_osdrop = GUINT64_SWAP_LE_BE ( wblock - > data . if_stats . isb_osdrop ) ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_osdrop % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_osdrop ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected " , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
case ( 8 ) : /* isb_usrdeliv 8 */
if ( oh . option_length = = 8 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & wblock - > data . if_stats . isb_usrdeliv , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_stats . isb_usrdeliv = GUINT64_SWAP_LE_BE ( wblock - > data . if_stats . isb_osdrop ) ;
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_usrdeliv % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_usrdeliv ) ;
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected " , oh . option_length ) ;
}
break ;
default :
pcapng_debug2 ( " pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
g_free ( option_content ) ;
2012-03-12 15:43:59 +00:00
2014-10-15 23:45:51 +00:00
return TRUE ;
2009-04-25 19:11:35 +00:00
}
2008-01-13 21:10:09 +00:00
2014-10-15 23:45:51 +00:00
static gboolean
2012-02-23 10:03:16 +00:00
pcapng_read_unknown_block ( FILE_T fh , pcapng_block_header_t * bh , pcapng_t * pn _U_ , wtapng_block_t * wblock _U_ , int * err , gchar * * err_info )
2008-01-19 12:09:00 +00:00
{
2014-08-05 20:10:44 +00:00
int block_read ;
guint32 block_total_length ;
2014-05-24 20:57:11 +00:00
# ifdef HAVE_PLUGINS
2014-08-05 20:10:44 +00:00
block_handler * handler ;
2014-05-24 20:57:11 +00:00
# endif
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( bh - > block_total_length < MIN_BLOCK_SIZE ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng_read_unknown_block: total block length %u of an unknown block type is less than the minimum block size %u " ,
bh - > block_total_length , MIN_BLOCK_SIZE ) ;
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* add padding bytes to "block total length" */
/* (the "block total length" of some example files don't contain any padding bytes!) */
if ( bh - > block_total_length % 4 ) {
block_total_length = bh - > block_total_length + 4 - ( bh - > block_total_length % 4 ) ;
} else {
block_total_length = bh - > block_total_length ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
block_read = block_total_length - MIN_BLOCK_SIZE ;
2012-03-12 15:43:59 +00:00
2014-05-24 20:57:11 +00:00
# ifdef HAVE_PLUGINS
2014-08-05 20:10:44 +00:00
/*
* Do we have a handler for this block type ?
*/
2014-10-14 20:41:36 +00:00
if ( block_handlers ! = NULL & &
( handler = ( block_handler * ) g_hash_table_lookup ( block_handlers ,
GUINT_TO_POINTER ( bh - > block_type ) ) ) ! = NULL ) {
2014-08-05 20:10:44 +00:00
/* Yes - call it to read this block type. */
if ( ! handler - > read ( fh , block_read , pn - > byte_swapped ,
wblock - > packet_header , wblock - > frame_buffer ,
err , err_info ) )
2014-10-15 23:45:51 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
} else
2014-05-24 20:57:11 +00:00
# endif
2014-08-05 20:10:44 +00:00
{
/* No. Skip over this unknown block. */
if ( ! file_skip ( fh , block_read , err ) ) {
2014-10-15 23:45:51 +00:00
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-10-15 23:45:51 +00:00
return TRUE ;
2008-01-19 12:09:00 +00:00
}
2008-01-13 21:10:09 +00:00
2009-06-27 17:33:23 +00:00
2014-10-15 23:45:51 +00:00
static block_return_val
pcapng_read_block ( wtap * wth , FILE_T fh , pcapng_t * pn , wtapng_block_t * wblock , int * err , gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
2014-10-15 23:45:51 +00:00
block_return_val ret ;
2014-08-05 20:10:44 +00:00
pcapng_block_header_t bh ;
guint32 block_total_length ;
2012-03-12 15:43:59 +00:00
2014-09-24 13:07:50 +00:00
memset ( & ( wblock - > data ) , 0 , sizeof ( wblock - > data ) ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Try to read the (next) block header */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes_or_eof ( fh , & bh , sizeof bh , err , err_info ) ) {
pcapng_debug1 ( " pcapng_read_block: wtap_read_bytes_or_eof() failed, err = %d. " , * err ) ;
if ( * err = = 0 | | * err = = WTAP_ERR_SHORT_READ ) {
2014-10-15 23:45:51 +00:00
/*
* Short read or EOF .
*
* If we ' re reading this as part of an open ,
* the file is too short to be a pcap - ng file .
*
* If we ' re not , we treat PCAPNG_BLOCK_NOT_SHB and
* PCAPNG_BLOCK_ERROR the same , so we can just return
* PCAPNG_BLOCK_NOT_SHB in both cases .
*/
return PCAPNG_BLOCK_NOT_SHB ;
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
}
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( pn - > byte_swapped ) {
bh . block_type = GUINT32_SWAP_LE_BE ( bh . block_type ) ;
bh . block_total_length = GUINT32_SWAP_LE_BE ( bh . block_total_length ) ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
wblock - > type = bh . block_type ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_read_block: block_type 0x%x " , bh . block_type ) ;
2012-03-12 15:43:59 +00:00
2014-10-15 23:45:51 +00:00
/*
* SHBs have to be treated differently from other blocks , as we
* might be doing an open and attempting to read a block at the
* beginning of the file to see if it ' s a pcap - ng file or not .
*/
if ( bh . block_type = = BLOCK_TYPE_SHB ) {
ret = pcapng_read_section_header_block ( fh , & bh , pn , wblock , err , err_info ) ;
if ( ret ! = PCAPNG_BLOCK_OK ) {
return ret ;
}
} else {
if ( ! pn - > shb_read ) {
/*
* No SHB seen yet , so we ' re trying to read the first block
2014-10-16 01:15:15 +00:00
* during an open , to see whether it ' s an SHB ; if what we
* read doesn ' t look like an SHB , this isn ' t a pcap - ng file .
2014-10-15 23:45:51 +00:00
*/
2014-10-16 01:15:15 +00:00
* err = 0 ;
* err_info = NULL ;
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_NOT_SHB ;
}
switch ( bh . block_type ) {
case ( BLOCK_TYPE_IDB ) :
if ( ! pcapng_read_if_descr_block ( wth , fh , & bh , pn , wblock , err , err_info ) )
return PCAPNG_BLOCK_ERROR ;
break ;
case ( BLOCK_TYPE_PB ) :
if ( ! pcapng_read_packet_block ( fh , & bh , pn , wblock , err , err_info , FALSE ) )
return PCAPNG_BLOCK_ERROR ;
break ;
case ( BLOCK_TYPE_SPB ) :
if ( ! pcapng_read_simple_packet_block ( fh , & bh , pn , wblock , err , err_info ) )
return PCAPNG_BLOCK_ERROR ;
break ;
case ( BLOCK_TYPE_EPB ) :
if ( ! pcapng_read_packet_block ( fh , & bh , pn , wblock , err , err_info , TRUE ) )
return PCAPNG_BLOCK_ERROR ;
break ;
case ( BLOCK_TYPE_NRB ) :
if ( ! pcapng_read_name_resolution_block ( fh , & bh , pn , wblock , err , err_info ) )
return PCAPNG_BLOCK_ERROR ;
break ;
case ( BLOCK_TYPE_ISB ) :
if ( ! pcapng_read_interface_statistics_block ( fh , & bh , pn , wblock , err , err_info ) )
return PCAPNG_BLOCK_ERROR ;
break ;
default :
pcapng_debug2 ( " pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d " , bh . block_type , bh . block_total_length ) ;
if ( ! pcapng_read_unknown_block ( fh , & bh , pn , wblock , err , err_info ) )
return PCAPNG_BLOCK_ERROR ;
break ;
}
2014-08-05 20:10:44 +00:00
}
/* sanity check: first and second block lengths must match */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes ( fh , & block_total_length , sizeof block_total_length ,
2014-10-07 07:39:54 +00:00
err , err_info ) ) {
2014-10-15 23:45:51 +00:00
pcapng_debug0 ( " pcapng_check_block_trailer: couldn't read second block length " ) ;
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( pn - > byte_swapped )
block_total_length = GUINT32_SWAP_LE_BE ( block_total_length ) ;
2012-03-12 15:43:59 +00:00
2014-10-15 23:45:51 +00:00
if ( block_total_length ! = bh . block_total_length ) {
2014-08-05 20:10:44 +00:00
* err = WTAP_ERR_BAD_FILE ;
2014-10-15 23:45:51 +00:00
* err_info = g_strdup_printf ( " pcapng_check_block_trailer: total block lengths (first %u and second %u) don't match " ,
2014-08-05 20:10:44 +00:00
bh . block_total_length , block_total_length ) ;
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_ERROR ;
2014-08-05 20:10:44 +00:00
}
2014-10-15 23:45:51 +00:00
return PCAPNG_BLOCK_OK ;
2008-01-13 21:10:09 +00:00
}
2012-10-12 03:55:10 +00:00
/* Process an IDB that we've just read. */
static void
pcapng_process_idb ( wtap * wth , pcapng_t * pcapng , wtapng_block_t * wblock )
{
2014-08-05 20:10:44 +00:00
wtapng_if_descr_t int_data ;
interface_info_t iface_info ;
int_data . wtap_encap = wblock - > data . if_descr . wtap_encap ;
int_data . time_units_per_second = wblock - > data . if_descr . time_units_per_second ;
int_data . link_type = wblock - > data . if_descr . link_type ;
int_data . snap_len = wblock - > data . if_descr . snap_len ;
/* Options */
int_data . opt_comment = wblock - > data . if_descr . opt_comment ;
int_data . if_name = wblock - > data . if_descr . if_name ;
int_data . if_description = wblock - > data . if_descr . if_description ;
/* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
/* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
/* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
/* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
int_data . if_speed = wblock - > data . if_descr . if_speed ;
int_data . if_tsresol = wblock - > data . if_descr . if_tsresol ;
/* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
int_data . if_filter_str = wblock - > data . if_descr . if_filter_str ;
int_data . bpf_filter_len = wblock - > data . if_descr . bpf_filter_len ;
int_data . if_filter_bpf_bytes = wblock - > data . if_descr . if_filter_bpf_bytes ;
int_data . if_os = wblock - > data . if_descr . if_os ;
int_data . if_fcslen = wblock - > data . if_descr . if_fcslen ;
/* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
/* Interface statistics */
int_data . num_stat_entries = 0 ;
int_data . interface_statistics = NULL ;
g_array_append_val ( wth - > interface_data , int_data ) ;
iface_info . wtap_encap = wblock - > data . if_descr . wtap_encap ;
iface_info . snap_len = wblock - > data . if_descr . snap_len ;
iface_info . time_units_per_second = wblock - > data . if_descr . time_units_per_second ;
2014-09-28 18:37:06 +00:00
iface_info . tsprecision = wblock - > data . if_descr . tsprecision ;
2014-08-05 20:10:44 +00:00
g_array_append_val ( pcapng - > interfaces , iface_info ) ;
2012-10-12 03:55:10 +00:00
}
2008-01-13 21:10:09 +00:00
/* classic wtap: open capture file */
2014-10-09 23:44:15 +00:00
wtap_open_return_val
2014-05-09 05:18:49 +00:00
pcapng_open ( wtap * wth , int * err , gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_t pn ;
wtapng_block_t wblock ;
pcapng_t * pcapng ;
pcapng_block_header_t bh ;
gint64 saved_offset ;
pn . shb_read = FALSE ;
/* we don't know the byte swapping of the file yet */
pn . byte_swapped = FALSE ;
pn . if_fcslen = - 1 ;
pn . version_major = - 1 ;
pn . version_minor = - 1 ;
2014-10-15 23:55:54 +00:00
pn . interfaces = NULL ;
2014-08-05 20:10:44 +00:00
/* we don't expect any packet blocks yet */
wblock . frame_buffer = NULL ;
wblock . packet_header = NULL ;
pcapng_debug0 ( " pcapng_open: opening file " ) ;
/* read first block */
2014-10-15 23:45:51 +00:00
switch ( pcapng_read_block ( wth , wth - > fh , & pn , & wblock , err , err_info ) ) {
case PCAPNG_BLOCK_OK :
/* No problem */
break ;
case PCAPNG_BLOCK_NOT_SHB :
/* An error indicating that this isn't a pcap-ng file. */
2014-09-22 11:43:14 +00:00
pcapng_free_wtapng_block_data ( & wblock ) ;
2014-10-15 23:45:51 +00:00
g_free ( * err_info ) ; /* We don't care why */
* err = 0 ;
* err_info = NULL ;
2014-10-09 23:44:15 +00:00
return WTAP_OPEN_NOT_MINE ;
2014-10-15 23:45:51 +00:00
case PCAPNG_BLOCK_ERROR :
/* An I/O error, or this probably *is* a pcap-ng file but not a valid one. */
pcapng_free_wtapng_block_data ( & wblock ) ;
return WTAP_OPEN_ERROR ;
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* first block must be a "Section Header Block" */
if ( wblock . type ! = BLOCK_TYPE_SHB ) {
2012-03-12 15:43:59 +00:00
/*
2014-08-05 20:10:44 +00:00
* XXX - check for damage from transferring a file
* between Windows and UN * X as text rather than
* binary data ?
2012-03-12 15:43:59 +00:00
*/
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_open: first block type %u not SHB " , wblock . type ) ;
2014-09-22 11:43:14 +00:00
pcapng_free_wtapng_block_data ( & wblock ) ;
2014-10-09 23:44:15 +00:00
return WTAP_OPEN_NOT_MINE ;
2014-08-05 20:10:44 +00:00
}
pn . shb_read = TRUE ;
/*
* At this point , we ' ve decided this is a pcap - NG file , not
2014-10-15 23:55:54 +00:00
* some other type of file , so we can ' t return WTAP_OPEN_NOT_MINE
* past this point .
2014-08-05 20:10:44 +00:00
*/
wth - > shb_hdr . opt_comment = wblock . data . section . opt_comment ;
wth - > shb_hdr . shb_hardware = wblock . data . section . shb_hardware ;
wth - > shb_hdr . shb_os = wblock . data . section . shb_os ;
wth - > shb_hdr . shb_user_appl = wblock . data . section . shb_user_appl ;
wth - > file_encap = WTAP_ENCAP_UNKNOWN ;
wth - > snapshot_length = 0 ;
2014-09-28 18:37:06 +00:00
wth - > file_tsprec = WTAP_TSPREC_UNKNOWN ;
2014-08-05 20:10:44 +00:00
pcapng = ( pcapng_t * ) g_malloc ( sizeof ( pcapng_t ) ) ;
wth - > priv = ( void * ) pcapng ;
* pcapng = pn ;
2014-10-15 23:55:54 +00:00
pcapng - > interfaces = g_array_new ( FALSE , FALSE , sizeof ( interface_info_t ) ) ;
2014-08-05 20:10:44 +00:00
wth - > subtype_read = pcapng_read ;
wth - > subtype_seek_read = pcapng_seek_read ;
wth - > subtype_close = pcapng_close ;
wth - > file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG ;
/* Loop over all IDB:s that appear before any packets */
while ( 1 ) {
/* peek at next block */
/* Try to read the (next) block header */
saved_offset = file_tell ( wth - > fh ) ;
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
if ( ! wtap_read_bytes_or_eof ( wth - > fh , & bh , sizeof bh , err , err_info ) ) {
if ( * err = = 0 ) {
2014-10-07 05:01:12 +00:00
/* EOF */
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
pcapng_debug0 ( " No more IDBs available... " ) ;
break ;
}
pcapng_debug1 ( " pcapng_open: Check for more IDB:s, wtap_read_bytes_or_eof() failed, err = %d. " , * err ) ;
2014-10-09 23:44:15 +00:00
return WTAP_OPEN_ERROR ;
2014-08-05 20:10:44 +00:00
}
2012-07-27 18:43:53 +00:00
2014-08-05 20:10:44 +00:00
/* go back to where we were */
file_seek ( wth - > fh , saved_offset , SEEK_SET , err ) ;
2012-07-27 18:43:53 +00:00
2014-08-05 20:10:44 +00:00
if ( pn . byte_swapped ) {
bh . block_type = GUINT32_SWAP_LE_BE ( bh . block_type ) ;
}
2012-07-27 18:43:53 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_open: Check for more IDB:s block_type 0x%x " , bh . block_type ) ;
2012-07-27 18:43:53 +00:00
2014-08-05 20:10:44 +00:00
if ( bh . block_type ! = BLOCK_TYPE_IDB ) {
break ; /* No more IDB:s */
}
2014-10-15 23:45:51 +00:00
if ( pcapng_read_block ( wth , wth - > fh , & pn , & wblock , err , err_info ) ! = PCAPNG_BLOCK_OK ) {
if ( * err = = 0 ) {
pcapng_debug0 ( " No more IDBs available... " ) ;
pcapng_free_wtapng_block_data ( & wblock ) ;
break ;
} else {
pcapng_debug0 ( " pcapng_open: couldn't read IDB " ) ;
pcapng_free_wtapng_block_data ( & wblock ) ;
return WTAP_OPEN_ERROR ;
}
2014-08-05 20:10:44 +00:00
}
pcapng_process_idb ( wth , pcapng , & wblock ) ;
pcapng_debug2 ( " pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i " ,
Add some higher-level file-read APIs and use them.
Add wtap_read_bytes(), which takes a FILE_T, a pointer, a byte count, an
error number pointer, and an error string pointer as arguments, and that
treats a short read of any sort, including a read that returns 0 bytes,
as a WTAP_ERR_SHORT_READ error, and that returns the error number and
string through its last two arguments.
Add wtap_read_bytes_or_eof(), which is similar, but that treats a read
that returns 0 bytes as an EOF, supplying an error number of 0 as an EOF
indication.
Use those in file readers; that simplifies the code and makes it less
likely that somebody will fail to supply the error number and error
string on a file read error.
Change-Id: Ia5dba2a6f81151e87b614461349d611cffc16210
Reviewed-on: https://code.wireshark.org/review/4512
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-10-07 01:00:57 +00:00
wth - > interface_data - > len , wth - > file_encap ) ;
2014-08-05 20:10:44 +00:00
}
2014-10-09 23:44:15 +00:00
return WTAP_OPEN_MINE ;
2008-01-13 21:10:09 +00:00
}
/* classic wtap: read packet */
2014-05-23 10:50:02 +00:00
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_read ( wtap * wth , int * err , gchar * * err_info , gint64 * data_offset )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_t * pcapng = ( pcapng_t * ) wth - > priv ;
wtapng_block_t wblock ;
wtapng_if_descr_t * wtapng_if_descr ;
wtapng_if_stats_t if_stats ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
wblock . frame_buffer = wth - > frame_buffer ;
wblock . packet_header = & wth - > phdr ;
pcapng - > add_new_ipv4 = wth - > add_new_ipv4 ;
pcapng - > add_new_ipv6 = wth - > add_new_ipv6 ;
/* read next block */
while ( 1 ) {
2014-10-14 23:39:17 +00:00
* data_offset = file_tell ( wth - > fh ) ;
pcapng_debug1 ( " pcapng_read: data_offset is % " G_GINT64_MODIFIER " d " , * data_offset ) ;
2014-10-15 23:45:51 +00:00
if ( pcapng_read_block ( wth , wth - > fh , pcapng , & wblock , err , err_info ) ! = PCAPNG_BLOCK_OK ) {
2014-08-05 20:10:44 +00:00
pcapng_debug1 ( " pcapng_read: data_offset is finally % " G_GINT64_MODIFIER " d " , * data_offset ) ;
pcapng_debug0 ( " pcapng_read: couldn't read packet block " ) ;
return FALSE ;
}
switch ( wblock . type ) {
case ( BLOCK_TYPE_SHB ) :
/* We don't currently support multi-section files. */
wth - > phdr . pkt_encap = WTAP_ENCAP_UNKNOWN ;
2014-09-28 18:37:06 +00:00
wth - > phdr . pkt_tsprec = WTAP_TSPREC_UNKNOWN ;
2014-08-05 20:10:44 +00:00
* err = WTAP_ERR_UNSUPPORTED ;
* err_info = g_strdup_printf ( " pcapng: multi-section files not currently supported " ) ;
return FALSE ;
case ( BLOCK_TYPE_PB ) :
case ( BLOCK_TYPE_SPB ) :
case ( BLOCK_TYPE_EPB ) :
/* packet block - we've found a packet */
goto got_packet ;
case ( BLOCK_TYPE_IDB ) :
/* A new interface */
pcapng_debug0 ( " pcapng_read: block type BLOCK_TYPE_IDB " ) ;
pcapng_process_idb ( wth , pcapng , & wblock ) ;
break ;
case ( BLOCK_TYPE_NRB ) :
/* More name resolution entries */
pcapng_debug0 ( " pcapng_read: block type BLOCK_TYPE_NRB " ) ;
break ;
case ( BLOCK_TYPE_ISB ) :
/* Another interface statistics report */
pcapng_debug0 ( " pcapng_read: block type BLOCK_TYPE_ISB " ) ;
if ( wth - > interface_data - > len < wblock . data . if_stats . interface_id ) {
pcapng_debug1 ( " pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u > number_of_interfaces " , wblock . data . if_stats . interface_id ) ;
} else {
/* Get the interface description */
wtapng_if_descr = & g_array_index ( wth - > interface_data , wtapng_if_descr_t , wblock . data . if_stats . interface_id ) ;
if ( wtapng_if_descr - > num_stat_entries = = 0 ) {
/* First ISB found, no previous entry */
pcapng_debug0 ( " pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry " ) ;
wtapng_if_descr - > interface_statistics = g_array_new ( FALSE , FALSE , sizeof ( wtapng_if_stats_t ) ) ;
}
if_stats . interface_id = wblock . data . if_stats . interface_id ;
if_stats . ts_high = wblock . data . if_stats . ts_high ;
if_stats . ts_low = wblock . data . if_stats . ts_low ;
/* options */
if_stats . opt_comment = wblock . data . if_stats . opt_comment ; /* NULL if not available */
if_stats . isb_starttime = wblock . data . if_stats . isb_starttime ;
if_stats . isb_endtime = wblock . data . if_stats . isb_endtime ;
if_stats . isb_ifrecv = wblock . data . if_stats . isb_ifrecv ;
if_stats . isb_ifdrop = wblock . data . if_stats . isb_ifdrop ;
if_stats . isb_filteraccept = wblock . data . if_stats . isb_filteraccept ;
if_stats . isb_osdrop = wblock . data . if_stats . isb_osdrop ;
if_stats . isb_usrdeliv = wblock . data . if_stats . isb_usrdeliv ;
g_array_append_val ( wtapng_if_descr - > interface_statistics , if_stats ) ;
wtapng_if_descr - > num_stat_entries + + ;
2012-03-15 13:46:42 +00:00
}
2014-08-05 20:10:44 +00:00
break ;
default :
/* XXX - improve handling of "unknown" blocks */
pcapng_debug1 ( " pcapng_read: Unknown block type 0x%08x " , wblock . type ) ;
break ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2012-10-12 03:55:10 +00:00
got_packet :
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
pcapng_debug1 ( " pcapng_read: data_offset is finally % " G_GINT64_MODIFIER " d " , * data_offset + bytes_read ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
return TRUE ;
2008-01-13 21:10:09 +00:00
}
/* classic wtap: seek to file position and read packet */
2014-05-23 10:50:02 +00:00
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_seek_read ( wtap * wth , gint64 seek_off ,
2014-08-05 20:10:44 +00:00
struct wtap_pkthdr * phdr , Buffer * buf ,
int * err , gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_t * pcapng = ( pcapng_t * ) wth - > priv ;
2014-10-15 23:45:51 +00:00
block_return_val ret ;
2014-08-05 20:10:44 +00:00
wtapng_block_t wblock ;
2014-05-09 05:18:49 +00:00
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* seek to the right file position */
Clean up reading code.
The only place where a short read should be treated as an EOF is if the
read of the block header reads 0 bytes. All other short reads,
including reads of the block header returning at least 1 byte but not
enough for a complete block header, and any reads of the stuff
*following* the block header even if they return 0 bytes, should be
treated as "short read" errors.
If the option length is bigger than the option buffer size, treat that
as a bad file (I'm not sure that can happen, so maybe it should be
treated as an internal error instead).
Use file_skip() rather than file_seek() when skipping forward N bytes.
If it fails, treat that as an error under all circumstances.
When reading the first section header block in the open routine, have
pcap_read_block() return -2 if it doesn't look like an SHB (too short,
wrong block type, bad block length, unknown byte-order magic number), as
that means the file isn't a pcap-ng file and the open should return 0.
Return -1, not 0, for all errors in various block-reading routines.
file_seek() returning 0 is *not* an error. file_seek() returning -1 (or
any other negative number *is* an error; its return value is signed, so
don't assign it to an unsigned variable.
This might fix the test errors for the Lua file format handler tests.
Change-Id: Ifa7d9834c38bf238461c9cc9625a2aa761cb6ff2
Reviewed-on: https://code.wireshark.org/review/4238
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-09-22 10:47:24 +00:00
if ( file_seek ( wth - > random_fh , seek_off , SEEK_SET , err ) < 0 ) {
2014-08-05 20:10:44 +00:00
return FALSE ; /* Seek error */
}
pcapng_debug1 ( " pcapng_seek_read: reading at offset % " G_GINT64_MODIFIER " u " , seek_off ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
wblock . frame_buffer = buf ;
wblock . packet_header = phdr ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* read the block */
2014-10-15 23:45:51 +00:00
ret = pcapng_read_block ( wth , wth - > random_fh , pcapng , & wblock , err , err_info ) ;
2014-09-22 11:43:14 +00:00
pcapng_free_wtapng_block_data ( & wblock ) ;
2014-10-15 23:45:51 +00:00
if ( ret ! = PCAPNG_BLOCK_OK ) {
2014-10-16 07:00:45 +00:00
pcapng_debug1 ( " pcapng_seek_read: couldn't read packet block (err=%d). " ,
* err ) ;
2014-08-05 20:10:44 +00:00
return FALSE ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* block must be a "Packet Block", an "Enhanced Packet Block",
or a " Simple Packet Block " */
if ( wblock . type ! = BLOCK_TYPE_PB & & wblock . type ! = BLOCK_TYPE_EPB & &
wblock . type ! = BLOCK_TYPE_SPB ) {
pcapng_debug1 ( " pcapng_seek_read: block type %u not PB/EPB/SPB " , wblock . type ) ;
return FALSE ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
return TRUE ;
2008-01-13 21:10:09 +00:00
}
/* classic wtap: close capture file */
static void
2014-05-09 05:18:49 +00:00
pcapng_close ( wtap * wth )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_t * pcapng = ( pcapng_t * ) wth - > priv ;
2010-02-26 07:59:54 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_close: closing file " ) ;
g_array_free ( pcapng - > interfaces , TRUE ) ;
2008-01-13 21:10:09 +00:00
}
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_write_section_header_block ( wtap_dumper * wdh , int * err )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_block_header_t bh ;
pcapng_section_header_block_t shb ;
const guint32 zero_pad = 0 ;
gboolean have_options = FALSE ;
struct option option_hdr ; /* guint16 type, guint16 value_length; */
guint32 options_total_length = 0 ;
guint32 comment_len = 0 , shb_hardware_len = 0 , shb_os_len = 0 , shb_user_appl_len = 0 ;
guint32 comment_pad_len = 0 , shb_hardware_pad_len = 0 , shb_os_pad_len = 0 , shb_user_appl_pad_len = 0 ;
if ( wdh - > shb_hdr ) {
pcapng_debug0 ( " pcapng_write_section_header_block: Have shb_hdr " ) ;
/* Check if we should write comment option */
if ( wdh - > shb_hdr - > opt_comment ) {
have_options = TRUE ;
comment_len = ( guint32 ) strlen ( wdh - > shb_hdr - > opt_comment ) & 0xffff ;
if ( ( comment_len % 4 ) ) {
comment_pad_len = 4 - ( comment_len % 4 ) ;
} else {
comment_pad_len = 0 ;
}
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Check if we should write shb_hardware option */
if ( wdh - > shb_hdr - > shb_hardware ) {
have_options = TRUE ;
shb_hardware_len = ( guint32 ) strlen ( wdh - > shb_hdr - > shb_hardware ) & 0xffff ;
if ( ( shb_hardware_len % 4 ) ) {
shb_hardware_pad_len = 4 - ( shb_hardware_len % 4 ) ;
} else {
shb_hardware_pad_len = 0 ;
}
options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Check if we should write shb_os option */
if ( wdh - > shb_hdr - > shb_os ) {
have_options = TRUE ;
shb_os_len = ( guint32 ) strlen ( wdh - > shb_hdr - > shb_os ) & 0xffff ;
if ( ( shb_os_len % 4 ) ) {
shb_os_pad_len = 4 - ( shb_os_len % 4 ) ;
} else {
shb_os_pad_len = 0 ;
}
options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Check if we should write shb_user_appl option */
if ( wdh - > shb_hdr - > shb_user_appl ) {
have_options = TRUE ;
shb_user_appl_len = ( guint32 ) strlen ( wdh - > shb_hdr - > shb_user_appl ) & 0xffff ;
if ( ( shb_user_appl_len % 4 ) ) {
shb_user_appl_pad_len = 4 - ( shb_user_appl_len % 4 ) ;
} else {
shb_user_appl_pad_len = 0 ;
}
options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
}
if ( have_options ) {
/* End-of-options tag */
options_total_length + = 4 ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block header */
bh . block_type = BLOCK_TYPE_SHB ;
bh . block_total_length = ( guint32 ) ( sizeof ( bh ) + sizeof ( shb ) + options_total_length + 4 ) ;
pcapng_debug2 ( " pcapng_write_section_header_block: Total len %u, Options total len %u " , bh . block_total_length , options_total_length ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block fixed content */
/* XXX - get these values from wblock? */
shb . magic = 0x1A2B3C4D ;
shb . version_major = 1 ;
shb . version_minor = 0 ;
shb . section_length = - 1 ;
if ( ! wtap_dump_file_write ( wdh , & shb , sizeof shb , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof shb ;
/* XXX - write (optional) block options
* opt_comment 1
* shb_hardware 2
* shb_os 3
* shb_user_appl 4
*/
if ( comment_len ) {
option_hdr . type = OPT_COMMENT ;
option_hdr . value_length = comment_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_section_header_block, comment:'%s' comment_len %u comment_pad_len %u " , wdh - > shb_hdr - > opt_comment , comment_len , comment_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , wdh - > shb_hdr - > opt_comment , comment_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( comment_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , comment_pad_len , err ) )
2012-03-12 15:43:59 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
wdh - > bytes_dumped + = comment_pad_len ;
}
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( shb_hardware_len ) {
option_hdr . type = OPT_SHB_HARDWARE ;
option_hdr . value_length = shb_hardware_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Write the string */
pcapng_debug3 ( " pcapng_write_section_header_block, shb_hardware:'%s' shb_hardware_len %u shb_hardware_pad_len %u " , wdh - > shb_hdr - > shb_hardware , shb_hardware_len , shb_hardware_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , wdh - > shb_hdr - > shb_hardware , shb_hardware_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = shb_hardware_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( shb_hardware_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , shb_hardware_pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = shb_hardware_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( shb_os_len ) {
option_hdr . type = OPT_SHB_OS ;
option_hdr . value_length = shb_os_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Write the string */
pcapng_debug3 ( " pcapng_write_section_header_block, shb_os:'%s' shb_os_len %u shb_os_pad_len %u " , wdh - > shb_hdr - > shb_os , shb_os_len , shb_os_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , wdh - > shb_hdr - > shb_os , shb_os_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = shb_os_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( shb_os_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , shb_os_pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = shb_os_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
if ( shb_user_appl_len ) {
option_hdr . type = OPT_SHB_USERAPPL ;
option_hdr . value_length = shb_user_appl_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_section_header_block, shb_user_appl:'%s' shb_user_appl_len %u shb_user_appl_pad_len %u " , wdh - > shb_hdr - > shb_user_appl , shb_user_appl_len , shb_user_appl_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , wdh - > shb_hdr - > shb_user_appl , shb_user_appl_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = shb_user_appl_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( shb_user_appl_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , shb_user_appl_pad_len , err ) )
2012-03-12 15:43:59 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
wdh - > bytes_dumped + = shb_user_appl_pad_len ;
}
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Write end of options if we have otions */
if ( have_options ) {
option_hdr . type = OPT_EOFOPT ;
option_hdr . value_length = 0 ;
if ( ! wtap_dump_file_write ( wdh , & zero_pad , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
}
/* write block footer */
if ( ! wtap_dump_file_write ( wdh , & bh . block_total_length ,
sizeof bh . block_total_length , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh . block_total_length ;
return TRUE ;
2008-01-13 21:10:09 +00:00
}
2012-03-12 15:43:59 +00:00
# define IDB_OPT_IF_NAME 2
# define IDB_OPT_IF_DESCR 3
# define IDB_OPT_IF_SPEED 8
# define IDB_OPT_IF_TSRESOL 9
# define IDB_OPT_IF_FILTER 11
# define IDB_OPT_IF_OS 12
2008-01-13 21:10:09 +00:00
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_write_if_descr_block ( wtap_dumper * wdh , wtapng_if_descr_t * int_data , int * err )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_block_header_t bh ;
pcapng_interface_description_block_t idb ;
const guint32 zero_pad = 0 ;
gboolean have_options = FALSE ;
struct option option_hdr ; /* guint16 type, guint16 value_length; */
guint32 options_total_length = 0 ;
guint32 comment_len = 0 , if_name_len = 0 , if_description_len = 0 , if_os_len = 0 , if_filter_str_len = 0 ;
guint32 comment_pad_len = 0 , if_name_pad_len = 0 , if_description_pad_len = 0 , if_os_pad_len = 0 , if_filter_str_pad_len = 0 ;
pcapng_debug3 ( " pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d " ,
int_data - > link_type ,
wtap_encap_string ( wtap_pcap_encap_to_wtap_encap ( int_data - > link_type ) ) ,
int_data - > snap_len ) ;
if ( int_data - > link_type = = ( guint16 ) - 1 ) {
* err = WTAP_ERR_UNSUPPORTED_ENCAP ;
return FALSE ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* Calculate options length */
if ( int_data - > opt_comment ) {
have_options = TRUE ;
comment_len = ( guint32 ) strlen ( int_data - > opt_comment ) & 0xffff ;
if ( ( comment_len % 4 ) ) {
comment_pad_len = 4 - ( comment_len % 4 ) ;
} else {
comment_pad_len = 0 ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/*
* if_name 2 A UTF - 8 string containing the name of the device used to capture data .
*/
if ( int_data - > if_name ) {
have_options = TRUE ;
if_name_len = ( guint32 ) strlen ( int_data - > if_name ) & 0xffff ;
if ( ( if_name_len % 4 ) ) {
if_name_pad_len = 4 - ( if_name_len % 4 ) ;
} else {
if_name_pad_len = 0 ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/*
* if_description 3 A UTF - 8 string containing the description of the device used to capture data .
*/
if ( int_data - > if_description ) {
have_options = TRUE ;
if_description_len = ( guint32 ) strlen ( int_data - > if_description ) & 0xffff ;
if ( ( if_description_len % 4 ) ) {
if_description_pad_len = 4 - ( if_description_len % 4 ) ;
} else {
if_description_pad_len = 0 ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
}
/* Currently not handled
* if_IPv4addr 4 Interface network address and netmask .
* if_IPv6addr 5 Interface network address and prefix length ( stored in the last byte ) .
* if_MACaddr 6 Interface Hardware MAC address ( 48 bits ) . 00 01 02 03 04 05
* if_EUIaddr 7 Interface Hardware EUI address ( 64 bits ) , if available . TODO : give a good example
*/
/*
* if_speed 8 Interface speed ( in bps ) . 100000000 for 100 Mbps
*/
if ( int_data - > if_speed ! = 0 ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 ;
}
/*
* if_tsresol 9 Resolution of timestamps .
*/
if ( int_data - > if_tsresol ! = 0 ) {
have_options = TRUE ;
options_total_length = options_total_length + 4 + 4 ;
}
/* Not used
* if_tzone 10 Time zone for GMT support ( TODO : specify better ) . TODO : give a good example
*/
/*
* if_filter 11 The filter ( e . g . " capture only TCP traffic " ) used to capture traffic .
* The first byte of the Option Data keeps a code of the filter used ( e . g . if this is a libpcap string , or BPF bytecode , and more ) .
*/
if ( int_data - > if_filter_str ) {
have_options = TRUE ;
if_filter_str_len = ( guint32 ) ( strlen ( int_data - > if_filter_str ) + 1 ) & 0xffff ;
if ( ( if_filter_str_len % 4 ) ) {
if_filter_str_pad_len = 4 - ( if_filter_str_len % 4 ) ;
} else {
if_filter_str_pad_len = 0 ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
}
/*
* if_os 12 A UTF - 8 string containing the name of the operating system of the machine in which this interface is installed .
*/
if ( int_data - > if_os ) {
have_options = TRUE ;
if_os_len = ( guint32 ) strlen ( int_data - > if_os ) & 0xffff ;
if ( ( if_os_len % 4 ) ) {
if_os_pad_len = 4 - ( if_os_len % 4 ) ;
} else {
if_os_pad_len = 0 ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
}
/*
* if_fcslen 13 An integer value that specified the length of the Frame Check Sequence ( in bits ) for this interface .
* - 1 if unknown or changes between packets , opt 13 An integer value that specified the length of the Frame Check Sequence ( in bits ) for this interface .
*/
if ( int_data - > if_fcslen ! = 0 ) {
}
/* Not used
* if_tsoffset 14 A 64 bits integer value that specifies an offset ( in seconds ) that must be added to the timestamp of each packet
* to obtain the absolute timestamp of a packet . If the option is missing , the timestamps stored in the packet must be considered absolute timestamps .
*/
if ( have_options ) {
/* End-of-options tag */
options_total_length + = 4 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block header */
bh . block_type = BLOCK_TYPE_IDB ;
bh . block_total_length = ( guint32 ) ( sizeof ( bh ) + sizeof ( idb ) + options_total_length + 4 ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block fixed content */
idb . linktype = int_data - > link_type ;
idb . reserved = 0 ;
idb . snaplen = int_data - > snap_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( ! wtap_dump_file_write ( wdh , & idb , sizeof idb , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof idb ;
/* XXX - write (optional) block options */
if ( comment_len ! = 0 ) {
option_hdr . type = OPT_COMMENT ;
option_hdr . value_length = comment_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u " , int_data - > opt_comment , comment_len , comment_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , int_data - > opt_comment , comment_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( comment_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , comment_pad_len , err ) )
2012-03-12 15:43:59 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
wdh - > bytes_dumped + = comment_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
/*
* if_name 2 A UTF - 8 string containing the name of the device used to capture data .
*/
if ( if_name_len ! = 0 ) {
option_hdr . type = IDB_OPT_IF_NAME ;
option_hdr . value_length = if_name_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u " , int_data - > if_name , if_name_len , if_name_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , int_data - > if_name , if_name_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_name_len ;
/* write padding (if any) */
if ( if_name_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , if_name_pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_name_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
/*
* if_description 3 A UTF - 8 string containing the description of the device used to capture data .
*/
if ( if_description_len ! = 0 ) {
option_hdr . type = IDB_OPT_IF_NAME ;
option_hdr . value_length = if_description_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u " , int_data - > if_description , if_description_len , if_description_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , int_data - > if_description , if_description_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_description_len ;
/* write padding (if any) */
if ( if_description_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , if_description_pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_description_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
/* Currently not handled
* if_IPv4addr 4 Interface network address and netmask .
* if_IPv6addr 5 Interface network address and prefix length ( stored in the last byte ) .
* if_MACaddr 6 Interface Hardware MAC address ( 48 bits ) . 00 01 02 03 04 05
* if_EUIaddr 7 Interface Hardware EUI address ( 64 bits ) , if available . TODO : give a good example
*/
/*
* if_speed 8 Interface speed ( in bps ) . 100000000 for 100 Mbps
*/
if ( int_data - > if_speed ! = 0 ) {
option_hdr . type = IDB_OPT_IF_SPEED ;
option_hdr . value_length = 8 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug1 ( " pcapng_write_if_descr_block: if_speed % " G_GINT64_MODIFIER " u (bps) " , int_data - > if_speed ) ;
if ( ! wtap_dump_file_write ( wdh , & int_data - > if_speed , sizeof ( guint64 ) , err ) )
return FALSE ;
wdh - > bytes_dumped + = 8 ;
}
/*
* if_tsresol 9 Resolution of timestamps .
* default is 6 for microsecond resolution , opt 9 Resolution of timestamps .
* If the Most Significant Bit is equal to zero , the remaining bits indicates
* the resolution of the timestamp as as a negative power of 10
*/
if ( int_data - > if_tsresol ! = 0 ) {
option_hdr . type = IDB_OPT_IF_TSRESOL ;
option_hdr . value_length = 1 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the time stamp resolution */
pcapng_debug1 ( " pcapng_write_if_descr_block: if_tsresol %u " , int_data - > if_tsresol ) ;
if ( ! wtap_dump_file_write ( wdh , & int_data - > if_tsresol , 1 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 1 ;
if ( ! wtap_dump_file_write ( wdh , & zero_pad , 3 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 3 ;
}
/* not used
* if_tzone 10 Time zone for GMT support ( TODO : specify better ) . TODO : give a good example
*/
/*
* if_filter 11 The filter ( e . g . " capture only TCP traffic " ) used to capture traffic .
*/
/* Libpcap string variant */
if ( if_filter_str_len ! = 0 ) {
option_hdr . type = IDB_OPT_IF_FILTER ;
option_hdr . value_length = if_filter_str_len ;
/* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the zero indicating libpcap filter variant */
if ( ! wtap_dump_file_write ( wdh , & zero_pad , 1 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 1 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_if_descr_block, if_filter_str:'%s' if_filter_str_len %u if_filter_str_pad_len %u " , int_data - > if_filter_str , if_filter_str_len , if_filter_str_pad_len ) ;
/* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
if ( ! wtap_dump_file_write ( wdh , int_data - > if_filter_str , if_filter_str_len - 1 , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_filter_str_len - 1 ;
/* write padding (if any) */
if ( if_filter_str_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , if_filter_str_pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_filter_str_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
/*
* if_os 12 A UTF - 8 string containing the name of the operating system of the machine in which this interface is installed .
*/
if ( if_os_len ! = 0 ) {
option_hdr . type = IDB_OPT_IF_OS ;
option_hdr . value_length = if_os_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u " , int_data - > if_os , if_os_len , if_os_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , int_data - > if_os , if_os_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_os_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( if_os_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , if_os_pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = if_os_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( have_options ) {
option_hdr . type = OPT_EOFOPT ;
option_hdr . value_length = 0 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/*
* if_fcslen 13 An integer value that specified the length of the Frame Check Sequence ( in bits ) for this interface .
*/
/*
* if_tsoffset 14 A 64 bits integer value that specifies an offset ( in seconds ) that must be added to the timestamp of each packet
* to obtain the absolute timestamp of a packet . If the option is missing , the timestamps stored in the packet must be considered absolute timestamps .
*/
/* write block footer */
if ( ! wtap_dump_file_write ( wdh , & bh . block_total_length ,
sizeof bh . block_total_length , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh . block_total_length ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
return TRUE ;
2008-01-13 21:10:09 +00:00
}
2012-03-20 11:42:55 +00:00
# define ISB_STARTTIME 2
# define ISB_ENDTIME 3
# define ISB_IFRECV 4
# define ISB_IFDROP 5
# define ISB_FILTERACCEPT 6
# define ISB_OSDROP 7
# define ISB_USRDELIV 8
2012-02-22 14:41:02 +00:00
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_write_interface_statistics_block ( wtap_dumper * wdh , wtapng_if_stats_t * if_stats , int * err )
2012-02-22 14:41:02 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_block_header_t bh ;
pcapng_interface_statistics_block_t isb ;
const guint32 zero_pad = 0 ;
gboolean have_options = FALSE ;
struct option option_hdr ; /* guint16 type, guint16 value_length; */
guint32 options_total_length = 0 ;
guint32 comment_len = 0 ;
guint32 comment_pad_len = 0 ;
pcapng_debug0 ( " pcapng_write_interface_statistics_block " ) ;
/* Calculate options length */
if ( if_stats - > opt_comment ) {
have_options = TRUE ;
comment_len = ( guint32 ) strlen ( if_stats - > opt_comment ) & 0xffff ;
if ( ( comment_len % 4 ) ) {
comment_pad_len = 4 - ( comment_len % 4 ) ;
} else {
comment_pad_len = 0 ;
2012-03-20 11:42:55 +00:00
}
2014-08-05 20:10:44 +00:00
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
/*guint64 isb_starttime */
if ( if_stats - > isb_starttime ! = 0 ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
/*guint64 isb_endtime */
if ( if_stats - > isb_endtime ! = 0 ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
/*guint64 isb_ifrecv */
if ( if_stats - > isb_ifrecv ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
/*guint64 isb_ifdrop */
if ( if_stats - > isb_ifdrop ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
/*guint64 isb_filteraccept */
if ( if_stats - > isb_filteraccept ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
/*guint64 isb_osdrop */
if ( if_stats - > isb_osdrop ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
/*guint64 isb_usrdeliv */
if ( if_stats - > isb_usrdeliv ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block header */
if ( have_options ) {
/* End-of-optios tag */
options_total_length + = 4 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block header */
bh . block_type = BLOCK_TYPE_ISB ;
bh . block_total_length = ( guint32 ) ( sizeof ( bh ) + sizeof ( isb ) + options_total_length + 4 ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
/* write block fixed content */
isb . interface_id = if_stats - > interface_id ;
isb . timestamp_high = if_stats - > ts_high ;
isb . timestamp_low = if_stats - > ts_low ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( ! wtap_dump_file_write ( wdh , & isb , sizeof isb , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof isb ;
/* write (optional) block options */
if ( comment_len ) {
option_hdr . type = OPT_COMMENT ;
option_hdr . value_length = comment_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_interface_statistics_block, comment:'%s' comment_len %u comment_pad_len %u " , if_stats - > opt_comment , comment_len , comment_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , if_stats - > opt_comment , comment_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( comment_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , comment_pad_len , err ) )
2012-03-12 15:43:59 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
wdh - > bytes_dumped + = comment_pad_len ;
2012-03-20 11:42:55 +00:00
}
2014-08-05 20:10:44 +00:00
}
/*guint64 isb_starttime */
if ( if_stats - > isb_starttime ! = 0 ) {
guint32 high , low ;
option_hdr . type = ISB_STARTTIME ;
option_hdr . value_length = 8 ;
high = ( guint32 ) ( ( if_stats - > isb_starttime > > 32 ) & 0xffffffff ) ;
low = ( guint32 ) ( if_stats - > isb_starttime & 0xffffffff ) ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write isb_starttime */
pcapng_debug1 ( " pcapng_write_interface_statistics_block, isb_starttime: % " G_GINT64_MODIFIER " u " , if_stats - > isb_starttime ) ;
if ( ! wtap_dump_file_write ( wdh , & high , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
if ( ! wtap_dump_file_write ( wdh , & low , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
}
/*guint64 isb_endtime */
if ( if_stats - > isb_endtime ! = 0 ) {
guint32 high , low ;
option_hdr . type = ISB_ENDTIME ;
option_hdr . value_length = 8 ;
high = ( guint32 ) ( ( if_stats - > isb_endtime > > 32 ) & 0xffffffff ) ;
low = ( guint32 ) ( if_stats - > isb_endtime & 0xffffffff ) ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write isb_endtime */
pcapng_debug1 ( " pcapng_write_interface_statistics_block, isb_starttime: % " G_GINT64_MODIFIER " u " , if_stats - > isb_endtime ) ;
if ( ! wtap_dump_file_write ( wdh , & high , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
if ( ! wtap_dump_file_write ( wdh , & low , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
}
/*guint64 isb_ifrecv;*/
if ( if_stats - > isb_ifrecv ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
option_hdr . type = ISB_IFRECV ;
option_hdr . value_length = 8 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write isb_ifrecv */
pcapng_debug1 ( " pcapng_write_interface_statistics_block, isb_ifrecv: % " G_GINT64_MODIFIER " u " , if_stats - > isb_ifrecv ) ;
if ( ! wtap_dump_file_write ( wdh , & if_stats - > isb_ifrecv , 8 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 8 ;
}
/*guint64 isb_ifdrop;*/
if ( if_stats - > isb_ifdrop ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
option_hdr . type = ISB_IFDROP ;
option_hdr . value_length = 8 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write isb_ifdrop */
pcapng_debug1 ( " pcapng_write_interface_statistics_block, isb_ifdrop: % " G_GINT64_MODIFIER " u " , if_stats - > isb_ifdrop ) ;
if ( ! wtap_dump_file_write ( wdh , & if_stats - > isb_ifdrop , 8 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 8 ;
}
/*guint64 isb_filteraccept;*/
if ( if_stats - > isb_filteraccept ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
option_hdr . type = ISB_FILTERACCEPT ;
option_hdr . value_length = 8 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write isb_filteraccept */
pcapng_debug1 ( " pcapng_write_interface_statistics_block, isb_filteraccept: % " G_GINT64_MODIFIER " u " , if_stats - > isb_filteraccept ) ;
if ( ! wtap_dump_file_write ( wdh , & if_stats - > isb_filteraccept , 8 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 8 ;
}
/*guint64 isb_osdrop;*/
if ( if_stats - > isb_osdrop ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
option_hdr . type = ISB_OSDROP ;
option_hdr . value_length = 8 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write isb_osdrop */
pcapng_debug1 ( " pcapng_write_interface_statistics_block, isb_osdrop: % " G_GINT64_MODIFIER " u " , if_stats - > isb_osdrop ) ;
if ( ! wtap_dump_file_write ( wdh , & if_stats - > isb_osdrop , 8 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 8 ;
}
/*guint64 isb_usrdeliv;*/
if ( if_stats - > isb_usrdeliv ! = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) ) {
option_hdr . type = ISB_USRDELIV ;
option_hdr . value_length = 8 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write isb_usrdeliv */
pcapng_debug1 ( " pcapng_write_interface_statistics_block, isb_usrdeliv: % " G_GINT64_MODIFIER " u " , if_stats - > isb_usrdeliv ) ;
if ( ! wtap_dump_file_write ( wdh , & if_stats - > isb_usrdeliv , 8 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 8 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( have_options ) {
option_hdr . type = OPT_EOFOPT ;
option_hdr . value_length = 0 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block footer */
if ( ! wtap_dump_file_write ( wdh , & bh . block_total_length ,
sizeof bh . block_total_length , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh . block_total_length ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
return TRUE ;
2012-02-22 14:41:02 +00:00
}
2012-03-20 11:42:55 +00:00
2008-01-13 21:10:09 +00:00
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_write_enhanced_packet_block ( wtap_dumper * wdh ,
2014-08-05 20:10:44 +00:00
const struct wtap_pkthdr * phdr ,
const union wtap_pseudo_header * pseudo_header , const guint8 * pd , int * err )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_block_header_t bh ;
pcapng_enhanced_packet_block_t epb ;
guint64 ts ;
const guint32 zero_pad = 0 ;
guint32 pad_len ;
guint32 phdr_len ;
gboolean have_options = FALSE ;
guint32 options_total_length = 0 ;
struct option option_hdr ;
guint32 comment_len = 0 , comment_pad_len = 0 ;
wtapng_if_descr_t int_data ;
/* Don't write anything we're not willing to read. */
if ( phdr - > caplen > WTAP_MAX_PACKET_SIZE ) {
* err = WTAP_ERR_PACKET_TOO_LARGE ;
return FALSE ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
phdr_len = ( guint32 ) pcap_get_phdr_size ( phdr - > pkt_encap , pseudo_header ) ;
if ( ( phdr_len + phdr - > caplen ) % 4 ) {
pad_len = 4 - ( ( phdr_len + phdr - > caplen ) % 4 ) ;
} else {
pad_len = 0 ;
}
2014-01-22 00:26:36 +00:00
2014-08-05 20:10:44 +00:00
/* Check if we should write comment option */
if ( phdr - > opt_comment ) {
have_options = TRUE ;
comment_len = ( guint32 ) strlen ( phdr - > opt_comment ) & 0xffff ;
if ( ( comment_len % 4 ) ) {
comment_pad_len = 4 - ( comment_len % 4 ) ;
2012-03-12 15:43:59 +00:00
} else {
2014-08-05 20:10:44 +00:00
comment_pad_len = 0 ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
if ( phdr - > presence_flags & WTAP_HAS_PACK_FLAGS ) {
have_options = TRUE ;
options_total_length = options_total_length + 8 ;
}
if ( have_options ) {
/* End-of optios tag */
options_total_length + = 4 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write (enhanced) packet block header */
bh . block_type = BLOCK_TYPE_EPB ;
bh . block_total_length = ( guint32 ) sizeof ( bh ) + ( guint32 ) sizeof ( epb ) + phdr_len + phdr - > caplen + pad_len + options_total_length + 4 ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block fixed content */
if ( phdr - > presence_flags & WTAP_HAS_INTERFACE_ID )
epb . interface_id = phdr - > interface_id ;
else {
2012-07-10 19:12:37 +00:00
/*
2014-08-05 20:10:44 +00:00
* XXX - we should support writing WTAP_ENCAP_PER_PACKET
* data to pcap - NG files even if we * don ' t * have interface
* IDs .
2012-07-10 19:12:37 +00:00
*/
2014-08-05 20:10:44 +00:00
epb . interface_id = 0 ;
}
/*
* Split the 64 - bit timestamp into two 32 - bit pieces , using
* the time stamp resolution for the interface .
*/
if ( epb . interface_id > = wdh - > interface_data - > len ) {
/*
* Our caller is doing something bad .
*/
* err = WTAP_ERR_INTERNAL ;
return FALSE ;
}
int_data = g_array_index ( wdh - > interface_data , wtapng_if_descr_t ,
epb . interface_id ) ;
ts = ( ( guint64 ) phdr - > ts . secs ) * int_data . time_units_per_second +
( ( ( guint64 ) phdr - > ts . nsecs ) * int_data . time_units_per_second ) / 1000000000 ;
epb . timestamp_high = ( guint32 ) ( ts > > 32 ) ;
epb . timestamp_low = ( guint32 ) ts ;
epb . captured_len = phdr - > caplen + phdr_len ;
epb . packet_len = phdr - > len + phdr_len ;
if ( ! wtap_dump_file_write ( wdh , & epb , sizeof epb , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof epb ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write pseudo header */
if ( ! pcap_write_phdr ( wdh , phdr - > pkt_encap , pseudo_header , err ) ) {
return FALSE ;
}
wdh - > bytes_dumped + = phdr_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write packet data */
if ( ! wtap_dump_file_write ( wdh , pd , phdr - > caplen , err ) )
return FALSE ;
wdh - > bytes_dumped + = phdr - > caplen ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = pad_len ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* XXX - write (optional) block options */
/* options defined in Section 2.5 (Options)
* Name Code Length Description
* opt_comment 1 variable A UTF - 8 string containing a comment that is associated to the current block .
*
* Enhanced Packet Block options
* epb_flags 2 4 A flags word containing link - layer information . A complete specification of
* the allowed flags can be found in Appendix A ( Packet Block Flags Word ) .
* epb_hash 3 variable This option contains a hash of the packet . The first byte specifies the hashing algorithm ,
* while the following bytes contain the actual hash , whose size depends on the hashing algorithm ,
* and hence from the value in the first bit . The hashing algorithm can be : 2 s complement
* ( algorithm byte = 0 , size = XXX ) , XOR ( algorithm byte = 1 , size = XXX ) , CRC32 ( algorithm byte = 2 , size = 4 ) ,
* MD - 5 ( algorithm byte = 3 , size = XXX ) , SHA - 1 ( algorithm byte = 4 , size = XXX ) .
* The hash covers only the packet , not the header added by the capture driver :
* this gives the possibility to calculate it inside the network card .
* The hash allows easier comparison / merging of different capture files , and reliable data transfer between the
* data acquisition system and the capture library .
* epb_dropcount 4 8 A 64 bit integer value specifying the number of packets lost ( by the interface and the operating system )
* between this packet and the preceding one .
* opt_endofopt 0 0 It delimits the end of the optional fields . This block cannot be repeated within a given list of options .
*/
if ( phdr - > opt_comment ) {
option_hdr . type = OPT_COMMENT ;
option_hdr . value_length = comment_len ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
pcapng_debug3 ( " pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u " , phdr - > opt_comment , comment_len , comment_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , phdr - > opt_comment , comment_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write padding (if any) */
if ( comment_pad_len ! = 0 ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , comment_pad_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = comment_pad_len ;
2012-03-12 15:43:59 +00:00
}
2014-08-05 20:10:44 +00:00
pcapng_debug2 ( " pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u " ,
comment_len ,
comment_pad_len ) ;
}
if ( phdr - > presence_flags & WTAP_HAS_PACK_FLAGS ) {
option_hdr . type = OPT_EPB_FLAGS ;
option_hdr . value_length = 4 ;
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
if ( ! wtap_dump_file_write ( wdh , & phdr - > pack_flags , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
pcapng_debug1 ( " pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x " , phdr - > pack_flags ) ;
}
/* Write end of options if we have otions */
if ( have_options ) {
if ( ! wtap_dump_file_write ( wdh , & zero_pad , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
}
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
/* write block footer */
if ( ! wtap_dump_file_write ( wdh , & bh . block_total_length ,
sizeof bh . block_total_length , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh . block_total_length ;
return TRUE ;
2008-01-13 21:10:09 +00:00
}
2011-03-24 22:47:57 +00:00
/* Arbitrary. */
# define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
static gboolean
2014-05-09 05:18:49 +00:00
pcapng_write_name_resolution_block ( wtap_dumper * wdh , int * err )
2011-03-24 22:47:57 +00:00
{
2013-09-22 20:18:25 +00:00
pcapng_block_header_t bh ;
pcapng_name_resolution_block_t nrb ;
guint8 * rec_data ;
gint rec_off , namelen , tot_rec_len ;
hashipv4_t * ipv4_hash_list_entry ;
hashipv6_t * ipv6_hash_list_entry ;
int i ;
if ( ( ! wdh - > addrinfo_lists ) | | ( ( ! wdh - > addrinfo_lists - > ipv4_addr_list ) & & ( ! wdh - > addrinfo_lists - > ipv6_addr_list ) ) ) {
return TRUE ;
}
rec_off = 8 ; /* block type + block total length */
bh . block_type = BLOCK_TYPE_NRB ;
bh . block_total_length = rec_off + 8 ; /* end-of-record + block total length */
rec_data = ( guint8 * ) g_malloc ( NRES_REC_MAX_SIZE ) ;
if ( wdh - > addrinfo_lists - > ipv4_addr_list ) {
i = 0 ;
ipv4_hash_list_entry = ( hashipv4_t * ) g_list_nth_data ( wdh - > addrinfo_lists - > ipv4_addr_list , i ) ;
while ( ipv4_hash_list_entry ! = NULL ) {
nrb . record_type = NRES_IP4RECORD ;
namelen = ( gint ) strlen ( ipv4_hash_list_entry - > name ) + 1 ;
nrb . record_len = 4 + namelen ;
tot_rec_len = 4 + nrb . record_len + PADDING4 ( nrb . record_len ) ;
if ( rec_off + tot_rec_len > NRES_REC_MAX_SIZE ) {
/* We know the total length now; copy the block header. */
memcpy ( rec_data , & bh , sizeof ( bh ) ) ;
/* End of record */
memset ( rec_data + rec_off , 0 , 4 ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , & bh . block_total_length , sizeof ( bh . block_total_length ) ) ;
pcapng_debug2 ( " pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u " , bh . block_total_length , rec_off ) ;
2014-05-09 05:18:49 +00:00
if ( ! wtap_dump_file_write ( wdh , rec_data , bh . block_total_length , err ) ) {
2013-09-22 20:18:25 +00:00
g_free ( rec_data ) ;
return FALSE ;
}
2014-05-09 05:18:49 +00:00
wdh - > bytes_dumped + = bh . block_total_length ;
2013-09-22 20:18:25 +00:00
/*Start a new NRB */
rec_off = 8 ; /* block type + block total length */
bh . block_type = BLOCK_TYPE_NRB ;
bh . block_total_length = rec_off + 8 ; /* end-of-record + block total length */
}
bh . block_total_length + = tot_rec_len ;
memcpy ( rec_data + rec_off , & nrb , sizeof ( nrb ) ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , & ( ipv4_hash_list_entry - > addr ) , 4 ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , ipv4_hash_list_entry - > name , namelen ) ;
rec_off + = namelen ;
memset ( rec_data + rec_off , 0 , PADDING4 ( namelen ) ) ;
rec_off + = PADDING4 ( namelen ) ;
pcapng_debug1 ( " NRB: added IPv4 record for %s " , ipv4_hash_list_entry - > name ) ;
i + + ;
ipv4_hash_list_entry = ( hashipv4_t * ) g_list_nth_data ( wdh - > addrinfo_lists - > ipv4_addr_list , i ) ;
}
g_list_free ( wdh - > addrinfo_lists - > ipv4_addr_list ) ;
wdh - > addrinfo_lists - > ipv4_addr_list = NULL ;
}
if ( wdh - > addrinfo_lists - > ipv6_addr_list ) {
i = 0 ;
ipv6_hash_list_entry = ( hashipv6_t * ) g_list_nth_data ( wdh - > addrinfo_lists - > ipv6_addr_list , i ) ;
while ( ipv6_hash_list_entry ! = NULL ) {
nrb . record_type = NRES_IP6RECORD ;
namelen = ( gint ) strlen ( ipv6_hash_list_entry - > name ) + 1 ;
2013-12-28 20:37:21 +00:00
nrb . record_len = 16 + namelen ; /* 16 bytes IPv6 address length */
/* 2 bytes record type, 2 bytes length field */
tot_rec_len = 4 + nrb . record_len + PADDING4 ( nrb . record_len ) ;
2013-09-22 20:18:25 +00:00
if ( rec_off + tot_rec_len > NRES_REC_MAX_SIZE ) {
/* We know the total length now; copy the block header. */
memcpy ( rec_data , & bh , sizeof ( bh ) ) ;
/* End of record */
memset ( rec_data + rec_off , 0 , 4 ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , & bh . block_total_length , sizeof ( bh . block_total_length ) ) ;
pcapng_debug2 ( " pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u " , bh . block_total_length , rec_off ) ;
2014-05-09 05:18:49 +00:00
if ( ! wtap_dump_file_write ( wdh , rec_data , bh . block_total_length , err ) ) {
2013-09-22 20:18:25 +00:00
g_free ( rec_data ) ;
return FALSE ;
}
2014-05-09 05:18:49 +00:00
wdh - > bytes_dumped + = bh . block_total_length ;
2013-09-22 20:18:25 +00:00
/*Start a new NRB */
rec_off = 8 ; /* block type + block total length */
bh . block_type = BLOCK_TYPE_NRB ;
bh . block_total_length = rec_off + 8 ; /* end-of-record + block total length */
}
bh . block_total_length + = tot_rec_len ;
memcpy ( rec_data + rec_off , & nrb , sizeof ( nrb ) ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , & ( ipv6_hash_list_entry - > addr ) , 16 ) ;
rec_off + = 16 ;
memcpy ( rec_data + rec_off , ipv6_hash_list_entry - > name , namelen ) ;
rec_off + = namelen ;
memset ( rec_data + rec_off , 0 , PADDING4 ( namelen ) ) ;
rec_off + = PADDING4 ( namelen ) ;
pcapng_debug1 ( " NRB: added IPv6 record for %s " , ipv6_hash_list_entry - > name ) ;
i + + ;
ipv6_hash_list_entry = ( hashipv6_t * ) g_list_nth_data ( wdh - > addrinfo_lists - > ipv6_addr_list , i ) ;
2012-03-12 15:43:59 +00:00
}
2013-09-22 20:18:25 +00:00
g_list_free ( wdh - > addrinfo_lists - > ipv6_addr_list ) ;
wdh - > addrinfo_lists - > ipv6_addr_list = NULL ;
}
2012-03-12 15:43:59 +00:00
2013-09-22 20:18:25 +00:00
/* We know the total length now; copy the block header. */
memcpy ( rec_data , & bh , sizeof ( bh ) ) ;
/* End of record */
memset ( rec_data + rec_off , 0 , 4 ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , & bh . block_total_length , sizeof ( bh . block_total_length ) ) ;
pcapng_debug2 ( " pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u " , bh . block_total_length , rec_off ) ;
2014-05-09 05:18:49 +00:00
if ( ! wtap_dump_file_write ( wdh , rec_data , bh . block_total_length , err ) ) {
2012-03-12 15:43:59 +00:00
g_free ( rec_data ) ;
2013-09-22 20:18:25 +00:00
return FALSE ;
}
g_free ( rec_data ) ;
2014-05-09 05:18:49 +00:00
wdh - > bytes_dumped + = bh . block_total_length ;
2013-09-22 20:18:25 +00:00
return TRUE ;
2011-03-24 22:47:57 +00:00
}
2014-05-09 05:18:49 +00:00
static gboolean pcapng_dump ( wtap_dumper * wdh ,
2014-08-05 20:10:44 +00:00
const struct wtap_pkthdr * phdr ,
const guint8 * pd , int * err )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
const union wtap_pseudo_header * pseudo_header = & phdr - > pseudo_header ;
2014-05-24 20:57:11 +00:00
# ifdef HAVE_PLUGINS
2014-08-05 20:10:44 +00:00
block_handler * handler ;
2014-05-24 20:57:11 +00:00
# endif
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug2 ( " pcapng_dump: encap = %d (%s) " ,
phdr - > pkt_encap ,
wtap_encap_string ( phdr - > pkt_encap ) ) ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
switch ( phdr - > rec_type ) {
2014-05-24 20:57:11 +00:00
case REC_TYPE_PACKET :
2014-08-05 20:10:44 +00:00
if ( ! pcapng_write_enhanced_packet_block ( wdh , phdr , pseudo_header , pd , err ) ) {
return FALSE ;
}
break ;
2014-05-24 20:57:11 +00:00
2014-05-24 21:53:15 +00:00
case REC_TYPE_FT_SPECIFIC_EVENT :
case REC_TYPE_FT_SPECIFIC_REPORT :
2014-05-24 20:57:11 +00:00
# ifdef HAVE_PLUGINS
2014-08-05 20:10:44 +00:00
/*
* Do we have a handler for this block type ?
*/
2014-10-14 20:41:36 +00:00
if ( block_handlers ! = NULL & &
( handler = ( block_handler * ) g_hash_table_lookup ( block_handlers ,
GUINT_TO_POINTER ( pseudo_header - > ftsrec . record_type ) ) ) ! = NULL ) {
2014-08-05 20:10:44 +00:00
/* Yes. Call it to write out this record. */
if ( ! handler - > write ( wdh , phdr , pd , err ) )
return FALSE ;
} else
2014-05-24 20:57:11 +00:00
# endif
2014-08-05 20:10:44 +00:00
{
/* No. */
2014-05-24 20:57:11 +00:00
* err = WTAP_ERR_REC_TYPE_UNSUPPORTED ;
2012-03-12 15:43:59 +00:00
return FALSE ;
2014-08-05 20:10:44 +00:00
}
break ;
2012-03-12 15:43:59 +00:00
2014-08-05 20:10:44 +00:00
default :
/* We don't support writing this record type. */
* err = WTAP_ERR_REC_TYPE_UNSUPPORTED ;
return FALSE ;
}
return TRUE ;
2008-01-13 21:10:09 +00:00
}
2009-06-27 15:20:44 +00:00
/* Finish writing to a dump file.
Returns TRUE on success , FALSE on failure . */
2014-05-09 05:18:49 +00:00
static gboolean pcapng_dump_close ( wtap_dumper * wdh , int * err _U_ )
2009-06-27 15:20:44 +00:00
{
2014-08-05 20:10:44 +00:00
guint i , j ;
2010-02-26 07:59:54 +00:00
2014-09-26 23:21:10 +00:00
/* Flush any hostname resolution info we may have */
pcapng_write_name_resolution_block ( wdh , err ) ;
2014-08-05 20:10:44 +00:00
for ( i = 0 ; i < wdh - > interface_data - > len ; i + + ) {
2012-03-20 11:42:55 +00:00
2014-08-05 20:10:44 +00:00
/* Get the interface description */
wtapng_if_descr_t int_data ;
2012-03-20 11:42:55 +00:00
2014-08-05 20:10:44 +00:00
int_data = g_array_index ( wdh - > interface_data , wtapng_if_descr_t , i ) ;
for ( j = 0 ; j < int_data . num_stat_entries ; j + + ) {
wtapng_if_stats_t if_stats ;
2012-03-20 11:42:55 +00:00
2014-08-05 20:10:44 +00:00
if_stats = g_array_index ( int_data . interface_statistics , wtapng_if_stats_t , j ) ;
pcapng_debug1 ( " pcapng_dump_close: write ISB for interface %u " , if_stats . interface_id ) ;
if ( ! pcapng_write_interface_statistics_block ( wdh , & if_stats , err ) ) {
return FALSE ;
}
2012-03-20 11:42:55 +00:00
}
2014-08-05 20:10:44 +00:00
}
2012-03-20 11:42:55 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_dump_close " ) ;
return TRUE ;
2009-06-27 15:20:44 +00:00
}
2008-01-13 21:10:09 +00:00
/* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
2011-02-04 02:08:47 +00:00
gboolean
2014-05-09 05:18:49 +00:00
pcapng_dump_open ( wtap_dumper * wdh , int * err )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
guint i ;
2012-03-10 00:24:42 +00:00
2014-08-05 20:10:44 +00:00
pcapng_debug0 ( " pcapng_dump_open " ) ;
/* This is a pcapng file */
wdh - > subtype_write = pcapng_dump ;
wdh - > subtype_close = pcapng_dump_close ;
2012-02-21 15:36:08 +00:00
2014-08-05 20:10:44 +00:00
if ( wdh - > interface_data - > len = = 0 ) {
pcapng_debug0 ( " There are no interfaces. Can't handle that... " ) ;
* err = WTAP_ERR_INTERNAL ;
return FALSE ;
}
2008-01-13 21:10:09 +00:00
2014-08-05 20:10:44 +00:00
/* write the section header block */
if ( ! pcapng_write_section_header_block ( wdh , err ) ) {
return FALSE ;
}
pcapng_debug0 ( " pcapng_dump_open: wrote section header block. " ) ;
2012-02-20 20:15:51 +00:00
2014-08-05 20:10:44 +00:00
/* Write the Interface description blocks */
pcapng_debug1 ( " pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u " ,
wdh - > interface_data - > len ) ;
2012-02-20 20:15:51 +00:00
2014-08-05 20:10:44 +00:00
for ( i = 0 ; i < wdh - > interface_data - > len ; i + + ) {
2012-02-20 20:15:51 +00:00
2014-08-05 20:10:44 +00:00
/* Get the interface description */
wtapng_if_descr_t int_data ;
2012-02-20 20:15:51 +00:00
2014-08-05 20:10:44 +00:00
int_data = g_array_index ( wdh - > interface_data , wtapng_if_descr_t , i ) ;
2012-02-20 20:15:51 +00:00
2014-08-05 20:10:44 +00:00
if ( ! pcapng_write_if_descr_block ( wdh , & int_data , err ) ) {
return FALSE ;
2012-03-12 15:43:59 +00:00
}
2012-02-20 20:15:51 +00:00
2014-08-05 20:10:44 +00:00
}
return TRUE ;
2008-01-13 21:10:09 +00:00
}
/* Returns 0 if we could write the specified encapsulation type,
an error indication otherwise . */
2009-06-27 15:20:44 +00:00
int pcapng_dump_can_write_encap ( int wtap_encap )
2008-01-13 21:10:09 +00:00
{
2014-08-05 20:10:44 +00:00
pcapng_debug2 ( " pcapng_dump_can_write_encap: encap = %d (%s) " ,
wtap_encap ,
wtap_encap_string ( wtap_encap ) ) ;
2011-02-04 02:08:47 +00:00
2014-08-05 20:10:44 +00:00
/* Per-packet encapsulation is supported. */
if ( wtap_encap = = WTAP_ENCAP_PER_PACKET )
return 0 ;
2008-01-13 21:10:09 +00:00
2014-08-05 20:10:44 +00:00
/* Make sure we can figure out this DLT type */
if ( wtap_wtap_encap_to_pcap_encap ( wtap_encap ) = = - 1 )
return WTAP_ERR_UNSUPPORTED_ENCAP ;
2008-01-13 21:10:09 +00:00
2014-08-05 20:10:44 +00:00
return 0 ;
2008-01-13 21:10:09 +00:00
}
2012-03-12 06:39:45 +00:00
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/