2008-01-13 21:10:09 +00:00
/* pcapng.c
*
* $ Id $
*
* 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
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
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
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdlib.h>
# include <string.h>
# include <errno.h>
2011-03-24 22:47:57 +00:00
/* Needed for addrinfo */
# ifdef HAVE_SYS_TYPES_H
# include <sys / types.h>
# endif
# ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# endif
# ifdef HAVE_NETINET_IN_H
# include <netinet / in.h>
# endif
# ifdef HAVE_NETDB_H
# include <netdb.h>
# endif
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
2011-03-24 23:33:38 +00:00
# if defined(_WIN32) && defined(INET6)
# include <ws2tcpip.h>
# endif
2008-01-13 21:10:09 +00:00
# include "wtap-int.h"
# include "file_wrappers.h"
# include "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"
2008-01-13 21:10:09 +00:00
2012-02-24 15:57:56 +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
2008-01-13 21:10:09 +00:00
pcapng_read ( wtap * wth , int * err , gchar * * err_info ,
gint64 * data_offset ) ;
static gboolean
pcapng_seek_read ( wtap * wth , gint64 seek_off ,
2011-09-01 09:43:10 +00:00
union wtap_pseudo_header * pseudo_header , guint8 * pd , int length ,
2008-01-13 21:10:09 +00:00
int * err , gchar * * err_info ) ;
static void
pcapng_close ( wtap * wth ) ;
/* pcapng: common block header for every block type */
typedef struct pcapng_block_header_s {
guint32 block_type ;
guint32 block_total_length ;
/* x bytes block_body */
/* guint32 block_total_length */
} pcapng_block_header_t ;
2012-02-22 18:32:43 +00:00
/*
* Minimum block size = size of block header + size of block trailer .
*/
# define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
2008-01-13 21:10:09 +00:00
/* pcapng: section header block */
typedef struct pcapng_section_header_block_s {
/* pcapng_block_header_t */
guint32 magic ;
guint16 version_major ;
guint16 version_minor ;
guint64 section_length ; /* might be -1 for unknown */
/* ... Options ... */
} 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 .
*/
# define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
2008-01-13 21:10:09 +00:00
/* pcapng: interface description block */
typedef struct pcapng_interface_description_block_s {
guint16 linktype ;
guint16 reserved ;
guint32 snaplen ;
/* ... Options ... */
} 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 .
*/
# define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
2008-01-13 21:10:09 +00:00
/* pcapng: packet block (obsolete) */
typedef struct pcapng_packet_block_s {
guint16 interface_id ;
2009-04-25 19:11:35 +00:00
guint16 drops_count ;
2008-01-13 21:10:09 +00:00
guint32 timestamp_high ;
guint32 timestamp_low ;
guint32 captured_len ;
guint32 packet_len ;
/* ... Packet Data ... */
/* ... Padding ... */
/* ... Options ... */
} 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 .
*/
# define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
2008-01-13 21:10:09 +00:00
/* pcapng: enhanced packet block */
typedef struct pcapng_enhanced_packet_block_s {
guint32 interface_id ;
guint32 timestamp_high ;
guint32 timestamp_low ;
guint32 captured_len ;
guint32 packet_len ;
/* ... Packet Data ... */
/* ... Padding ... */
/* ... Options ... */
} 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 .
*/
# define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
2008-01-19 12:09:00 +00:00
/* pcapng: simple packet block */
typedef struct pcapng_simple_packet_block_s {
guint32 packet_len ;
/* ... Packet Data ... */
/* ... Padding ... */
} 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 .
*/
# define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
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 {
guint16 record_type ;
guint16 record_len ;
/* ... Record ... */
} 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 ) .
*/
# define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
2009-04-25 19:11:35 +00:00
/* pcapng: interface statistics block */
typedef struct pcapng_interface_statistics_block_s {
guint32 interface_id ;
guint32 timestamp_high ;
guint32 timestamp_low ;
/* ... Options ... */
} 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 .
*/
# define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
2008-01-18 10:29:23 +00:00
/* pcapng: common option header for every option type */
typedef struct pcapng_option_header_s {
guint16 option_code ;
guint16 option_length ;
2008-01-19 12:09:00 +00:00
/* ... x bytes Option Body ... */
2012-02-14 17:07:52 +00:00
/* ... 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 {
guint16 type ;
guint16 value_length ;
} ;
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-02-21 16:32:25 +00:00
# define OPT_EOFOPT 0
2012-02-15 19:44:16 +00:00
# define OPT_COMMENT 1
# define OPT_SHB_HARDWARE 2
2012-02-21 16:32:25 +00:00
# define OPT_SHB_OS 3
2012-02-15 19:44:16 +00:00
# define OPT_SHB_USERAPPL 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 {
/* mandatory */
guint64 section_length ;
/* options */
gchar * opt_comment ; /* NULL if not available */
gchar * shb_hardware ; /* NULL if not available */
2012-02-15 19:44:16 +00:00
gchar * shb_os ; /* NULL if not available */
2008-01-13 21:10:09 +00:00
gchar * shb_user_appl ; /* NULL if not available */
} 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 */
/* Interface Description
*
* Options :
* 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
2012-03-03 16:17:20 +00:00
* 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 {
/* mandatory */
guint16 link_type ;
2012-02-20 20:15:51 +00:00
guint encap ;
2008-01-13 21:10:09 +00:00
guint32 snap_len ;
/* options */
gchar * opt_comment ; /* NULL if not available */
2012-02-20 20:15:51 +00:00
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)*/
2012-02-21 16:32:25 +00:00
guint64 if_speed ; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
2012-02-20 20:15:51 +00:00
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 {
/* mandatory */
2012-03-02 05:03:06 +00:00
guint32 ts_high ; /* seconds since 1.1.1970 */
guint32 ts_low ; /* fraction of seconds, depends on if_tsresol */
2008-01-19 12:09:00 +00:00
guint32 cap_len ; /* data length in the file */
guint32 packet_len ; /* data length on the wire */
2009-04-25 19:11:35 +00:00
guint32 interface_id ; /* identifier of the interface. */
guint16 drops_count ; /* drops count, only valid for packet block */
2012-02-20 20:15:51 +00:00
/* 0xffff if information no available */
2008-01-13 21:10:09 +00:00
/* pack_hash */
/* XXX - put the packet data / pseudo_header here as well? */
} wtapng_packet_t ;
2008-01-19 12:09:00 +00:00
/* Simple Packets */
typedef struct wtapng_simple_packet_s {
/* mandatory */
guint32 cap_len ; /* data length in the file */
guint32 packet_len ; /* data length on the wire */
2009-06-27 11:39:47 +00:00
guint32 pseudo_header_len ;
2009-06-27 17:33:23 +00:00
int wtap_encap ;
2008-01-19 12:09:00 +00:00
/* XXX - put the packet data / pseudo_header here as well? */
} wtapng_simple_packet_t ;
2008-01-13 21:10:09 +00:00
/* Name Resolution */
typedef struct wtapng_name_res_s {
/* options */
gchar * opt_comment ; /* NULL if not available */
/* XXX */
} wtapng_name_res_t ;
/* Interface Statistics */
typedef struct wtapng_if_stats_s {
/* mandatory */
2012-02-22 14:41:02 +00:00
guint32 interface_id ;
2008-01-13 21:10:09 +00:00
guint32 ts_high ;
guint32 ts_low ;
/* options */
gchar * opt_comment ; /* NULL if not available */
2012-02-22 14:41:02 +00:00
guint64 isb_starttime ;
guint64 isb_endtime ;
2009-04-25 19:11:35 +00:00
guint64 isb_ifrecv ;
guint64 isb_ifdrop ;
2012-02-22 14:41:02 +00:00
guint64 isb_filteraccept ;
guint64 isb_osdrop ;
guint64 isb_usrdeliv ;
2008-01-13 21:10:09 +00:00
} wtapng_if_stats_t ;
typedef struct wtapng_block_s {
guint32 type ; /* block_type as defined by pcapng */
union {
2008-07-09 20:09:23 +00:00
wtapng_section_t section ;
wtapng_if_descr_t if_descr ;
wtapng_packet_t packet ;
wtapng_simple_packet_t simple_packet ;
wtapng_name_res_t name_res ;
wtapng_if_stats_t if_stats ;
2008-01-13 21:10:09 +00:00
} data ;
2010-02-23 03:50:42 +00:00
/*
* 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 .
*/
2008-01-13 21:10:09 +00:00
const union wtap_pseudo_header * pseudo_header ;
2009-06-27 17:33:23 +00:00
struct wtap_pkthdr * packet_header ;
2011-09-01 09:43:10 +00:00
const guint8 * frame_buffer ;
2009-06-27 17:33:23 +00:00
int * file_encap ;
2008-01-13 21:10:09 +00:00
} wtapng_block_t ;
2012-02-20 20:15:51 +00:00
/* Interface data in private struct */
2009-05-03 15:47:41 +00:00
typedef struct interface_data_s {
2009-06-27 15:20:44 +00:00
int wtap_encap ;
2009-05-03 15:47:41 +00:00
guint64 time_units_per_second ;
} interface_data_t ;
2010-02-26 07:59:54 +00:00
typedef struct {
2012-03-03 16:17:20 +00:00
gboolean shb_read ; /**< Set when first SHB read, second read will fail */
gboolean read_idbs ; /**< Indicates that it is the first read after a SHB, at least one IDB is expected */
2010-02-26 07:59:54 +00:00
gboolean byte_swapped ;
guint16 version_major ;
guint16 version_minor ;
GArray * interface_data ;
guint number_of_interfaces ;
2012-02-20 20:15:51 +00:00
gint8 if_fcslen ;
2011-03-24 22:47:57 +00:00
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 ;
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 ,
2011-04-21 09:41:52 +00:00
char * content , int len , int * err , gchar * * err_info )
2008-01-19 12:09:00 +00:00
{
int bytes_read ;
int block_read ;
guint64 file_offset64 ;
2008-07-09 20:09:23 +00:00
/* read option header */
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( oh , sizeof ( * oh ) , fh ) ;
2008-10-26 08:20:26 +00:00
if ( bytes_read ! = sizeof ( * oh ) ) {
2008-01-26 14:08:51 +00:00
pcapng_debug0 ( " pcapng_read_option: failed to read option " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2008-01-19 12:09:00 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
2008-07-09 20:09:23 +00:00
}
2008-10-26 08:20:26 +00:00
block_read = sizeof ( * oh ) ;
2008-07-09 20:09:23 +00:00
if ( pn - > byte_swapped ) {
oh - > option_code = BSWAP16 ( oh - > option_code ) ;
2008-10-26 08:20:26 +00:00
oh - > option_length = BSWAP16 ( oh - > option_length ) ;
2008-07-09 20:09:23 +00:00
}
2008-01-19 12:09:00 +00:00
2008-07-09 20:09:23 +00:00
/* sanity check: option length */
if ( oh - > option_length > len ) {
2011-02-04 02:08:47 +00:00
pcapng_debug2 ( " pcapng_read_option: option_length %u larger than buffer (%u) " ,
2008-07-09 20:09:23 +00:00
oh - > option_length , len ) ;
return 0 ;
}
2008-01-19 12:09:00 +00:00
2008-07-09 20:09:23 +00:00
/* read option content */
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( content , oh - > option_length , fh ) ;
2008-07-09 20:09:23 +00:00
if ( bytes_read ! = oh - > option_length ) {
2011-05-11 12:51:01 +00:00
pcapng_debug1 ( " pcapng_read_option: failed to read content of option %u " , oh - > option_code ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2008-07-09 20:09:23 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
block_read + = oh - > option_length ;
2008-01-19 12:09:00 +00:00
2008-07-09 20:09:23 +00:00
/* jump over potential padding bytes at end of option */
if ( ( oh - > option_length % 4 ) ! = 0 ) {
file_offset64 = file_seek ( fh , 4 - ( oh - > option_length % 4 ) , SEEK_CUR , err ) ;
if ( file_offset64 < = 0 ) {
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
block_read + = 4 - ( oh - > option_length % 4 ) ;
}
return block_read ;
2008-01-19 12:09:00 +00:00
}
2008-01-13 21:10:09 +00:00
static int
2010-04-05 22:20:21 +00:00
pcapng_read_section_header_block ( FILE_T fh , gboolean first_block ,
pcapng_block_header_t * bh , pcapng_t * pn ,
wtapng_block_t * wblock , int * err ,
2009-06-28 11:09:24 +00:00
gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
int bytes_read ;
2008-01-19 12:09:00 +00:00
int block_read ;
2012-02-14 17:07:52 +00:00
int to_read , opt_cont_buf_len ;
2008-01-13 21:10:09 +00:00
pcapng_section_header_block_t shb ;
2008-07-09 20:09:23 +00:00
pcapng_option_header_t oh ;
2012-02-14 17:07:52 +00:00
char * option_content = NULL ; /* Allocate as large as the options block */
2008-01-13 21:10:09 +00:00
2012-02-22 18:32:43 +00:00
/*
* Is this block long enough to be an SHB ?
*/
if ( bh - > block_total_length < MIN_SHB_SIZE ) {
/*
* No .
*/
if ( first_block )
return 0 ; /* probably not a pcap-ng file */
* 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 ) ;
return - 1 ;
}
2008-01-13 21:10:09 +00:00
/* read block content */
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & shb , sizeof shb , fh ) ;
2008-01-13 21:10:09 +00:00
if ( bytes_read ! = sizeof shb ) {
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2010-04-05 22:20:21 +00:00
if ( * err = = 0 ) {
if ( first_block ) {
/*
* We ' re reading this as part of an open ,
* and this block is too short to be
* an SHB , so the file is too short
* to be a pcap - ng file .
*/
return 0 ;
}
/*
* Otherwise , just report this as an error .
*/
* err = WTAP_ERR_SHORT_READ ;
}
return - 1 ;
2008-01-13 21:10:09 +00:00
}
2008-07-09 20:09:23 +00:00
block_read = bytes_read ;
2008-01-13 21:10:09 +00:00
/* is the magic number one we expect? */
switch ( shb . magic ) {
2008-07-09 20:09:23 +00:00
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 ;
2008-01-13 21:10:09 +00:00
2008-07-09 20:09:23 +00:00
pcapng_debug3 ( " pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u " ,
2008-01-13 21:10:09 +00:00
pn - > version_major , pn - > version_minor , bh - > block_total_length ) ;
2008-07-09 20:09:23 +00:00
break ;
case ( 0x4D3C2B1A ) :
/* this seems pcapng with swapped byte order */
pn - > byte_swapped = TRUE ;
pn - > version_major = BSWAP16 ( shb . version_major ) ;
pn - > version_minor = BSWAP16 ( shb . version_minor ) ;
2011-02-04 02:08:47 +00:00
2008-07-09 20:09:23 +00:00
/* tweak the block length to meet current swapping that we know now */
bh - > block_total_length = BSWAP32 ( bh - > block_total_length ) ;
2008-01-13 21:10:09 +00:00
2008-07-09 20:09:23 +00:00
pcapng_debug3 ( " pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u " ,
2008-01-13 21:10:09 +00:00
pn - > version_major , pn - > version_minor , bh - > block_total_length ) ;
2008-07-09 20:09:23 +00:00
break ;
default :
/* Not a "pcapng" magic number we know about. */
2010-04-05 22:20:21 +00:00
if ( first_block ) {
/* Not a pcap-ng file. */
return 0 ;
}
/* A bad block */
2011-12-13 09:53:50 +00:00
* err = WTAP_ERR_BAD_FILE ;
2010-04-05 22:20:21 +00:00
* err_info = g_strdup_printf ( " pcapng_read_section_header_block: unknown byte-order magic number 0x%08x " , shb . magic ) ;
2008-07-09 20:09:23 +00:00
return 0 ;
2008-01-13 21:10:09 +00:00
}
2010-04-05 22:20:21 +00:00
/* OK, at this point we assume it's a pcap-ng file. */
2012-02-20 20:15:51 +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. " ) ;
return 0 ;
}
2010-04-05 22:20:21 +00:00
2008-01-13 21:10:09 +00:00
/* we currently only understand SHB V1.0 */
2010-04-05 22:20:21 +00:00
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 " ,
2008-07-09 20:09:23 +00:00
pn - > version_major , pn - > version_minor ) ;
2010-04-05 22:20:21 +00:00
return - 1 ;
2008-01-13 21:10:09 +00:00
}
2012-02-20 20:15:51 +00:00
2008-01-21 01:54:28 +00:00
/* 64bit section_length (currently unused) */
2009-06-28 11:09:24 +00:00
if ( pn - > byte_swapped ) {
2008-07-09 20:09:23 +00:00
wblock - > data . section . section_length = BSWAP64 ( shb . section_length ) ;
} else {
wblock - > data . section . section_length = shb . section_length ;
}
2008-01-13 21:10:09 +00:00
2008-01-19 12:09:00 +00:00
/* Option defaults */
2008-01-13 21:10:09 +00:00
wblock - > data . section . opt_comment = NULL ;
wblock - > data . section . shb_hardware = NULL ;
2012-02-14 17:07:52 +00:00
wblock - > data . section . shb_os = NULL ;
2008-01-13 21:10:09 +00:00
wblock - > data . section . shb_user_appl = NULL ;
2008-01-19 12:09:00 +00:00
/* Options */
errno = WTAP_ERR_CANT_READ ;
2012-02-22 18:32:43 +00:00
to_read = bh - > block_total_length - MIN_SHB_SIZE ;
2012-02-14 17:07:52 +00:00
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = g_malloc ( opt_cont_buf_len ) ;
pcapng_debug1 ( " pcapng_read_section_header_block: Options %u bytes " , to_read ) ;
2008-07-09 20:09:23 +00:00
while ( to_read > 0 ) {
/* read option */
2012-02-14 17:07:52 +00:00
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 , err , err_info ) ;
2008-07-09 20:09:23 +00:00
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_section_header_block: failed to read option " ) ;
return bytes_read ;
}
block_read + = bytes_read ;
to_read - = bytes_read ;
/* handle option content */
switch ( oh . option_code ) {
case ( 0 ) : /* opt_endofopt */
if ( to_read ! = 0 ) {
pcapng_debug1 ( " pcapng_read_section_header_block: %u bytes after opt_endofopt " , to_read ) ;
}
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( 1 ) : /* opt_comment */
2012-02-14 17:07:52 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . section . opt_comment = g_strndup ( option_content , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
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 ( 2 ) : /* shb_hardware */
2012-02-14 17:07:52 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . section . shb_hardware = g_strndup ( option_content , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
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 ) ;
}
break ;
case ( 3 ) : /* shb_os */
2012-02-14 17:07:52 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . section . shb_os = g_strndup ( option_content , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
pcapng_debug1 ( " pcapng_read_section_header_block: shb_os %s " , wblock - > data . section . shb_os ) ;
} else {
2012-02-14 17:07:52 +00:00
pcapng_debug2 ( " pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u " , oh . option_length , to_read ) ;
2008-07-09 20:09:23 +00:00
}
break ;
2012-02-15 19:44:16 +00:00
case ( 4 ) : /* shb_user_appl */
2012-02-14 17:07:52 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
wblock - > data . section . shb_user_appl = g_strndup ( option_content , oh . option_length ) ;
2012-02-15 19:44:16 +00:00
pcapng_debug1 ( " pcapng_read_section_header_block: shb_user_appl %s " , wblock - > data . section . shb_user_appl ) ;
2008-07-09 20:09:23 +00:00
} else {
2012-02-15 19:44:16 +00:00
pcapng_debug1 ( " pcapng_read_section_header_block: shb_user_appl length %u seems strange " , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
}
break ;
default :
pcapng_debug2 ( " pcapng_read_section_header_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
}
}
2012-02-14 17:07:52 +00:00
g_free ( option_content ) ;
2008-01-19 12:09:00 +00:00
return block_read ;
2008-01-13 21:10:09 +00:00
}
/* "Interface Description Block" */
static int
2009-06-27 17:33:23 +00:00
pcapng_read_if_descr_block ( FILE_T fh , pcapng_block_header_t * bh , pcapng_t * pn ,
2011-04-21 09:41:52 +00:00
wtapng_block_t * wblock , int * err , gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
2012-02-20 20:15:51 +00:00
guint64 time_units_per_second = 1000000 ; /* default */
2008-01-13 21:10:09 +00:00
int bytes_read ;
2008-01-18 10:29:23 +00:00
int block_read ;
2012-02-20 20:15:51 +00:00
int to_read , opt_cont_buf_len ;
2008-01-13 21:10:09 +00:00
pcapng_interface_description_block_t idb ;
2008-07-09 20:09:23 +00:00
pcapng_option_header_t oh ;
2012-02-20 20:15:51 +00:00
char * option_content = NULL ; /* Allocate as large as the options block */
2012-02-22 18:32:43 +00:00
/*
* Is this block long enough to be an IDB ?
*/
if ( bh - > block_total_length < MIN_IDB_SIZE ) {
/*
* No .
*/
* 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 ) ;
return - 1 ;
}
2008-01-13 21:10:09 +00:00
/* read block content */
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & idb , sizeof idb , fh ) ;
2008-01-13 21:10:09 +00:00
if ( bytes_read ! = sizeof idb ) {
2008-01-26 14:08:51 +00:00
pcapng_debug0 ( " pcapng_read_if_descr_block: failed to read IDB " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2008-01-13 21:10:09 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
2008-07-09 20:09:23 +00:00
block_read = bytes_read ;
2008-01-13 21:10:09 +00:00
2008-01-19 12:09:00 +00:00
/* mandatory values */
2009-06-27 12:14:18 +00:00
if ( pn - > byte_swapped ) {
2008-01-13 21:10:09 +00:00
wblock - > data . if_descr . link_type = BSWAP16 ( idb . linktype ) ;
wblock - > data . if_descr . snap_len = BSWAP32 ( idb . snaplen ) ;
} else {
wblock - > data . if_descr . link_type = idb . linktype ;
wblock - > data . if_descr . snap_len = idb . snaplen ;
}
2012-02-20 20:15:51 +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 ;
2009-06-27 11:39:47 +00:00
pcapng_debug3 ( " pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u " ,
wblock - > data . if_descr . link_type ,
2012-02-20 20:15:51 +00:00
wtap_encap_string ( wblock - > data . if_descr . wtap_encap ) ,
2009-06-27 11:39:47 +00:00
wblock - > data . if_descr . snap_len ) ;
2008-01-13 21:10:09 +00:00
2009-06-27 12:14:18 +00:00
if ( wblock - > data . if_descr . snap_len > WTAP_MAX_PACKET_SIZE ) {
2012-03-03 16:17:20 +00:00
/* This is unrealistic, but text2pcap currently uses 102400.
2009-06-27 18:50:13 +00:00
* 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. " ,
2008-07-09 20:09:23 +00:00
wblock - > data . if_descr . snap_len ) ;
2009-06-27 18:50:13 +00:00
/*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
2008-01-13 21:10:09 +00:00
}
2008-01-19 12:09:00 +00:00
/* Option defaults */
2012-02-21 16:32:25 +00:00
wblock - > data . if_descr . opt_comment = NULL ;
wblock - > data . if_descr . if_name = NULL ;
wblock - > data . if_descr . if_description = NULL ;
2008-01-13 21:10:09 +00:00
/* XXX: if_IPv4addr */
/* XXX: if_IPv6addr */
/* XXX: if_MACaddr */
/* XXX: if_EUIaddr */
2012-02-21 16:32:25 +00:00
wblock - > data . if_descr . if_speed = 0 ; /* "unknown" */
wblock - > data . if_descr . if_tsresol = 6 ; /* default is 6 for microsecond resolution */
2012-03-04 19:01:14 +00:00
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 ;
2012-02-21 16:32:25 +00:00
wblock - > data . if_descr . if_os = NULL ;
wblock - > data . if_descr . if_fcslen = - 1 ; /* unknown or changes between packets */
2008-01-13 21:10:09 +00:00
/* XXX: guint64 if_tsoffset; */
2008-01-18 10:29:23 +00:00
2008-01-19 12:09:00 +00:00
/* Options */
2008-01-18 10:29:23 +00:00
errno = WTAP_ERR_CANT_READ ;
2012-02-22 18:32:43 +00:00
to_read = bh - > block_total_length - MIN_IDB_SIZE ;
2012-02-20 20:15:51 +00:00
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = g_malloc ( opt_cont_buf_len ) ;
2009-06-27 12:14:18 +00:00
while ( to_read > 0 ) {
2008-07-09 20:09:23 +00:00
/* read option */
2012-02-20 20:15:51 +00:00
bytes_read = pcapng_read_option ( fh , pn , & oh , option_content , opt_cont_buf_len , err , err_info ) ;
2008-07-09 20:09:23 +00:00
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_if_descr_block: failed to read option " ) ;
return bytes_read ;
}
block_read + = bytes_read ;
to_read - = bytes_read ;
/* 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 ) ;
}
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( 1 ) : /* opt_comment */
2012-02-21 16:32:25 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2012-02-20 20:15:51 +00:00
wblock - > data . if_descr . opt_comment = g_strndup ( option_content , oh . option_length ) ;
2011-08-11 21:42:37 +00:00
pcapng_debug1 ( " pcapng_read_if_descr_block: opt_comment %s " , wblock - > data . if_descr . opt_comment ) ;
2008-07-09 20:09:23 +00:00
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: opt_comment length %u seems strange " , oh . option_length ) ;
}
break ;
case ( 2 ) : /* if_name */
2012-02-21 16:32:25 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2012-02-20 20:15:51 +00:00
wblock - > data . if_descr . if_name = g_strndup ( option_content , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
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 ) ;
}
break ;
case ( 3 ) : /* if_description */
2012-02-21 16:32:25 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2012-02-20 20:15:51 +00:00
wblock - > data . if_descr . if_description = g_strndup ( option_content , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
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-02-20 20:15:51 +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
*/
2008-07-09 20:09:23 +00:00
case ( 8 ) : /* if_speed */
2012-02-21 16:32:25 +00:00
if ( oh . option_length = = 8 ) {
2008-07-09 20:16:24 +00:00
/* 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 ) ) ;
2011-02-04 02:08:47 +00:00
if ( pn - > byte_swapped )
2008-07-09 20:09:23 +00:00
wblock - > data . if_descr . if_speed = BSWAP64 ( 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 ) ;
}
break ;
case ( 9 ) : /* if_tsresol */
2009-05-03 15:09:23 +00:00
if ( oh . option_length = = 1 ) {
guint64 base ;
guint64 result ;
2012-02-20 20:15:51 +00:00
guint8 i , exponent , if_tsresol ;
2009-05-03 15:09:23 +00:00
2012-02-20 20:15:51 +00:00
if_tsresol = option_content [ 0 ] ;
if ( if_tsresol & 0x80 ) {
2009-05-03 15:09:23 +00:00
base = 2 ;
} else {
base = 10 ;
}
2012-02-20 20:15:51 +00:00
exponent = ( guint8 ) ( if_tsresol & 0x7f ) ;
2009-05-03 15:09:23 +00:00
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 ) ) {
2009-05-03 15:47:41 +00:00
pcapng_debug0 ( " pcapng_open: time conversion might be inaccurate " ) ;
2009-05-03 09:56:53 +00:00
}
pcapng_debug1 ( " pcapng_read_if_descr_block: if_tsresol %u " , wblock - > data . if_descr . if_tsresol ) ;
2012-02-20 20:15:51 +00:00
wblock - > data . if_descr . time_units_per_second = time_units_per_second ;
wblock - > data . if_descr . if_tsresol = if_tsresol ;
2008-07-09 20:09:23 +00:00
} else {
2009-05-03 09:56:53 +00:00
pcapng_debug1 ( " pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected " , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
}
break ;
2012-02-20 20:15:51 +00:00
/*
* if_tzone 10 Time zone for GMT support ( TODO : specify better ) . TODO : give a good example
*/
2009-04-25 19:11:35 +00:00
case ( 11 ) : /* if_filter */
2012-02-21 16:32:25 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2012-03-04 19:01:14 +00:00
/* 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 ) ;
2012-03-05 09:21:36 +00:00
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 ) ;
2012-03-04 19:01:14 +00:00
} 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 = g_malloc ( oh . option_length - 1 ) ;
memcpy ( & wblock - > data . if_descr . if_filter_bpf_bytes , option_content + 1 , oh . option_length - 1 ) ;
}
2009-04-25 19:11:35 +00:00
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: if_filter length %u seems strange " , oh . option_length ) ;
}
break ;
2012-02-20 20:15:51 +00:00
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 " / . . .
*/
2012-02-21 16:32:25 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2012-02-20 20:15:51 +00:00
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 ) ;
}
break ;
2008-07-09 20:09:23 +00:00
case ( 13 ) : /* if_fcslen */
2012-02-21 16:32:25 +00:00
if ( oh . option_length = = 1 ) {
2008-07-09 20:09:23 +00:00
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 */
} else {
pcapng_debug1 ( " pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected " , oh . option_length ) ;
}
break ;
2012-02-20 20:15:51 +00:00
/*
* 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 .
2012-03-03 16:17:20 +00:00
* 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-07-09 20:09:23 +00:00
default :
pcapng_debug2 ( " pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
}
}
2009-06-27 12:14:18 +00:00
2012-02-20 20:15:51 +00:00
g_free ( option_content ) ;
2009-06-27 17:33:23 +00:00
if ( * wblock - > file_encap = = WTAP_ENCAP_UNKNOWN ) {
2012-02-20 20:15:51 +00:00
* wblock - > file_encap = wblock - > data . if_descr . wtap_encap ;
2009-06-27 12:14:18 +00:00
} else {
2012-02-20 20:15:51 +00:00
if ( * wblock - > file_encap ! = wblock - > data . if_descr . wtap_encap ) {
2009-06-27 17:33:23 +00:00
* wblock - > file_encap = WTAP_ENCAP_PER_PACKET ;
2009-06-27 12:14:18 +00:00
}
}
2008-01-18 10:29:23 +00:00
return block_read ;
2008-01-13 21:10:09 +00:00
}
2011-02-04 02:08:47 +00:00
static int
2011-04-21 09:41:52 +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 )
2008-01-13 21:10:09 +00:00
{
2008-01-19 12:34:43 +00:00
int bytes_read ;
2008-01-19 12:09:00 +00:00
int block_read ;
2012-02-20 20:15:51 +00:00
int to_read , opt_cont_buf_len ;
2008-01-19 12:09:00 +00:00
guint64 file_offset64 ;
2008-01-13 21:10:09 +00:00
pcapng_enhanced_packet_block_t epb ;
2009-04-26 02:59:16 +00:00
pcapng_packet_block_t pb ;
2008-01-13 21:10:09 +00:00
guint32 block_total_length ;
2012-02-22 18:32:43 +00:00
guint32 padding ;
2012-03-02 05:03:06 +00:00
interface_data_t int_data ;
guint64 ts ;
2008-07-09 20:09:23 +00:00
pcapng_option_header_t oh ;
2009-06-27 11:39:47 +00:00
int pseudo_header_len ;
2012-02-20 20:15:51 +00:00
char * option_content = NULL ; /* Allocate as large as the options block */
2011-09-01 09:43:10 +00:00
int fcslen ;
2008-01-13 21:10:09 +00:00
2008-01-19 12:09:00 +00:00
/* "(Enhanced) Packet Block" read fixed part */
2008-01-13 21:10:09 +00:00
errno = WTAP_ERR_CANT_READ ;
2009-04-26 02:59:16 +00:00
if ( enhanced ) {
2012-02-22 18:32:43 +00:00
/*
* Is this block long enough to be an EPB ?
*/
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 ) ;
return - 1 ;
}
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & epb , sizeof epb , fh ) ;
2009-04-26 02:59:16 +00:00
if ( bytes_read ! = sizeof epb ) {
pcapng_debug0 ( " pcapng_read_packet_block: failed to read packet data " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2009-04-26 02:59:16 +00:00
return 0 ;
}
block_read = bytes_read ;
2008-01-13 21:10:09 +00:00
2009-04-26 07:46:03 +00:00
if ( pn - > byte_swapped ) {
2009-04-25 19:11:35 +00:00
wblock - > data . packet . interface_id = BSWAP32 ( epb . interface_id ) ;
wblock - > data . packet . drops_count = - 1 ; /* invalid */
2012-02-22 18:32:43 +00:00
wblock - > data . packet . ts_high = BSWAP32 ( epb . timestamp_high ) ;
wblock - > data . packet . ts_low = BSWAP32 ( epb . timestamp_low ) ;
wblock - > data . packet . cap_len = BSWAP32 ( epb . captured_len ) ;
2009-04-26 02:59:16 +00:00
wblock - > data . packet . packet_len = BSWAP32 ( epb . packet_len ) ;
2009-04-25 19:11:35 +00:00
} else {
wblock - > data . packet . interface_id = epb . interface_id ;
wblock - > data . packet . drops_count = - 1 ; /* invalid */
2012-02-22 18:32:43 +00:00
wblock - > data . packet . ts_high = epb . timestamp_high ;
wblock - > data . packet . ts_low = epb . timestamp_low ;
wblock - > data . packet . cap_len = epb . captured_len ;
2009-04-26 02:59:16 +00:00
wblock - > data . packet . packet_len = epb . packet_len ;
}
} else {
2012-02-22 18:32:43 +00:00
/*
* Is this block long enough to be a PB ?
*/
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 ) ;
return - 1 ;
}
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & pb , sizeof pb , fh ) ;
2009-04-26 02:59:16 +00:00
if ( bytes_read ! = sizeof pb ) {
pcapng_debug0 ( " pcapng_read_packet_block: failed to read packet data " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2009-04-26 02:59:16 +00:00
return 0 ;
}
block_read = bytes_read ;
2009-04-26 07:46:03 +00:00
if ( pn - > byte_swapped ) {
2009-04-26 02:59:16 +00:00
wblock - > data . packet . interface_id = BSWAP16 ( pb . interface_id ) ;
wblock - > data . packet . drops_count = BSWAP16 ( pb . drops_count ) ;
2012-02-22 18:32:43 +00:00
wblock - > data . packet . ts_high = BSWAP32 ( pb . timestamp_high ) ;
wblock - > data . packet . ts_low = BSWAP32 ( pb . timestamp_low ) ;
wblock - > data . packet . cap_len = BSWAP32 ( pb . captured_len ) ;
2009-04-26 02:59:16 +00:00
wblock - > data . packet . packet_len = BSWAP32 ( pb . packet_len ) ;
2009-04-25 19:11:35 +00:00
} else {
2009-04-26 02:59:16 +00:00
wblock - > data . packet . interface_id = pb . interface_id ;
wblock - > data . packet . drops_count = pb . drops_count ;
2012-02-22 18:32:43 +00:00
wblock - > data . packet . ts_high = pb . timestamp_high ;
wblock - > data . packet . ts_low = pb . timestamp_low ;
wblock - > data . packet . cap_len = pb . captured_len ;
2009-04-26 02:59:16 +00:00
wblock - > data . packet . packet_len = pb . packet_len ;
2009-04-25 19:11:35 +00:00
}
2012-02-22 18:32:43 +00:00
}
/*
* How much padding is there at the end of the packet data ?
*/
if ( ( wblock - > data . packet . cap_len % 4 ) ! = 0 )
padding = 4 - ( wblock - > data . 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 ;
}
/*
* Is this block long enough to hold the packet data ?
*/
if ( enhanced ) {
if ( block_total_length <
MIN_EPB_SIZE + wblock - > data . 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 , wblock - > data . packet . cap_len ) ;
return - 1 ;
}
} else {
if ( block_total_length <
MIN_PB_SIZE + wblock - > data . 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 , wblock - > data . packet . cap_len ) ;
return - 1 ;
}
2008-01-13 21:10:09 +00:00
}
2009-06-26 15:08:04 +00:00
if ( wblock - > data . packet . cap_len > wblock - > data . packet . packet_len ) {
2011-12-13 09:53:50 +00:00
* err = WTAP_ERR_BAD_FILE ;
2011-02-04 02:24:33 +00:00
* err_info = g_strdup_printf ( " pcapng_read_packet_block: cap_len %u is larger than packet_len %u. " ,
wblock - > data . packet . cap_len , wblock - > data . packet . packet_len ) ;
2009-06-26 15:08:04 +00:00
return 0 ;
}
if ( wblock - > data . packet . cap_len > WTAP_MAX_PACKET_SIZE ) {
2011-12-13 09:53:50 +00:00
* err = WTAP_ERR_BAD_FILE ;
2011-02-04 02:24:33 +00:00
* err_info = g_strdup_printf ( " pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u. " ,
wblock - > data . packet . cap_len , WTAP_MAX_PACKET_SIZE ) ;
2009-06-26 15:08:04 +00:00
return 0 ;
}
2009-04-25 19:11:35 +00:00
pcapng_debug3 ( " pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u " ,
wblock - > data . packet . packet_len ,
wblock - > data . packet . cap_len ,
wblock - > data . packet . interface_id ) ;
2008-01-13 21:10:09 +00:00
2012-03-02 05:03:06 +00:00
if ( wblock - > data . packet . interface_id > = pn - > number_of_interfaces ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: interface index %u is not less than interface count %u. " ,
wblock - > data . packet . interface_id , pn - > number_of_interfaces ) ;
return FALSE ;
}
int_data = g_array_index ( pn - > interface_data , interface_data_t ,
wblock - > data . packet . interface_id ) ;
wblock - > packet_header - > presence_flags = WTAP_HAS_TS | WTAP_HAS_CAP_LEN | WTAP_HAS_INTERFACE_ID ;
2009-06-28 11:09:24 +00:00
pcapng_debug3 ( " pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d. " ,
2012-03-02 05:03:06 +00:00
int_data . wtap_encap ,
wtap_encap_string ( int_data . wtap_encap ) ,
pcap_get_phdr_size ( int_data . wtap_encap , wblock - > pseudo_header ) ) ;
wblock - > packet_header - > interface_id = wblock - > data . packet . interface_id ;
wblock - > packet_header - > pkt_encap = int_data . wtap_encap ;
2008-01-13 21:10:09 +00:00
2009-06-26 15:08:04 +00:00
memset ( ( void * ) wblock - > pseudo_header , 0 , sizeof ( union wtap_pseudo_header ) ) ;
2009-06-27 16:08:18 +00:00
pseudo_header_len = pcap_process_pseudo_header ( fh ,
WTAP_FILE_PCAPNG ,
2012-03-02 05:03:06 +00:00
int_data . wtap_encap ,
2009-06-27 11:39:47 +00:00
wblock - > data . packet . cap_len ,
TRUE ,
2009-06-27 17:33:23 +00:00
wblock - > packet_header ,
2009-06-27 11:39:47 +00:00
( union wtap_pseudo_header * ) wblock - > pseudo_header ,
err ,
err_info ) ;
if ( pseudo_header_len < 0 ) {
2012-03-02 05:03:06 +00:00
return FALSE ;
2009-06-27 11:39:47 +00:00
}
block_read + = pseudo_header_len ;
2012-03-02 05:03:06 +00:00
if ( pseudo_header_len ! = pcap_get_phdr_size ( int_data . wtap_encap , wblock - > pseudo_header ) ) {
2009-06-27 11:39:47 +00:00
pcapng_debug1 ( " pcapng_read_packet_block: Could only read %d bytes for pseudo header. " ,
pseudo_header_len ) ;
}
2012-03-02 09:03:26 +00:00
wblock - > packet_header - > caplen = wblock - > data . packet . cap_len - pseudo_header_len ;
wblock - > packet_header - > len = wblock - > data . packet . packet_len - pseudo_header_len ;
2012-03-02 05:03:06 +00:00
/* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
ts = ( ( ( guint64 ) wblock - > data . packet . ts_high ) < < 32 ) | ( ( guint64 ) wblock - > data . packet . ts_low ) ;
wblock - > packet_header - > ts . secs = ( time_t ) ( ts / int_data . time_units_per_second ) ;
wblock - > packet_header - > ts . nsecs = ( int ) ( ( ( ts % int_data . time_units_per_second ) * 1000000000 ) / int_data . time_units_per_second ) ;
2008-01-13 21:10:09 +00:00
2008-01-19 12:09:00 +00:00
/* "(Enhanced) Packet Block" read capture data */
2008-01-13 21:10:09 +00:00
errno = WTAP_ERR_CANT_READ ;
2011-09-01 09:43:10 +00:00
bytes_read = file_read ( ( guint8 * ) ( wblock - > frame_buffer ) , wblock - > data . packet . cap_len - pseudo_header_len , fh ) ;
2009-06-27 11:39:47 +00:00
if ( bytes_read ! = ( int ) ( wblock - > data . packet . cap_len - pseudo_header_len ) ) {
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2011-02-04 02:08:47 +00:00
pcapng_debug1 ( " pcapng_read_packet_block: couldn't read %u bytes of captured data " ,
2009-06-27 11:39:47 +00:00
wblock - > data . packet . cap_len - pseudo_header_len ) ;
2008-01-13 21:10:09 +00:00
if ( * err = = 0 )
* err = WTAP_ERR_SHORT_READ ;
2009-06-26 15:08:04 +00:00
return 0 ;
2008-01-13 21:10:09 +00:00
}
2008-01-19 12:09:00 +00:00
block_read + = bytes_read ;
2008-07-09 20:09:23 +00:00
/* jump over potential padding bytes at end of the packet data */
2012-02-22 18:32:43 +00:00
if ( padding ! = 0 ) {
file_offset64 = file_seek ( fh , padding , SEEK_CUR , err ) ;
2008-07-09 20:09:23 +00:00
if ( file_offset64 < = 0 ) {
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
2012-02-22 18:32:43 +00:00
block_read + = padding ;
2008-01-13 21:10:09 +00:00
}
2008-01-19 12:09:00 +00:00
/* Option defaults */
2012-03-02 05:03:06 +00:00
wblock - > packet_header - > opt_comment = NULL ;
wblock - > packet_header - > drop_count = - 1 ;
wblock - > packet_header - > pack_flags = 0 ;
2008-01-13 21:10:09 +00:00
2011-09-01 09:43:10 +00:00
/* FCS length default */
fcslen = pn - > if_fcslen ;
2012-02-11 17:31:13 +00:00
/* Options
* opt_comment 1
* epb_flags 2
* epb_hash 3
* epb_dropcount 4
*/
2008-01-13 21:10:09 +00:00
errno = WTAP_ERR_CANT_READ ;
2012-02-14 17:07:52 +00:00
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 ) ;
2012-02-20 20:15:51 +00:00
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = g_malloc ( opt_cont_buf_len ) ;
2008-07-09 20:09:23 +00:00
while ( to_read > 0 ) {
/* read option */
2012-02-20 20:15:51 +00:00
bytes_read = pcapng_read_option ( fh , pn , & oh , option_content , opt_cont_buf_len , err , err_info ) ;
2008-07-09 20:09:23 +00:00
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_packet_block: failed to read option " ) ;
return bytes_read ;
}
block_read + = bytes_read ;
to_read - = bytes_read ;
/* handle option content */
switch ( oh . option_code ) {
case ( 0 ) : /* opt_endofopt */
if ( to_read ! = 0 ) {
pcapng_debug1 ( " pcapng_read_packet_block: %u bytes after opt_endofopt " , to_read ) ;
}
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( 1 ) : /* opt_comment */
2012-02-20 20:15:51 +00:00
if ( oh . option_length > 0 & & oh . option_length < opt_cont_buf_len ) {
2012-03-02 05:03:06 +00:00
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 ) ;
2008-07-09 20:09:23 +00:00
} else {
pcapng_debug1 ( " pcapng_read_packet_block: opt_comment length %u seems strange " , oh . option_length ) ;
}
break ;
case ( 2 ) : /* pack_flags / epb_flags */
if ( oh . option_length = = 4 ) {
2008-07-09 20:16:24 +00:00
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
2012-03-02 05:03:06 +00:00
wblock - > packet_header - > presence_flags | = WTAP_HAS_PACK_FLAGS ;
memcpy ( & wblock - > packet_header - > pack_flags , option_content , sizeof ( guint32 ) ) ;
2011-02-04 02:08:47 +00:00
if ( pn - > byte_swapped )
2012-03-02 05:03:06 +00:00
wblock - > packet_header - > pack_flags = BSWAP32 ( wblock - > packet_header - > pack_flags ) ;
if ( wblock - > packet_header - > pack_flags & 0x000001E0 ) {
2011-09-01 09:43:10 +00:00
/* The FCS length is present */
2012-03-02 05:03:06 +00:00
fcslen = ( wblock - > packet_header - > pack_flags & 0x000001E0 ) > > 5 ;
2011-09-01 09:43:10 +00:00
}
2012-03-02 05:03:06 +00:00
pcapng_debug1 ( " pcapng_read_packet_block: pack_flags %u (ignored) " , wblock - > packet_header - > pack_flags ) ;
2008-07-09 20:09:23 +00:00
} else {
2012-02-12 21:56:00 +00:00
pcapng_debug1 ( " pcapng_read_packet_block: pack_flags length %u not 4 as expected " , oh . option_length ) ;
2008-07-09 20:09:23 +00:00
}
break ;
2012-03-02 05:03:06 +00:00
case ( 3 ) : /* epb_hash */
2012-02-11 17:31:13 +00:00
pcapng_debug2 ( " pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
break ;
2012-03-02 05:03:06 +00:00
case ( 4 ) : /* epb_dropcount */
2012-02-13 17:34:15 +00:00
if ( oh . option_length = = 8 ) {
2012-02-11 17:31:13 +00:00
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
2012-03-02 05:03:06 +00:00
wblock - > packet_header - > presence_flags | = WTAP_HAS_DROP_COUNT ;
memcpy ( & wblock - > packet_header - > drop_count , option_content , sizeof ( guint64 ) ) ;
2012-02-11 17:31:13 +00:00
if ( pn - > byte_swapped )
2012-03-02 05:03:06 +00:00
wblock - > packet_header - > drop_count = BSWAP64 ( wblock - > packet_header - > drop_count ) ;
2012-02-11 17:31:13 +00:00
2012-03-02 05:03:06 +00:00
pcapng_debug1 ( " pcapng_read_packet_block: drop_count % " G_GINT64_MODIFIER " u " , wblock - > packet_header - > drop_count ) ;
2012-02-11 17:31:13 +00:00
} else {
2012-02-13 17:34:15 +00:00
pcapng_debug1 ( " pcapng_read_packet_block: drop_count length %u not 8 as expected " , oh . option_length ) ;
2012-02-11 17:31:13 +00:00
}
break ;
2008-07-09 20:09:23 +00:00
default :
pcapng_debug2 ( " pcapng_read_packet_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
}
}
2008-01-19 12:09:00 +00:00
2012-02-21 06:57:14 +00:00
g_free ( option_content ) ;
2012-03-02 05:03:06 +00:00
pcap_read_post_process ( WTAP_FILE_PCAPNG , int_data . wtap_encap ,
2011-09-01 19:58:25 +00:00
( union wtap_pseudo_header * ) wblock - > pseudo_header ,
2011-09-01 09:43:10 +00:00
( guint8 * ) ( wblock - > frame_buffer ) ,
( int ) ( wblock - > data . packet . cap_len - pseudo_header_len ) ,
2011-09-01 19:58:25 +00:00
pn - > byte_swapped , fcslen ) ;
2009-05-03 09:56:53 +00:00
return block_read ;
2008-01-19 12:09:00 +00:00
}
2011-02-04 02:08:47 +00:00
static int
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
{
2008-01-19 12:34:43 +00:00
int bytes_read ;
2008-01-19 12:09:00 +00:00
int block_read ;
guint64 file_offset64 ;
2012-03-02 05:03:06 +00:00
interface_data_t int_data ;
2009-06-27 11:39:47 +00:00
int pseudo_header_len ;
2008-01-19 12:09:00 +00:00
pcapng_simple_packet_block_t spb ;
2012-02-22 18:32:43 +00:00
/*
* Is this block long enough to be an SPB ?
*/
if ( bh - > block_total_length < MIN_SPB_SIZE ) {
/*
* No .
*/
* 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 ) ;
return - 1 ;
}
2008-01-19 12:09:00 +00:00
/* "Simple Packet Block" read fixed part */
2008-01-13 21:10:09 +00:00
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & spb , sizeof spb , fh ) ;
2008-01-19 12:09:00 +00:00
if ( bytes_read ! = sizeof spb ) {
2008-01-26 14:08:51 +00:00
pcapng_debug0 ( " pcapng_read_simple_packet_block: failed to read packet data " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2008-01-13 21:10:09 +00:00
return 0 ;
}
2008-01-19 12:09:00 +00:00
block_read = bytes_read ;
2009-06-27 11:39:47 +00:00
if ( pn - > byte_swapped ) {
2008-07-09 20:09:23 +00:00
wblock - > data . simple_packet . packet_len = BSWAP32 ( spb . packet_len ) ;
2008-01-19 12:09:00 +00:00
} else {
wblock - > data . simple_packet . packet_len = spb . packet_len ;
2008-01-13 21:10:09 +00:00
}
2012-02-22 23:44:25 +00:00
wblock - > data . simple_packet . cap_len = bh - > block_total_length
2011-02-04 02:08:47 +00:00
- ( guint32 ) sizeof ( pcapng_simple_packet_block_t )
2009-04-22 03:07:37 +00:00
- ( guint32 ) sizeof ( bh - > block_total_length ) ;
2008-01-19 12:09:00 +00:00
2009-06-26 15:08:04 +00:00
if ( wblock - > data . simple_packet . cap_len > WTAP_MAX_PACKET_SIZE ) {
2011-12-13 09:53:50 +00:00
* err = WTAP_ERR_BAD_FILE ;
2011-02-04 02:24:33 +00:00
* err_info = g_strdup_printf ( " pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u. " ,
wblock - > data . simple_packet . cap_len , WTAP_MAX_PACKET_SIZE ) ;
2009-06-26 15:08:04 +00:00
return 0 ;
}
pcapng_debug1 ( " pcapng_read_simple_packet_block: packet data: packet_len %u " ,
wblock - > data . simple_packet . packet_len ) ;
2008-01-19 12:09:00 +00:00
2012-03-02 05:03:06 +00:00
if ( 0 > = pn - > number_of_interfaces ) {
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup_printf ( " pcapng: interface index 0 is not less than interface count %u. " ,
pn - > number_of_interfaces ) ;
return FALSE ;
}
int_data = g_array_index ( pn - > interface_data , interface_data_t , 0 ) ;
2009-06-27 11:39:47 +00:00
pcapng_debug1 ( " pcapng_read_simple_packet_block: Need to read pseudo header of size %d " ,
2012-03-02 05:03:06 +00:00
pcap_get_phdr_size ( int_data . wtap_encap , wblock - > pseudo_header ) ) ;
/* No time stamp in a simple packet block; no options, either */
wblock - > packet_header - > presence_flags = WTAP_HAS_CAP_LEN | WTAP_HAS_INTERFACE_ID ;
wblock - > packet_header - > interface_id = 0 ;
wblock - > packet_header - > pkt_encap = int_data . wtap_encap ;
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 ;
2009-06-27 11:39:47 +00:00
memset ( ( void * ) wblock - > pseudo_header , 0 , sizeof ( union wtap_pseudo_header ) ) ;
2009-06-27 16:08:18 +00:00
pseudo_header_len = pcap_process_pseudo_header ( fh ,
WTAP_FILE_PCAPNG ,
2012-03-02 05:03:06 +00:00
int_data . wtap_encap ,
2009-06-27 11:39:47 +00:00
wblock - > data . simple_packet . cap_len ,
TRUE ,
2009-06-27 17:33:23 +00:00
wblock - > packet_header ,
2009-06-27 11:39:47 +00:00
( union wtap_pseudo_header * ) wblock - > pseudo_header ,
err ,
err_info ) ;
if ( pseudo_header_len < 0 ) {
return 0 ;
}
2012-03-02 09:03:26 +00:00
wblock - > packet_header - > caplen = wblock - > data . simple_packet . cap_len - pseudo_header_len ;
wblock - > packet_header - > len = wblock - > data . packet . packet_len - pseudo_header_len ;
2009-06-27 11:39:47 +00:00
block_read + = pseudo_header_len ;
2012-03-02 05:03:06 +00:00
if ( pseudo_header_len ! = pcap_get_phdr_size ( int_data . wtap_encap , wblock - > pseudo_header ) ) {
2009-06-27 11:39:47 +00:00
pcapng_debug1 ( " pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header. " ,
pseudo_header_len ) ;
}
2009-06-26 15:08:04 +00:00
memset ( ( void * ) wblock - > pseudo_header , 0 , sizeof ( union wtap_pseudo_header ) ) ;
2008-01-19 12:09:00 +00:00
/* "Simple Packet Block" read capture data */
errno = WTAP_ERR_CANT_READ ;
2011-09-01 09:43:10 +00:00
bytes_read = file_read ( ( guint8 * ) ( wblock - > frame_buffer ) , wblock - > data . simple_packet . cap_len , fh ) ;
2008-01-19 12:34:43 +00:00
if ( bytes_read ! = ( int ) wblock - > data . simple_packet . cap_len ) {
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2011-02-04 02:08:47 +00:00
pcapng_debug1 ( " pcapng_read_simple_packet_block: couldn't read %u bytes of captured data " ,
2008-07-09 20:09:23 +00:00
wblock - > data . simple_packet . cap_len ) ;
2008-01-19 12:09:00 +00:00
if ( * err = = 0 )
* err = WTAP_ERR_SHORT_READ ;
2009-06-26 15:08:04 +00:00
return 0 ;
2008-01-19 12:09:00 +00:00
}
block_read + = bytes_read ;
2008-07-09 20:09:23 +00:00
/* jump over potential padding bytes at end of the packet data */
2009-06-26 15:08:04 +00:00
if ( ( wblock - > data . simple_packet . cap_len % 4 ) ! = 0 ) {
2008-07-09 20:09:23 +00:00
file_offset64 = file_seek ( fh , 4 - ( wblock - > data . simple_packet . cap_len % 4 ) , SEEK_CUR , err ) ;
if ( file_offset64 < = 0 ) {
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
block_read + = 4 - ( wblock - > data . simple_packet . cap_len % 4 ) ;
}
2008-01-19 12:09:00 +00:00
2012-03-02 05:03:06 +00:00
pcap_read_post_process ( WTAP_FILE_PCAPNG , int_data . wtap_encap ,
2011-09-01 19:58:25 +00:00
( union wtap_pseudo_header * ) wblock - > pseudo_header ,
2011-09-01 09:43:10 +00:00
( guint8 * ) ( wblock - > frame_buffer ) ,
( int ) wblock - > data . simple_packet . cap_len ,
2011-09-01 19:58:25 +00:00
pn - > byte_swapped , pn - > if_fcslen ) ;
2008-01-19 12:09:00 +00:00
return block_read ;
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 .
*
* If we don ' t find the terminating NUL , or if the name is zero - length
* ( not counting the terminating NUL ) , return - 1 and set * err and
* * err_info appropriately .
*/
static int
name_resolution_block_find_name_end ( guint8 * p , guint record_len , int * err ,
gchar * * err_info )
{
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 */
}
if ( namelen = = 0 ) {
/* The name is empty. */
* err = WTAP_ERR_BAD_FILE ;
* err_info = g_strdup ( " pcapng_read_name_resolution_block: NRB record has empty host name " ) ;
return - 1 ;
}
/* Include the NUL in the name length. */
return namelen + 1 ;
}
2011-03-24 22:47:57 +00:00
static int
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
{
int bytes_read = 0 ;
int block_read = 0 ;
int to_read ;
guint64 file_offset64 ;
pcapng_name_resolution_block_t nrb ;
2012-03-04 02:20:25 +00:00
Buffer nrb_rec ;
2011-03-24 22:47:57 +00:00
guint32 v4_addr ;
2012-03-04 02:20:25 +00:00
guint record_len ;
guint8 * namep ;
int namelen ;
2011-03-24 22:47:57 +00:00
2012-02-22 18:32:43 +00:00
/*
* Is this block long enough to be an NRB ?
*/
if ( bh - > block_total_length < MIN_NRB_SIZE ) {
/*
* No .
*/
* err = WTAP_ERR_BAD_FILE ;
2012-02-23 10:03:16 +00:00
* 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 " ,
2012-02-22 18:32:43 +00:00
bh - > block_total_length , MIN_NRB_SIZE ) ;
return - 1 ;
}
2011-03-24 22:47:57 +00:00
errno = WTAP_ERR_CANT_READ ;
2012-03-01 13:31:40 +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-01 10:13:02 +00:00
2012-03-01 13:31:40 +00:00
pcapng_debug1 ( " pcapng_read_name_resolution_block, total %d bytes " , bh - > block_total_length ) ;
2011-03-24 22:47:57 +00:00
2012-03-04 02:20:25 +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 .
*/
buffer_init ( & nrb_rec , INITIAL_NRB_REC_SIZE ) ;
2011-03-24 22:47:57 +00:00
while ( block_read < to_read ) {
2012-02-22 18:32:43 +00:00
/*
* There must be at least one record ' s worth of data
* here .
*/
if ( ( size_t ) ( to_read - block_read ) < sizeof nrb ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2012-02-22 18:32:43 +00:00
* 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 ) ;
return - 1 ;
}
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & nrb , sizeof nrb , fh ) ;
2011-03-24 22:47:57 +00:00
if ( bytes_read ! = sizeof nrb ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2011-03-24 22:47:57 +00:00
pcapng_debug0 ( " pcapng_read_name_resolution_block: failed to read record header " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2011-03-24 22:47:57 +00:00
return 0 ;
}
block_read + = bytes_read ;
if ( pn - > byte_swapped ) {
2011-03-31 16:46:16 +00:00
nrb . record_type = BSWAP16 ( nrb . record_type ) ;
nrb . record_len = BSWAP16 ( nrb . record_len ) ;
2011-03-24 22:47:57 +00:00
}
2012-02-22 18:32:43 +00:00
if ( to_read - block_read < nrb . record_len + PADDING4 ( nrb . record_len ) ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2012-02-22 18:32:43 +00:00
* 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 ) ) ;
return - 1 ;
}
2011-03-24 22:47:57 +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-04 02:20:25 +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-02-22 18:32:43 +00:00
if ( nrb . record_len < 4 ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2012-02-22 18:32:43 +00:00
* 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 ) ;
return - 1 ;
}
2012-03-04 02:20:25 +00:00
buffer_assure_space ( & nrb_rec , nrb . record_len ) ;
bytes_read = file_read ( buffer_start_ptr ( & nrb_rec ) ,
nrb . record_len , fh ) ;
2011-03-24 22:47:57 +00:00
if ( bytes_read ! = nrb . record_len ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2011-03-24 22:47:57 +00:00
pcapng_debug0 ( " pcapng_read_name_resolution_block: failed to read IPv4 record data " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2011-03-24 22:47:57 +00:00
return 0 ;
}
block_read + = bytes_read ;
if ( pn - > add_new_ipv4 ) {
2012-03-04 02:20:25 +00:00
/*
* Scan through all the names in
* the record and add them .
*/
memcpy ( & v4_addr ,
buffer_start_ptr ( & nrb_rec ) , 4 ) ;
2011-03-24 22:47:57 +00:00
if ( pn - > byte_swapped )
v4_addr = BSWAP32 ( v4_addr ) ;
2012-03-04 02:20:25 +00:00
for ( namep = 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 ) {
buffer_free ( & nrb_rec ) ;
return - 1 ; /* fail */
}
pn - > add_new_ipv4 ( v4_addr , namep ) ;
}
2011-03-24 22:47:57 +00:00
}
file_offset64 = file_seek ( fh , PADDING4 ( nrb . record_len ) , SEEK_CUR , err ) ;
if ( file_offset64 < = 0 ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2011-03-24 22:47:57 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
block_read + = PADDING4 ( nrb . record_len ) ;
break ;
case NRES_IP6RECORD :
2012-03-04 02:20:25 +00:00
/*
* 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 . )
*/
2012-02-22 18:32:43 +00:00
if ( nrb . record_len < 16 ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2012-02-22 18:32:43 +00:00
* 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 ) ;
return - 1 ;
}
2012-03-04 02:20:25 +00:00
if ( to_read < nrb . record_len ) {
buffer_free ( & nrb_rec ) ;
pcapng_debug0 ( " pcapng_read_name_resolution_block: insufficient data for IPv6 record " ) ;
2011-03-24 22:47:57 +00:00
return 0 ;
}
2012-03-04 02:20:25 +00:00
buffer_assure_space ( & nrb_rec , nrb . record_len ) ;
bytes_read = file_read ( buffer_start_ptr ( & nrb_rec ) ,
nrb . record_len , fh ) ;
2011-03-24 22:47:57 +00:00
if ( bytes_read ! = nrb . record_len ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2011-03-24 22:47:57 +00:00
pcapng_debug0 ( " pcapng_read_name_resolution_block: failed to read IPv6 record data " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2011-03-24 22:47:57 +00:00
return 0 ;
}
block_read + = bytes_read ;
if ( pn - > add_new_ipv6 ) {
2012-03-04 02:20:25 +00:00
for ( namep = 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 ) {
buffer_free ( & nrb_rec ) ;
return - 1 ; /* fail */
}
pn - > add_new_ipv6 ( buffer_start_ptr ( & nrb_rec ) ,
namep ) ;
}
2011-03-24 22:47:57 +00:00
}
file_offset64 = file_seek ( fh , PADDING4 ( nrb . record_len ) , SEEK_CUR , err ) ;
if ( file_offset64 < = 0 ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2011-03-24 22:47:57 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
block_read + = PADDING4 ( nrb . record_len ) ;
break ;
default :
pcapng_debug1 ( " pcapng_read_name_resolution_block: unknown record type 0x%x " , nrb . record_type ) ;
file_offset64 = file_seek ( fh , nrb . record_len + PADDING4 ( nrb . record_len ) , SEEK_CUR , err ) ;
if ( file_offset64 < = 0 ) {
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2011-03-24 22:47:57 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
block_read + = nrb . record_len + PADDING4 ( nrb . record_len ) ;
break ;
}
}
2012-03-04 02:20:25 +00:00
buffer_free ( & nrb_rec ) ;
2011-03-24 22:47:57 +00:00
return block_read ;
}
2011-02-04 02:08:47 +00:00
static int
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
{
int bytes_read ;
int block_read ;
2012-02-21 07:25:22 +00:00
int to_read , opt_cont_buf_len ;
2009-04-25 19:11:35 +00:00
pcapng_interface_statistics_block_t isb ;
pcapng_option_header_t oh ;
2012-02-21 06:57:14 +00:00
char * option_content = NULL ; /* Allocate as large as the options block */
2009-04-25 19:11:35 +00:00
2012-02-22 18:32:43 +00:00
/*
* Is this block long enough to be an ISB ?
*/
if ( bh - > block_total_length < MIN_ISB_SIZE ) {
/*
* No .
*/
* err = WTAP_ERR_BAD_FILE ;
2012-03-01 10:13:02 +00:00
* err_info = g_strdup_printf ( " pcapng_read_interface_statistics_block: total block length %u is too small (< %u) " ,
2012-02-22 18:32:43 +00:00
bh - > block_total_length , MIN_NRB_SIZE ) ;
return - 1 ;
}
2009-04-25 19:11:35 +00:00
/* "Interface Statistics Block" read fixed part */
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & isb , sizeof isb , fh ) ;
2009-04-25 19:11:35 +00:00
if ( bytes_read ! = sizeof isb ) {
pcapng_debug0 ( " pcapng_read_interface_statistics_block: failed to read packet data " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2009-04-25 19:11:35 +00:00
return 0 ;
}
block_read = bytes_read ;
if ( pn - > byte_swapped ) {
2012-03-01 14:51:26 +00:00
wblock - > data . if_stats . interface_id = BSWAP32 ( isb . interface_id ) ;
wblock - > data . if_stats . ts_high = BSWAP32 ( isb . timestamp_high ) ;
wblock - > data . if_stats . ts_low = BSWAP32 ( isb . timestamp_low ) ;
2009-04-25 19:11:35 +00:00
} else {
2012-03-01 14:51:26 +00:00
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 ;
2009-04-25 19:11:35 +00:00
}
2012-02-23 11:55:24 +00:00
pcapng_debug1 ( " pcapng_read_interface_statistics_block: interface_id %u " , wblock - > data . if_stats . interface_id ) ;
2009-04-25 19:11:35 +00:00
/* Option defaults */
wblock - > data . if_stats . opt_comment = NULL ;
wblock - > data . if_stats . isb_ifrecv = - 1 ;
wblock - > data . if_stats . isb_ifdrop = - 1 ;
/* Options */
errno = WTAP_ERR_CANT_READ ;
2012-02-14 17:07:52 +00:00
to_read = bh - > block_total_length -
2012-02-22 18:32:43 +00:00
( MIN_BLOCK_SIZE + block_read ) ; /* fixed and variable part, including padding */
2012-02-21 06:57:14 +00:00
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read ;
option_content = g_malloc ( opt_cont_buf_len ) ;
2009-04-25 19:11:35 +00:00
while ( to_read > 0 ) {
/* read option */
2012-02-21 06:57:14 +00:00
bytes_read = pcapng_read_option ( fh , pn , & oh , option_content , opt_cont_buf_len , err , err_info ) ;
2009-04-25 19:11:35 +00:00
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_read_interface_statistics_block: failed to read option " ) ;
return bytes_read ;
}
block_read + = bytes_read ;
to_read - = bytes_read ;
/* 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 ) ;
}
/* padding should be ok here, just get out of this */
to_read = 0 ;
break ;
case ( 1 ) : /* opt_comment */
2012-02-21 06:57:14 +00:00
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 ) ;
2011-08-11 21:42:37 +00:00
pcapng_debug1 ( " pcapng_read_interface_statistics_block: opt_comment %s " , wblock - > data . if_stats . opt_comment ) ;
2009-04-25 19:11:35 +00:00
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: opt_comment length %u seems strange " , oh . option_length ) ;
}
break ;
2012-02-22 14:41:02 +00:00
case ( 2 ) : /* isb_starttime */
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_starttime , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_stats . isb_starttime = BSWAP64 ( wblock - > data . if_stats . isb_starttime ) ;
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 ) {
/* Don't cast a char[] into a guint32--the
* char [ ] may not be aligned correctly .
*/
memcpy ( & wblock - > data . if_stats . isb_endtime , option_content , sizeof ( guint64 ) ) ;
if ( pn - > byte_swapped )
wblock - > data . if_stats . isb_endtime = BSWAP64 ( wblock - > data . if_stats . isb_endtime ) ;
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 ;
2009-04-25 19:11:35 +00:00
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 ) ) ;
2011-02-04 02:08:47 +00:00
if ( pn - > byte_swapped )
2009-04-25 19:11:35 +00:00
wblock - > data . if_stats . isb_ifrecv = BSWAP64 ( wblock - > data . if_stats . isb_ifrecv ) ;
2009-04-25 21:06:09 +00:00
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_ifrecv % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_ifrecv ) ;
2009-04-25 19:11:35 +00:00
} 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 ) ) ;
2011-02-04 02:08:47 +00:00
if ( pn - > byte_swapped )
2009-04-25 19:11:35 +00:00
wblock - > data . if_stats . isb_ifdrop = BSWAP64 ( wblock - > data . if_stats . isb_ifdrop ) ;
2009-04-25 21:06:09 +00:00
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_ifdrop % " G_GINT64_MODIFIER " u " , wblock - > data . if_stats . isb_ifdrop ) ;
2009-04-25 19:11:35 +00:00
} else {
pcapng_debug1 ( " pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected " , oh . option_length ) ;
}
break ;
2012-02-22 14:41:02 +00:00
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 = BSWAP64 ( 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 = BSWAP64 ( 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 ) ;
}
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 = BSWAP64 ( 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 ;
2009-04-25 19:11:35 +00:00
default :
pcapng_debug2 ( " pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes " ,
oh . option_code , oh . option_length ) ;
}
}
2012-02-21 06:57:14 +00:00
g_free ( option_content ) ;
2012-02-22 18:32:43 +00:00
return block_read ;
2009-04-25 19:11:35 +00:00
}
2008-01-13 21:10:09 +00:00
2011-02-04 02:08:47 +00:00
static int
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
{
int block_read ;
guint64 file_offset64 ;
guint32 block_total_length ;
2012-02-23 10:03:16 +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 ) ;
return - 1 ;
}
2008-01-19 12:09:00 +00:00
2009-04-25 19:11:35 +00:00
/* add padding bytes to "block total length" */
2008-01-19 12:09:00 +00:00
/* (the "block total length" of some example files don't contain any padding bytes!) */
2009-06-26 15:08:04 +00:00
if ( bh - > block_total_length % 4 ) {
2008-01-19 12:09:00 +00:00
block_total_length = bh - > block_total_length + 4 - ( bh - > block_total_length % 4 ) ;
} else {
block_total_length = bh - > block_total_length ;
}
2012-02-22 18:32:43 +00:00
block_read = block_total_length - MIN_BLOCK_SIZE ;
2008-01-19 12:09:00 +00:00
2008-07-09 20:09:23 +00:00
/* jump over this unknown block */
file_offset64 = file_seek ( fh , block_read , SEEK_CUR , err ) ;
if ( file_offset64 < = 0 ) {
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
2008-01-19 12:09:00 +00:00
return block_read ;
}
2008-01-13 21:10:09 +00:00
2009-06-27 17:33:23 +00:00
2011-02-04 02:08:47 +00:00
static int
2010-04-05 22:20:21 +00:00
pcapng_read_block ( FILE_T fh , gboolean first_block , pcapng_t * pn , wtapng_block_t * wblock , int * err , gchar * * err_info )
2008-01-13 21:10:09 +00:00
{
2009-06-27 11:39:47 +00:00
int block_read ;
int bytes_read ;
2008-01-13 21:10:09 +00:00
pcapng_block_header_t bh ;
2008-01-19 12:09:00 +00:00
guint32 block_total_length ;
2008-01-13 21:10:09 +00:00
/* Try to read the (next) block header */
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & bh , sizeof bh , fh ) ;
2008-01-19 12:09:00 +00:00
if ( bytes_read ! = sizeof bh ) {
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2011-04-19 13:28:17 +00:00
pcapng_debug3 ( " pcapng_read_block: file_read() returned %d instead of %u, err = %d. " , bytes_read , ( unsigned int ) sizeof bh , * err ) ;
2008-01-13 21:10:09 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
2008-07-09 20:09:23 +00:00
block_read = bytes_read ;
2009-06-27 11:39:47 +00:00
if ( pn - > byte_swapped ) {
bh . block_type = BSWAP32 ( bh . block_type ) ;
bh . block_total_length = BSWAP32 ( bh . block_total_length ) ;
2008-01-13 21:10:09 +00:00
}
wblock - > type = bh . block_type ;
2009-05-03 09:56:53 +00:00
pcapng_debug1 ( " pcapng_read_block: block_type 0x%x " , bh . block_type ) ;
2008-01-13 21:10:09 +00:00
2010-04-05 22:20:21 +00:00
if ( first_block ) {
/*
* This is being read in by pcapng_open ( ) , so this block
* must be an SHB . If it ' s not , this is not a pcap - ng
* file .
*
* XXX - check for various forms of Windows < - > UN * X
* mangling , and suggest that the file might be a
* pcap - ng file that was damaged in transit ?
*/
if ( bh . block_type ! = BLOCK_TYPE_SHB )
return 0 ; /* not a pcap-ng file */
}
2008-01-13 21:10:09 +00:00
switch ( bh . block_type ) {
2008-01-18 00:59:30 +00:00
case ( BLOCK_TYPE_SHB ) :
2010-04-05 22:20:21 +00:00
bytes_read = pcapng_read_section_header_block ( fh , first_block , & bh , pn , wblock , err , err_info ) ;
2008-01-13 21:10:09 +00:00
break ;
2008-01-18 00:59:30 +00:00
case ( BLOCK_TYPE_IDB ) :
2009-06-27 17:33:23 +00:00
bytes_read = pcapng_read_if_descr_block ( fh , & bh , pn , wblock , err , err_info ) ;
2008-01-13 21:10:09 +00:00
break ;
2008-01-18 00:59:30 +00:00
case ( BLOCK_TYPE_PB ) :
2009-06-27 17:33:23 +00:00
bytes_read = pcapng_read_packet_block ( fh , & bh , pn , wblock , err , err_info , FALSE ) ;
2008-01-19 12:09:00 +00:00
break ;
case ( BLOCK_TYPE_SPB ) :
2009-06-27 17:33:23 +00:00
bytes_read = pcapng_read_simple_packet_block ( fh , & bh , pn , wblock , err , err_info ) ;
2008-01-13 21:10:09 +00:00
break ;
2008-01-18 00:59:30 +00:00
case ( BLOCK_TYPE_EPB ) :
2009-06-27 17:33:23 +00:00
bytes_read = pcapng_read_packet_block ( fh , & bh , pn , wblock , err , err_info , TRUE ) ;
2009-04-25 19:11:35 +00:00
break ;
2011-03-24 22:47:57 +00:00
case ( BLOCK_TYPE_NRB ) :
bytes_read = pcapng_read_name_resolution_block ( fh , & bh , pn , wblock , err , err_info ) ;
break ;
2009-04-25 19:11:35 +00:00
case ( BLOCK_TYPE_ISB ) :
bytes_read = pcapng_read_interface_statistics_block ( fh , & bh , pn , wblock , err , err_info ) ;
2008-01-13 21:10:09 +00:00
break ;
default :
2009-04-25 19:11:35 +00:00
pcapng_debug2 ( " pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d " , bh . block_type , bh . block_total_length ) ;
2008-01-19 12:09:00 +00:00
bytes_read = pcapng_read_unknown_block ( fh , & bh , pn , wblock , err , err_info ) ;
}
2008-07-09 20:09:23 +00:00
2009-06-26 15:08:04 +00:00
if ( bytes_read < = 0 ) {
2008-07-09 20:09:23 +00:00
return bytes_read ;
}
block_read + = bytes_read ;
2008-01-19 12:09:00 +00:00
/* sanity check: first and second block lengths must match */
errno = WTAP_ERR_CANT_READ ;
2011-04-06 06:51:19 +00:00
bytes_read = file_read ( & block_total_length , sizeof block_total_length , fh ) ;
2008-01-19 12:09:00 +00:00
if ( bytes_read ! = sizeof block_total_length ) {
2008-01-26 14:08:51 +00:00
pcapng_debug0 ( " pcapng_read_block: couldn't read second block length " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( fh , err_info ) ;
2010-04-05 22:20:21 +00:00
if ( * err = = 0 )
* err = WTAP_ERR_SHORT_READ ;
return - 1 ;
2008-01-13 21:10:09 +00:00
}
2008-07-09 20:09:23 +00:00
block_read + = bytes_read ;
2008-01-19 12:09:00 +00:00
2009-06-26 15:08:04 +00:00
if ( pn - > byte_swapped )
2008-07-09 20:09:23 +00:00
block_total_length = BSWAP32 ( block_total_length ) ;
2008-01-13 21:10:09 +00:00
2009-06-26 15:08:04 +00:00
if ( ! ( block_total_length = = bh . block_total_length ) ) {
2011-12-13 09:53:50 +00:00
* err = WTAP_ERR_BAD_FILE ;
2011-02-04 02:08:47 +00:00
* err_info = g_strdup_printf ( " pcapng_read_block: total block lengths (first %u and second %u) don't match " ,
2008-07-09 20:09:23 +00:00
bh . block_total_length , block_total_length ) ;
2010-04-05 22:20:21 +00:00
return - 1 ;
2008-01-19 12:09:00 +00:00
}
return block_read ;
2008-01-13 21:10:09 +00:00
}
/* classic wtap: open capture file */
2011-02-04 02:08:47 +00:00
int
2008-01-13 21:10:09 +00:00
pcapng_open ( wtap * wth , int * err , gchar * * err_info )
{
int bytes_read ;
pcapng_t pn ;
wtapng_block_t wblock ;
2010-02-26 07:59:54 +00:00
pcapng_t * pcapng ;
2012-02-20 20:15:51 +00:00
wtapng_if_descr_t int_data ;
interface_data_t interface_data ;
pcapng_block_header_t bh ;
2008-01-13 21:10:09 +00:00
2012-02-20 20:15:51 +00:00
pn . shb_read = FALSE ;
pn . read_idbs = TRUE ; /* IDB expected after SHB */
2008-01-13 21:10:09 +00:00
/* we don't know the byte swapping of the file yet */
pn . byte_swapped = FALSE ;
2008-07-09 20:09:23 +00:00
pn . if_fcslen = - 1 ;
pn . version_major = - 1 ;
pn . version_minor = - 1 ;
2012-02-20 20:15:51 +00:00
pn . interface_data = g_array_new ( FALSE , FALSE , sizeof ( interface_data_t ) ) ;
2009-05-03 17:43:41 +00:00
pn . number_of_interfaces = 0 ;
2008-01-13 21:10:09 +00:00
2012-02-20 20:15:51 +00:00
2008-01-13 21:10:09 +00:00
/* we don't expect any packet blocks yet */
wblock . frame_buffer = NULL ;
wblock . pseudo_header = NULL ;
2009-06-27 17:33:23 +00:00
wblock . packet_header = NULL ;
wblock . file_encap = & wth - > file_encap ;
2008-01-13 21:10:09 +00:00
2009-05-03 17:43:41 +00:00
pcapng_debug0 ( " pcapng_open: opening file " ) ;
2008-01-13 21:10:09 +00:00
/* read first block */
2010-04-05 22:20:21 +00:00
bytes_read = pcapng_read_block ( wth - > fh , TRUE , & pn , & wblock , err , err_info ) ;
2008-01-13 21:10:09 +00:00
if ( bytes_read < = 0 ) {
2009-06-27 11:39:47 +00:00
pcapng_debug0 ( " pcapng_open: couldn't read first SHB " ) ;
2011-04-21 09:41:52 +00:00
* err = file_error ( wth - > fh , err_info ) ;
2008-01-13 21:10:09 +00:00
if ( * err ! = 0 )
return - 1 ;
return 0 ;
}
wth - > data_offset + = bytes_read ;
/* first block must be a "Section Header Block" */
2009-05-03 09:56:53 +00:00
if ( wblock . type ! = BLOCK_TYPE_SHB ) {
2009-04-27 09:28:28 +00:00
/*
* XXX - check for damage from transferring a file
* between Windows and UN * X as text rather than
* binary data ?
*/
2009-06-27 11:39:47 +00:00
pcapng_debug1 ( " pcapng_open: first block type %u not SHB " , wblock . type ) ;
2008-01-13 21:10:09 +00:00
return 0 ;
}
2012-02-20 20:15:51 +00:00
pn . shb_read = TRUE ;
2008-01-13 21:10:09 +00:00
2012-02-21 08:27:41 +00:00
/*
* At this point , we ' ve decided this is a pcap - NG file , not
* some other type of file , so we can ' t return 0 , as that
* means " this isn't a pcap-NG file, try some other file
* type " .
*/
2012-02-21 12:24:42 +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 ;
2012-02-15 19:44:16 +00:00
2009-06-27 12:14:18 +00:00
wth - > file_encap = WTAP_ENCAP_UNKNOWN ;
2009-05-03 09:56:53 +00:00
wth - > snapshot_length = 0 ;
2009-05-03 11:46:40 +00:00
wth - > tsprecision = WTAP_FILE_TSPREC_NSEC ;
2010-02-26 07:59:54 +00:00
pcapng = ( pcapng_t * ) g_malloc ( sizeof ( pcapng_t ) ) ;
wth - > priv = ( void * ) pcapng ;
* pcapng = pn ;
2012-02-20 20:15:51 +00:00
2009-05-03 10:38:41 +00:00
wth - > subtype_read = pcapng_read ;
wth - > subtype_seek_read = pcapng_seek_read ;
wth - > subtype_close = pcapng_close ;
2009-05-03 15:47:41 +00:00
wth - > file_type = WTAP_FILE_PCAPNG ;
2008-01-13 21:10:09 +00:00
2012-02-20 20:15:51 +00:00
/* Read IDBs */
wth - > interface_data = g_array_new ( FALSE , FALSE , sizeof ( wtapng_if_descr_t ) ) ;
wth - > number_of_interfaces = 0 ;
2012-03-03 16:17:20 +00:00
/* Loop over all IDB:s that appear before any packets */
2012-02-20 20:15:51 +00:00
while ( 1 ) {
bytes_read = pcapng_read_block ( wth - > fh , FALSE , & pn , & wblock , err , err_info ) ;
wth - > data_offset + = bytes_read ;
2012-02-22 03:03:34 +00:00
if ( bytes_read = = 0 ) {
pcapng_debug0 ( " No more IDBs available... " ) ;
break ;
}
2012-02-20 20:15:51 +00:00
if ( bytes_read < = 0 ) {
pcapng_debug0 ( " pcapng_open: couldn't read IDB " ) ;
* err = file_error ( wth - > fh , err_info ) ;
2012-02-21 08:27:41 +00:00
if ( * err = = 0 )
* err = WTAP_ERR_SHORT_READ ;
return - 1 ;
2012-02-20 20:15:51 +00:00
}
2012-02-21 12:24:42 +00:00
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 ;
2012-02-20 20:15:51 +00:00
/* Options */
2012-02-21 12:24:42 +00:00
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 ;
2012-02-20 20:15:51 +00:00
/* 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)*/
2012-02-21 12:24:42 +00:00
int_data . if_speed = wblock . data . if_descr . if_speed ;
int_data . if_tsresol = wblock . data . if_descr . if_tsresol ;
2012-02-20 20:15:51 +00:00
/* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2012-03-04 19:01:14 +00:00
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 ;
2012-02-21 12:24:42 +00:00
int_data . if_os = wblock . data . if_descr . if_os ;
int_data . if_fcslen = wblock . data . if_descr . if_fcslen ;
2012-02-20 20:15:51 +00:00
/* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
g_array_append_val ( wth - > interface_data , int_data ) ;
wth - > number_of_interfaces + + ;
interface_data . wtap_encap = wblock . data . if_descr . wtap_encap ;
interface_data . time_units_per_second = 1000000 ; /* default */
g_array_append_val ( pcapng - > interface_data , interface_data ) ;
pcapng - > number_of_interfaces + + ;
pcapng_debug2 ( " pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i " , wth - > number_of_interfaces , int_data . wtap_encap ) ;
/* peek at next block */
/* Try to read the (next) block header */
errno = WTAP_ERR_CANT_READ ;
bytes_read = file_read ( & bh , sizeof bh , wth - > fh ) ;
2012-02-21 12:24:42 +00:00
if ( bytes_read = = 0 ) {
pcapng_debug0 ( " No more IDBs available... " ) ;
break ;
}
2012-02-20 20:15:51 +00:00
if ( bytes_read ! = sizeof bh ) {
* err = file_error ( wth - > fh , err_info ) ;
pcapng_debug3 ( " pcapng_open: Check for more IDB:s, file_read() returned %d instead of %u, err = %d. " , bytes_read , ( unsigned int ) sizeof bh , * err ) ;
2012-02-21 08:27:41 +00:00
if ( * err = = 0 )
* err = WTAP_ERR_SHORT_READ ;
return - 1 ;
2012-02-20 20:15:51 +00:00
}
2012-02-21 12:24:42 +00:00
/* go back to where we were */
2012-02-20 20:15:51 +00:00
file_seek ( wth - > fh , wth - > data_offset , SEEK_SET , err ) ;
if ( pn . byte_swapped ) {
bh . block_type = BSWAP32 ( bh . block_type ) ;
}
pcapng_debug1 ( " pcapng_open: Check for more IDB:s block_type 0x%x " , bh . block_type ) ;
if ( bh . block_type ! = BLOCK_TYPE_IDB ) {
2012-02-21 08:27:41 +00:00
break ; /* No more IDB:s */
2012-02-20 20:15:51 +00:00
}
}
pcapng - > read_idbs = FALSE ;
2008-01-13 21:10:09 +00:00
return 1 ;
}
/* classic wtap: read packet */
2011-02-04 02:08:47 +00:00
static gboolean
2008-07-09 20:09:23 +00:00
pcapng_read ( wtap * wth , int * err , gchar * * err_info , gint64 * data_offset )
2008-01-13 21:10:09 +00:00
{
2010-02-26 07:59:54 +00:00
pcapng_t * pcapng = ( pcapng_t * ) wth - > priv ;
2008-01-13 21:10:09 +00:00
int bytes_read ;
wtapng_block_t wblock ;
2009-05-02 17:10:01 +00:00
pcapng_debug1 ( " pcapng_read: wth->data_offset is initially % " G_GINT64_MODIFIER " u " , wth - > data_offset ) ;
2008-01-13 21:10:09 +00:00
* data_offset = wth - > data_offset ;
2009-05-02 17:10:01 +00:00
pcapng_debug1 ( " pcapng_read: *data_offset is initially set to % " G_GINT64_MODIFIER " u " , * data_offset ) ;
2008-01-13 21:10:09 +00:00
2009-06-26 15:08:04 +00:00
/* XXX - This should be done in the packet block reading function and
* should make use of the caplen of the packet .
*/
if ( wth - > snapshot_length > 0 ) {
buffer_assure_space ( wth - > frame_buffer , wth - > snapshot_length ) ;
} else {
buffer_assure_space ( wth - > frame_buffer , WTAP_MAX_PACKET_SIZE ) ;
}
2008-01-13 21:10:09 +00:00
2009-06-27 17:33:23 +00:00
wblock . frame_buffer = buffer_start_ptr ( wth - > frame_buffer ) ;
2008-01-13 21:10:09 +00:00
wblock . pseudo_header = & wth - > pseudo_header ;
2009-06-27 17:33:23 +00:00
wblock . packet_header = & wth - > phdr ;
wblock . file_encap = & wth - > file_encap ;
2008-01-13 21:10:09 +00:00
2011-03-24 22:47:57 +00:00
pcapng - > add_new_ipv4 = wth - > add_new_ipv4 ;
pcapng - > add_new_ipv6 = wth - > add_new_ipv6 ;
2008-01-13 21:10:09 +00:00
/* read next block */
2009-05-03 11:46:40 +00:00
while ( 1 ) {
2010-04-05 22:20:21 +00:00
bytes_read = pcapng_read_block ( wth - > fh , FALSE , pcapng , & wblock , err , err_info ) ;
2008-02-16 11:52:56 +00:00
if ( bytes_read < = 0 ) {
2011-04-19 13:28:17 +00:00
wth - > data_offset = * data_offset ;
pcapng_debug1 ( " pcapng_read: wth->data_offset is finally % " G_GINT64_MODIFIER " u " , wth - > data_offset ) ;
2009-06-26 15:08:04 +00:00
pcapng_debug0 ( " pcapng_read: couldn't read packet block " ) ;
return FALSE ;
2008-02-16 11:52:56 +00:00
}
2008-01-13 21:10:09 +00:00
2008-02-16 11:52:56 +00:00
/* block must be a "Packet Block" or an "Enhanced Packet Block" -> otherwise continue */
2009-05-03 11:46:40 +00:00
if ( wblock . type = = BLOCK_TYPE_PB | | wblock . type = = BLOCK_TYPE_EPB ) {
2008-07-09 20:09:23 +00:00
break ;
2008-02-16 11:52:56 +00:00
}
2008-01-19 12:09:00 +00:00
2008-02-16 11:52:56 +00:00
/* XXX - improve handling of "unknown" blocks */
2008-01-26 14:08:51 +00:00
pcapng_debug1 ( " pcapng_read: block type 0x%x not PB/EPB " , wblock . type ) ;
2009-05-02 17:10:01 +00:00
* data_offset + = bytes_read ;
pcapng_debug1 ( " pcapng_read: *data_offset is updated to % " G_GINT64_MODIFIER " u " , * data_offset ) ;
2008-02-16 11:52:56 +00:00
}
2008-01-13 21:10:09 +00:00
2010-02-26 07:59:54 +00:00
if ( wblock . data . packet . interface_id < pcapng - > number_of_interfaces ) {
2009-05-03 15:47:41 +00:00
} else {
wth - > phdr . pkt_encap = WTAP_ENCAP_UNKNOWN ;
2011-12-13 09:53:50 +00:00
* err = WTAP_ERR_BAD_FILE ;
2011-02-04 02:24:33 +00:00
* err_info = g_strdup_printf ( " pcapng: interface index %u is not less than interface count %u. " ,
wblock . data . packet . interface_id , pcapng - > number_of_interfaces ) ;
2011-04-19 13:28:17 +00:00
wth - > data_offset = * data_offset + bytes_read ;
pcapng_debug1 ( " pcapng_read: wth->data_offset is finally % " G_GINT64_MODIFIER " u " , wth - > data_offset ) ;
2009-06-26 15:08:04 +00:00
return FALSE ;
2009-05-03 15:47:41 +00:00
}
2008-01-13 21:10:09 +00:00
2008-01-26 14:08:51 +00:00
/*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2009-05-02 17:10:01 +00:00
wth - > data_offset = * data_offset + bytes_read ;
pcapng_debug1 ( " pcapng_read: wth->data_offset is finally % " G_GINT64_MODIFIER " u " , wth - > data_offset ) ;
2008-01-19 12:09:00 +00:00
2009-05-02 17:10:01 +00:00
return TRUE ;
2008-01-13 21:10:09 +00:00
}
/* classic wtap: seek to file position and read packet */
static gboolean
pcapng_seek_read ( wtap * wth , gint64 seek_off ,
2011-09-01 09:43:10 +00:00
union wtap_pseudo_header * pseudo_header , guint8 * pd , int length _U_ ,
2008-01-13 21:10:09 +00:00
int * err , gchar * * err_info )
{
2010-02-26 07:59:54 +00:00
pcapng_t * pcapng = ( pcapng_t * ) wth - > priv ;
2008-01-13 21:10:09 +00:00
guint64 bytes_read64 ;
int bytes_read ;
wtapng_block_t wblock ;
/* seek to the right file position */
bytes_read64 = file_seek ( wth - > random_fh , seek_off , SEEK_SET , err ) ;
if ( bytes_read64 < = 0 ) {
return FALSE ; /* Seek error */
}
2009-05-02 17:10:01 +00:00
pcapng_debug1 ( " pcapng_seek_read: reading at offset % " G_GINT64_MODIFIER " u " , seek_off ) ;
2008-01-13 21:10:09 +00:00
wblock . frame_buffer = pd ;
wblock . pseudo_header = pseudo_header ;
2009-06-27 17:33:23 +00:00
wblock . packet_header = & wth - > phdr ;
wblock . file_encap = & wth - > file_encap ;
2008-01-13 21:10:09 +00:00
/* read the block */
2010-04-05 22:20:21 +00:00
bytes_read = pcapng_read_block ( wth - > random_fh , FALSE , pcapng , & wblock , err , err_info ) ;
2008-01-13 21:10:09 +00:00
if ( bytes_read < = 0 ) {
2011-04-21 09:41:52 +00:00
* err = file_error ( wth - > random_fh , err_info ) ;
2009-06-28 11:09:24 +00:00
pcapng_debug3 ( " pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d). " ,
* err , errno , bytes_read ) ;
2008-01-13 21:10:09 +00:00
return FALSE ;
}
/* block must be a "Packet Block" or an "Enhanced Packet Block" */
2009-05-03 09:56:53 +00:00
if ( wblock . type ! = BLOCK_TYPE_PB & & wblock . type ! = BLOCK_TYPE_EPB ) {
2008-01-26 14:08:51 +00:00
pcapng_debug1 ( " pcapng_seek_read: block type %u not PB/EPB " , wblock . type ) ;
2008-01-13 21:10:09 +00:00
return FALSE ;
}
return TRUE ;
}
/* classic wtap: close capture file */
static void
pcapng_close ( wtap * wth )
{
2010-02-26 07:59:54 +00:00
pcapng_t * pcapng = ( pcapng_t * ) wth - > priv ;
2009-05-03 17:43:41 +00:00
pcapng_debug0 ( " pcapng_close: closing file " ) ;
2010-02-26 07:59:54 +00:00
if ( pcapng - > interface_data ! = NULL ) {
g_array_free ( pcapng - > interface_data , TRUE ) ;
2009-05-03 17:43:41 +00:00
}
2008-01-13 21:10:09 +00:00
}
2010-02-26 07:59:54 +00:00
typedef struct {
GArray * interface_data ;
guint number_of_interfaces ;
2011-03-24 22:47:57 +00:00
struct addrinfo * addrinfo_list_last ;
2010-02-26 07:59:54 +00:00
} pcapng_dump_t ;
2008-01-13 21:10:09 +00:00
static gboolean
2012-03-02 09:38:43 +00:00
pcapng_write_section_header_block ( wtap_dumper * wdh , int * err )
2008-01-13 21:10:09 +00:00
{
pcapng_block_header_t bh ;
pcapng_section_header_block_t shb ;
2012-02-15 19:44:16 +00:00
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 ;
2012-02-21 16:32:25 +00:00
if ( wdh - > shb_hdr ) {
2012-02-15 19:44:16 +00:00
pcapng_debug0 ( " pcapng_write_section_header_block: Have shb_hdr " ) ;
/* Check if we should write comment option */
2012-02-21 16:32:25 +00:00
if ( wdh - > shb_hdr - > opt_comment ) {
2012-02-15 19:44:16 +00:00
have_options = TRUE ;
comment_len = ( guint32 ) strlen ( wdh - > shb_hdr - > opt_comment ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( comment_len % 4 ) ) {
2012-02-15 19:44:16 +00:00
comment_pad_len = 4 - ( comment_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-15 19:44:16 +00:00
comment_pad_len = 0 ;
}
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
/* Check if we should write shb_hardware option */
2012-02-21 16:32:25 +00:00
if ( wdh - > shb_hdr - > shb_hardware ) {
2012-02-15 19:44:16 +00:00
have_options = TRUE ;
shb_hardware_len = ( guint32 ) strlen ( wdh - > shb_hdr - > shb_hardware ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( shb_hardware_len % 4 ) ) {
2012-02-15 19:44:16 +00:00
shb_hardware_pad_len = 4 - ( shb_hardware_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-15 19:44:16 +00:00
shb_hardware_pad_len = 0 ;
}
options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
}
2008-01-13 21:10:09 +00:00
2012-02-15 19:44:16 +00:00
/* Check if we should write shb_os option */
2012-02-21 16:32:25 +00:00
if ( wdh - > shb_hdr - > shb_os ) {
2012-02-15 19:44:16 +00:00
have_options = TRUE ;
shb_os_len = ( guint32 ) strlen ( wdh - > shb_hdr - > shb_os ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( shb_os_len % 4 ) ) {
2012-02-15 19:44:16 +00:00
shb_os_pad_len = 4 - ( shb_os_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-15 19:44:16 +00:00
shb_os_pad_len = 0 ;
}
options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
}
/* Check if we should write shb_user_appl option */
2012-02-21 16:32:25 +00:00
if ( wdh - > shb_hdr - > shb_user_appl ) {
2012-02-15 19:44:16 +00:00
have_options = TRUE ;
shb_user_appl_len = ( guint32 ) strlen ( wdh - > shb_hdr - > shb_user_appl ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( shb_user_appl_len % 4 ) ) {
2012-02-15 19:44:16 +00:00
shb_user_appl_pad_len = 4 - ( shb_user_appl_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-15 19:44:16 +00:00
shb_user_appl_pad_len = 0 ;
}
options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
}
2012-02-21 16:32:25 +00:00
if ( have_options ) {
2012-03-03 16:17:20 +00:00
/* End-of-options tag */
2012-02-15 19:44:16 +00:00
options_total_length + = 4 ;
}
}
2008-01-13 21:10:09 +00:00
/* write block header */
2012-03-02 09:38:43 +00:00
bh . block_type = BLOCK_TYPE_SHB ;
2012-02-15 19:44:16 +00:00
bh . block_total_length = 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 ) ;
2008-01-13 21:10:09 +00:00
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
/* 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 ;
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & shb , sizeof shb , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof shb ;
2012-02-15 19:44:16 +00:00
/* XXX - write (optional) block options
* opt_comment 1
* shb_hardware 2
* shb_os 3
* shb_user_appl 4
*/
2012-02-21 16:32:25 +00:00
if ( comment_len ) {
2012-02-15 19:44:16 +00:00
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 */
2012-02-20 20:15:51 +00:00
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 ) ;
2012-02-15 19:44:16 +00:00
if ( ! wtap_dump_file_write ( wdh , wdh - > shb_hdr - > opt_comment , comment_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
/* 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-02-21 16:32:25 +00:00
if ( shb_hardware_len ) {
2012-02-15 19:44:16 +00:00
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 ;
/* Write the string */
2012-02-20 20:15:51 +00:00
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 ) ;
2012-02-15 19:44:16 +00:00
if ( ! wtap_dump_file_write ( wdh , wdh - > shb_hdr - > shb_hardware , shb_hardware_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = shb_hardware_len ;
/* 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-02-21 16:32:25 +00:00
if ( shb_os_len ) {
2012-02-15 19:44:16 +00:00
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 ;
/* Write the string */
2012-02-20 20:15:51 +00:00
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 ) ;
2012-02-15 19:44:16 +00:00
if ( ! wtap_dump_file_write ( wdh , wdh - > shb_hdr - > shb_os , shb_os_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = shb_os_len ;
/* 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-02-21 16:32:25 +00:00
if ( shb_user_appl_len ) {
2012-02-15 19:44:16 +00:00
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 */
2012-02-20 20:15:51 +00:00
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 ) ;
2012-02-15 19:44:16 +00:00
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 ;
/* 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 ) )
return FALSE ;
wdh - > bytes_dumped + = shb_user_appl_pad_len ;
}
}
/* Write end of options if we have otions */
2012-02-21 16:32:25 +00:00
if ( have_options ) {
option_hdr . type = OPT_EOFOPT ;
option_hdr . value_length = 0 ;
2012-02-15 19:44:16 +00:00
if ( ! wtap_dump_file_write ( wdh , & zero_pad , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
}
2008-01-13 21:10:09 +00:00
/* write block footer */
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh . block_total_length ,
sizeof bh . block_total_length , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof bh . block_total_length ;
return TRUE ;
}
2012-02-20 20:15:51 +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
2012-03-02 09:30:10 +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
{
pcapng_block_header_t bh ;
pcapng_interface_description_block_t idb ;
2012-02-20 20:15:51 +00:00
const guint32 zero_pad = 0 ;
gboolean have_options = FALSE ;
struct option option_hdr ; /* guint16 type, guint16 value_length; */
guint32 options_total_length = 0 ;
2012-03-04 19:01:14 +00:00
guint32 comment_len = 0 , if_name_len = 0 , if_description_len = 0 , if_os_len = 0 , if_filter_str_len = 0 ;
2012-03-04 20:49:17 +00:00
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 ;
2008-01-13 21:10:09 +00:00
2009-06-27 12:41:06 +00:00
pcapng_debug3 ( " pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d " ,
2012-03-02 09:30:10 +00:00
int_data - > link_type ,
wtap_encap_string ( wtap_pcap_encap_to_wtap_encap ( int_data - > link_type ) ) ,
int_data - > snap_len ) ;
2009-06-27 12:41:06 +00:00
2012-03-02 09:30:10 +00:00
if ( int_data - > link_type = = ( guint16 ) - 1 ) {
2009-06-27 15:20:44 +00:00
* err = WTAP_ERR_UNSUPPORTED_ENCAP ;
return FALSE ;
}
2012-02-20 20:15:51 +00:00
/* Calculate options length */
2012-03-02 09:30:10 +00:00
if ( int_data - > opt_comment ) {
2012-02-20 20:15:51 +00:00
have_options = TRUE ;
2012-03-02 09:30:10 +00:00
comment_len = ( guint32 ) strlen ( int_data - > opt_comment ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( comment_len % 4 ) ) {
2012-02-20 20:15:51 +00:00
comment_pad_len = 4 - ( comment_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-20 20:15:51 +00:00
comment_pad_len = 0 ;
}
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
/*
* if_name 2 A UTF - 8 string containing the name of the device used to capture data .
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_name ) {
2012-02-20 20:15:51 +00:00
have_options = TRUE ;
2012-03-02 09:30:10 +00:00
if_name_len = ( guint32 ) strlen ( int_data - > if_name ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( if_name_len % 4 ) ) {
2012-02-20 20:15:51 +00:00
if_name_pad_len = 4 - ( if_name_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-20 20:15:51 +00:00
if_name_pad_len = 0 ;
}
options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
}
/*
* if_description 3 A UTF - 8 string containing the description of the device used to capture data .
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_description ) {
2012-02-20 20:15:51 +00:00
have_options = TRUE ;
2012-03-02 09:30:10 +00:00
if_description_len = ( guint32 ) strlen ( int_data - > if_description ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( if_description_len % 4 ) ) {
2012-02-20 20:15:51 +00:00
if_description_pad_len = 4 - ( if_description_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-20 20:15:51 +00:00
if_description_pad_len = 0 ;
}
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
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_speed ! = 0 ) {
2012-02-20 20:15:51 +00:00
have_options = TRUE ;
options_total_length = options_total_length + 8 + 4 ;
}
/*
* if_tsresol 9 Resolution of timestamps .
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_tsresol ! = 0 ) {
2012-02-20 20:15:51 +00:00
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
*/
/*
2012-03-02 09:30:10 +00:00
* 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 ) .
2012-02-20 20:15:51 +00:00
*/
2012-03-04 19:01:14 +00:00
if ( int_data - > if_filter_str ) {
have_options = TRUE ;
2012-03-04 19:31:33 +00:00
if_filter_str_len = ( guint32 ) ( strlen ( int_data - > if_filter_str ) + 1 ) & 0xffff ;
2012-03-04 19:01:14 +00:00
if ( ( if_filter_str_len % 4 ) ) {
if_filter_str_pad_len = 4 - ( if_filter_str_len % 4 ) ;
} else {
if_filter_str_pad_len = 0 ;
}
options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2012-02-20 20:15:51 +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 .
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_os ) {
2012-02-20 20:15:51 +00:00
have_options = TRUE ;
2012-03-02 09:30:10 +00:00
if_os_len = ( guint32 ) strlen ( int_data - > if_os ) & 0xffff ;
2012-02-21 16:32:25 +00:00
if ( ( if_os_len % 4 ) ) {
2012-02-20 20:15:51 +00:00
if_os_pad_len = 4 - ( if_os_len % 4 ) ;
2012-02-21 16:32:25 +00:00
} else {
2012-02-20 20:15:51 +00:00
if_os_pad_len = 0 ;
}
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 .
2012-03-02 09:30:10 +00:00
* - 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 .
2012-02-20 20:15:51 +00:00
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_fcslen ! = 0 ) {
2012-02-20 20:15:51 +00:00
}
/* 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 .
*/
2012-02-21 16:32:25 +00:00
if ( have_options ) {
2012-03-03 16:17:20 +00:00
/* End-of-options tag */
2012-02-20 20:15:51 +00:00
options_total_length + = 4 ;
}
2008-01-13 21:10:09 +00:00
/* write block header */
2012-03-02 09:30:10 +00:00
bh . block_type = BLOCK_TYPE_IDB ;
2012-02-20 20:15:51 +00:00
bh . block_total_length = sizeof ( bh ) + sizeof ( idb ) + options_total_length + 4 ;
2008-01-13 21:10:09 +00:00
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
/* write block fixed content */
2012-03-02 09:30:10 +00:00
idb . linktype = int_data - > link_type ;
2008-01-13 21:10:09 +00:00
idb . reserved = 0 ;
2012-03-02 09:30:10 +00:00
idb . snaplen = int_data - > snap_len ;
2008-01-13 21:10:09 +00:00
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & idb , sizeof idb , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof idb ;
/* XXX - write (optional) block options */
2012-03-04 19:01:14 +00:00
if ( comment_len ! = 0 ) {
2012-02-20 20:15:51 +00:00
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 */
2012-03-02 09:30:10 +00:00
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 ) )
2012-02-20 20:15:51 +00:00
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
/* 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-02-21 20:37:22 +00:00
* if_name 2 A UTF - 8 string containing the name of the device used to capture data .
2012-02-20 20:15:51 +00:00
*/
2012-03-04 19:01:14 +00:00
if ( if_name_len ! = 0 ) {
2012-02-21 20:37:22 +00:00
option_hdr . type = IDB_OPT_IF_NAME ;
2012-02-20 20:15:51 +00:00
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 */
2012-03-02 09:30:10 +00:00
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 ) )
2012-02-20 20:15:51 +00:00
return FALSE ;
2012-02-21 20:37:22 +00:00
wdh - > bytes_dumped + = if_name_len ;
2012-02-20 20:15:51 +00:00
/* 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 ;
}
}
/*
* if_description 3 A UTF - 8 string containing the description of the device used to capture data .
*/
2012-03-04 19:01:14 +00:00
if ( if_description_len ! = 0 ) {
2012-02-20 20:15:51 +00:00
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 */
2012-03-02 09:30:10 +00:00
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 ) )
2012-02-20 20:15:51 +00:00
return FALSE ;
wdh - > bytes_dumped + = comment_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 ;
}
}
/* 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
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_speed ! = 0 ) {
2012-02-21 16:32:25 +00:00
printf ( " HJKHJHK \n " ) ;
2012-02-20 20:15:51 +00:00
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 */
2012-03-02 09:30:10 +00:00
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 ) )
2012-02-20 20:15:51 +00:00
return FALSE ;
wdh - > bytes_dumped + = 8 ;
}
/*
* if_tsresol 9 Resolution of timestamps .
2012-03-02 09:30:10 +00:00
* 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
2012-02-20 20:15:51 +00:00
*/
2012-03-02 09:30:10 +00:00
if ( int_data - > if_tsresol ! = 0 ) {
2012-02-20 20:15:51 +00:00
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 comments string */
2012-03-02 09:30:10 +00:00
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 ) )
2012-02-20 20:15:51 +00:00
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 .
*/
2012-03-04 19:01:14 +00:00
/* Libpcap string variant */
if ( if_filter_str_len ! = 0 ) {
option_hdr . type = IDB_OPT_IF_FILTER ;
option_hdr . value_length = if_filter_str_len ;
2012-03-05 09:32:21 +00:00
/* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2012-03-04 19:01:14 +00:00
if ( ! wtap_dump_file_write ( wdh , & option_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the zero indicaling 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_len ) ;
2012-03-05 09:32:21 +00:00
/* 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 ) )
2012-03-04 19:01:14 +00:00
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
/* 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-02-20 20:15:51 +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 .
*/
2012-03-04 19:01:14 +00:00
if ( if_os_len ! = 0 ) {
2012-02-20 20:15:51 +00:00
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 */
2012-03-02 09:30:10 +00:00
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 ) )
2012-02-20 20:15:51 +00:00
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
/* 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-02-21 16:32:25 +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-02-20 20:15:51 +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 .
*/
2008-01-13 21:10:09 +00:00
/* write block footer */
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh . block_total_length ,
sizeof bh . block_total_length , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof bh . block_total_length ;
return TRUE ;
}
2012-03-02 09:03:26 +00:00
#if 0
2012-02-22 14:41:02 +00:00
static gboolean
pcapng_write_interface_statistics_block ( wtap_dumper * wdh , wtapng_block_t * wblock , int * err )
{
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 ( wblock - > data . if_descr . opt_comment ) {
have_options = TRUE ;
comment_len = ( guint32 ) strlen ( wblock - > data . if_descr . 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 */ ;
}
/* XXX */
/*guint32 isb_starttime_high;*/
/*guint32 isb_starttime_low;*/
/*guint32 isb_endtime_high;*/
/*guint32 isb_endtime_low;*/
/*guint64 isb_ifrecv;*/
/*guint64 isb_ifdrop;*/
/*guint64 isb_filteraccept;*/
/*guint64 isb_osdrop;*/
/*guint64 isb_usrdeliv;*/
/* write block header */
if ( have_options ) {
/* End-of-optios tag */
options_total_length + = 4 ;
}
/* write block header */
bh . block_type = wblock - > type ;
bh . block_total_length = sizeof ( bh ) + sizeof ( isb ) + options_total_length + 4 ;
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
/* write block fixed content */
isb . interface_id = wblock - > data . if_stats . interface_id ;
isb . timestamp_high = wblock - > data . if_stats . ts_high ;
isb . timestamp_low = wblock - > data . if_stats . ts_low ;
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_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u " , wblock - > data . if_descr . opt_comment , comment_len , comment_pad_len ) ;
if ( ! wtap_dump_file_write ( wdh , wblock - > data . if_descr . opt_comment , comment_len , err ) )
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
/* 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 ;
}
}
/* XXX */
/*guint32 isb_starttime */
/*guint32 isb_endtime */
/*guint64 isb_ifrecv;*/
/*guint64 isb_ifdrop;*/
/*guint64 isb_filteraccept;*/
/*guint64 isb_osdrop;*/
/*guint64 isb_usrdeliv;*/
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 ;
}
/* 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 ;
}
2012-03-02 09:03:26 +00:00
# endif
2008-01-13 21:10:09 +00:00
static gboolean
2012-03-02 09:03:26 +00:00
pcapng_write_enhanced_packet_block ( wtap_dumper * wdh ,
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
{
pcapng_block_header_t bh ;
pcapng_enhanced_packet_block_t epb ;
2012-03-02 09:03:26 +00:00
guint64 ts ;
2009-06-27 12:41:06 +00:00
const guint32 zero_pad = 0 ;
guint32 pad_len ;
guint32 phdr_len ;
2012-02-11 12:34:39 +00:00
gboolean have_options = FALSE ;
guint32 options_total_length = 0 ;
guint32 options_hdr = 0 ;
guint32 comment_len = 0 , comment_pad_len = 0 ;
2011-02-04 02:08:47 +00:00
2012-03-02 09:03:26 +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 ) ;
2009-06-27 12:41:06 +00:00
} else {
pad_len = 0 ;
2008-07-09 20:09:23 +00:00
}
2008-01-13 21:10:09 +00:00
2012-02-11 12:34:39 +00:00
/* Check if we should write comment option */
2012-03-02 09:03:26 +00:00
if ( phdr - > opt_comment ) {
2012-02-11 12:34:39 +00:00
have_options = TRUE ;
2012-03-02 09:03:26 +00:00
comment_len = ( guint32 ) strlen ( phdr - > opt_comment ) & 0xffff ;
2012-02-11 12:34:39 +00:00
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 */ ;
}
if ( have_options ) {
/* End-of optios tag */
options_total_length + = 4 ;
}
2008-01-13 21:10:09 +00:00
/* write (enhanced) packet block header */
2012-03-02 09:03:26 +00:00
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 ;
2008-01-13 21:10:09 +00:00
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh , sizeof bh , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof bh ;
/* write block fixed content */
2012-03-03 00:13:25 +00:00
if ( phdr - > presence_flags & WTAP_HAS_INTERFACE_ID )
epb . interface_id = phdr - > interface_id ;
else {
/*
* XXX - we should support writing WTAP_ENCAP_PER_PACKET
* data to pcap - NG files even if we * don ' t * have interface
* IDs .
*/
epb . interface_id = 0 ;
}
2012-03-02 09:03:26 +00:00
/* Split the 64-bit timestamp into two 32-bit pieces */
ts = ( ( ( guint64 ) phdr - > ts . secs ) * 1000000 ) + ( phdr - > ts . nsecs / 1000 ) ;
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 ;
2008-01-13 21:10:09 +00:00
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & epb , sizeof epb , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof epb ;
2009-06-27 12:41:06 +00:00
/* write pseudo header */
2012-03-02 09:03:26 +00:00
if ( ! pcap_write_phdr ( wdh , phdr - > pkt_encap , pseudo_header , err ) ) {
2009-06-27 12:41:06 +00:00
return FALSE ;
}
wdh - > bytes_dumped + = phdr_len ;
2008-01-13 21:10:09 +00:00
/* write packet data */
2012-03-02 09:03:26 +00:00
if ( ! wtap_dump_file_write ( wdh , pd , phdr - > caplen , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
2012-03-02 09:03:26 +00:00
wdh - > bytes_dumped + = phdr - > caplen ;
2008-01-13 21:10:09 +00:00
/* write padding (if any) */
2009-06-27 12:41:06 +00:00
if ( pad_len ! = 0 ) {
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & zero_pad , pad_len , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
2009-06-27 12:41:06 +00:00
wdh - > bytes_dumped + = pad_len ;
2008-01-13 21:10:09 +00:00
}
/* XXX - write (optional) block options */
2012-02-11 12:34:39 +00:00
/* 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 .
*/
2012-03-02 09:03:26 +00:00
if ( phdr - > opt_comment ) {
2012-02-11 12:34:39 +00:00
options_hdr = comment_len ;
options_hdr = options_hdr < < 16 ;
/* Option 1 */
options_hdr + = 1 ;
if ( ! wtap_dump_file_write ( wdh , & options_hdr , 4 , err ) )
return FALSE ;
wdh - > bytes_dumped + = 4 ;
/* Write the comments string */
2012-03-02 09:30:10 +00:00
pcapng_debug3 ( " pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u " , phdr - > opt_comment , comment_len , comment_pad_len ) ;
2012-03-02 09:03:26 +00:00
if ( ! wtap_dump_file_write ( wdh , phdr - > opt_comment , comment_len , err ) )
2012-02-11 12:34:39 +00:00
return FALSE ;
wdh - > bytes_dumped + = comment_len ;
/* 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-02 09:30:10 +00:00
pcapng_debug2 ( " pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u " ,
2012-02-11 12:34:39 +00:00
comment_len ,
comment_pad_len ) ;
}
/* 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 ;
}
2008-01-13 21:10:09 +00:00
/* write block footer */
2010-06-06 19:14:32 +00:00
if ( ! wtap_dump_file_write ( wdh , & bh . block_total_length ,
sizeof bh . block_total_length , err ) )
2008-01-13 21:10:09 +00:00
return FALSE ;
wdh - > bytes_dumped + = sizeof bh . block_total_length ;
return TRUE ;
}
2011-03-24 22:47:57 +00:00
/* Arbitrary. */
# define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
static gboolean
pcapng_write_name_resolution_block ( wtap_dumper * wdh , pcapng_dump_t * pcapng , int * err )
{
pcapng_block_header_t bh ;
pcapng_name_resolution_block_t nrb ;
struct addrinfo * ai ;
struct sockaddr_in * sa4 ;
struct sockaddr_in6 * sa6 ;
2011-09-01 09:43:10 +00:00
guint8 * rec_data ;
2011-03-24 22:47:57 +00:00
gint rec_off , namelen , tot_rec_len ;
if ( ! pcapng - > addrinfo_list_last | | ! pcapng - > addrinfo_list_last - > ai_next ) {
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 = g_malloc ( NRES_REC_MAX_SIZE ) ;
2011-03-24 23:33:38 +00:00
2011-03-24 22:47:57 +00:00
for ( ; pcapng - > addrinfo_list_last & & pcapng - > addrinfo_list_last - > ai_next ; pcapng - > addrinfo_list_last = pcapng - > addrinfo_list_last - > ai_next ) {
ai = pcapng - > addrinfo_list_last - > ai_next ; /* Skips over the first (dummy) entry */
2011-03-25 06:42:59 +00:00
namelen = ( gint ) strlen ( ai - > ai_canonname ) + 1 ;
2011-03-24 22:47:57 +00:00
if ( ai - > ai_family = = AF_INET ) {
nrb . record_type = NRES_IP4RECORD ;
nrb . record_len = 4 + namelen ;
tot_rec_len = 4 + nrb . record_len + PADDING4 ( nrb . record_len ) ;
bh . block_total_length + = tot_rec_len ;
if ( rec_off + tot_rec_len > NRES_REC_MAX_SIZE )
break ;
2011-04-22 03:11:14 +00:00
/*
* The joys of BSD sockaddrs . In practice , this
* cast is alignment - safe .
*/
sa4 = ( struct sockaddr_in * ) ( void * ) ai - > ai_addr ;
2011-03-24 22:47:57 +00:00
memcpy ( rec_data + rec_off , & nrb , sizeof ( nrb ) ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , & ( sa4 - > sin_addr . s_addr ) , 4 ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , ai - > ai_canonname , namelen ) ;
rec_off + = namelen ;
memset ( rec_data + rec_off , 0 , PADDING4 ( namelen ) ) ;
rec_off + = PADDING4 ( namelen ) ;
pcapng_debug1 ( " NRB: added IPv4 record for %s " , ai - > ai_canonname ) ;
} else if ( ai - > ai_family = = AF_INET6 ) {
nrb . record_type = NRES_IP6RECORD ;
nrb . record_len = 16 + namelen ;
tot_rec_len = 4 + nrb . record_len + PADDING4 ( nrb . record_len ) ;
bh . block_total_length + = tot_rec_len ;
if ( rec_off + tot_rec_len > NRES_REC_MAX_SIZE )
break ;
2011-04-22 03:11:14 +00:00
/*
* The joys of BSD sockaddrs . In practice , this
* cast is alignment - safe .
*/
sa6 = ( struct sockaddr_in6 * ) ( void * ) ai - > ai_addr ;
2011-03-24 22:47:57 +00:00
memcpy ( rec_data + rec_off , & nrb , sizeof ( nrb ) ) ;
rec_off + = 4 ;
memcpy ( rec_data + rec_off , sa6 - > sin6_addr . s6_addr , 16 ) ;
rec_off + = 16 ;
memcpy ( rec_data + rec_off , ai - > ai_canonname , namelen ) ;
rec_off + = namelen ;
memset ( rec_data + rec_off , 0 , PADDING4 ( namelen ) ) ;
rec_off + = PADDING4 ( namelen ) ;
pcapng_debug1 ( " NRB: added IPv6 record for %s " , ai - > ai_canonname ) ;
}
}
/* 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 ) ) ;
2012-03-01 13:31:40 +00:00
rec_off + = 4 ;
pcapng_debug2 ( " pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u " , bh . block_total_length , rec_off ) ;
2011-03-24 22:47:57 +00:00
if ( ! wtap_dump_file_write ( wdh , rec_data , bh . block_total_length , err ) ) {
g_free ( rec_data ) ;
return FALSE ;
}
g_free ( rec_data ) ;
wdh - > bytes_dumped + = bh . block_total_length ;
return TRUE ;
}
2012-02-20 20:15:51 +00:00
#if 0
2009-06-27 15:20:44 +00:00
static guint32
pcapng_lookup_interface_id_by_encap ( int wtap_encap , wtap_dumper * wdh )
{
gint i ;
interface_data_t int_data ;
2010-02-26 07:59:54 +00:00
pcapng_dump_t * pcapng = ( pcapng_dump_t * ) wdh - > priv ;
for ( i = 0 ; i < ( gint ) pcapng - > number_of_interfaces ; i + + ) {
int_data = g_array_index ( pcapng - > interface_data , interface_data_t , i ) ;
2009-06-27 15:20:44 +00:00
if ( wtap_encap = = int_data . wtap_encap ) {
return ( guint32 ) i ;
}
}
return G_MAXUINT32 ;
}
2012-02-20 20:15:51 +00:00
# endif
2009-06-27 15:20:44 +00:00
2008-01-13 21:10:09 +00:00
static gboolean pcapng_dump ( wtap_dumper * wdh ,
const struct wtap_pkthdr * phdr ,
2009-06-26 15:08:04 +00:00
const union wtap_pseudo_header * pseudo_header ,
2011-09-01 09:43:10 +00:00
const guint8 * pd , int * err )
2008-01-13 21:10:09 +00:00
{
2012-02-20 20:15:51 +00:00
/*interface_data_t int_data;*/
2010-02-26 07:59:54 +00:00
pcapng_dump_t * pcapng = ( pcapng_dump_t * ) wdh - > priv ;
2012-02-20 20:15:51 +00:00
/*int pcap_encap;*/
2008-01-13 21:10:09 +00:00
2009-06-27 12:41:06 +00:00
pcapng_debug2 ( " pcapng_dump: encap = %d (%s) " ,
phdr - > pkt_encap ,
wtap_encap_string ( phdr - > pkt_encap ) ) ;
2011-03-24 23:33:38 +00:00
if ( ! pcapng - > addrinfo_list_last )
2011-03-24 22:47:57 +00:00
pcapng - > addrinfo_list_last = wdh - > addrinfo_list ;
/* Flush any hostname resolution info we may have */
while ( pcapng - > addrinfo_list_last & & pcapng - > addrinfo_list_last - > ai_next ) {
pcapng_write_name_resolution_block ( wdh , pcapng , err ) ;
}
2012-03-02 09:03:26 +00:00
if ( ! pcapng_write_enhanced_packet_block ( wdh , phdr , pseudo_header , pd , err ) ) {
2008-01-13 21:10:09 +00:00
return FALSE ;
}
return TRUE ;
}
2009-06-27 15:20:44 +00:00
/* Finish writing to a dump file.
Returns TRUE on success , FALSE on failure . */
static gboolean pcapng_dump_close ( wtap_dumper * wdh , int * err _U_ )
{
2010-02-26 07:59:54 +00:00
pcapng_dump_t * pcapng = ( pcapng_dump_t * ) wdh - > priv ;
2009-06-27 15:20:44 +00:00
pcapng_debug0 ( " pcapng_dump_close " ) ;
2010-02-26 07:59:54 +00:00
g_array_free ( pcapng - > interface_data , TRUE ) ;
pcapng - > number_of_interfaces = 0 ;
2009-06-27 15:20:44 +00:00
return TRUE ;
}
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
2011-04-12 00:44:44 +00:00
pcapng_dump_open ( wtap_dumper * wdh , int * err )
2008-01-13 21:10:09 +00:00
{
2010-02-26 07:59:54 +00:00
pcapng_dump_t * pcapng ;
2012-02-20 20:15:51 +00:00
int i ;
interface_data_t interface_data ;
2009-06-27 15:20:44 +00:00
pcapng_debug0 ( " pcapng_dump_open " ) ;
2008-01-13 21:10:09 +00:00
/* This is a pcapng file */
wdh - > subtype_write = pcapng_dump ;
2009-06-27 15:20:44 +00:00
wdh - > subtype_close = pcapng_dump_close ;
2011-03-24 22:47:57 +00:00
pcapng = ( pcapng_dump_t * ) g_malloc0 ( sizeof ( pcapng_dump_t ) ) ;
2010-02-26 07:59:54 +00:00
wdh - > priv = ( void * ) pcapng ;
2012-02-20 20:15:51 +00:00
pcapng - > interface_data = g_array_new ( FALSE , FALSE , sizeof ( wtapng_if_descr_t ) ) ;
2008-01-13 21:10:09 +00:00
2012-02-21 15:36:08 +00:00
if ( ( wdh - > number_of_interfaces = = 0 ) | | ( wdh - > interface_data = = NULL ) ) {
pcapng_debug0 ( " There are no interfaces. Can't handle that... " ) ;
* err = WTAP_ERR_INTERNAL ;
return FALSE ;
}
2008-01-13 21:10:09 +00:00
/* write the section header block */
2012-03-02 09:38:43 +00:00
if ( ! pcapng_write_section_header_block ( wdh , err ) ) {
2008-01-13 21:10:09 +00:00
return FALSE ;
}
2009-06-27 15:20:44 +00:00
pcapng_debug0 ( " pcapng_dump_open: wrote section header block. " ) ;
2008-01-13 21:10:09 +00:00
2012-02-20 20:15:51 +00:00
/* Write the Interface description blocks */
2012-02-21 15:36:08 +00:00
pcapng_debug1 ( " pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u " , wdh - > number_of_interfaces ) ;
2012-02-20 20:15:51 +00:00
2012-02-21 15:36:08 +00:00
for ( i = 0 ; i < ( int ) wdh - > number_of_interfaces ; i + + ) {
2012-02-20 20:15:51 +00:00
/* Get the interface description */
wtapng_if_descr_t int_data ;
int_data = g_array_index ( wdh - > interface_data , wtapng_if_descr_t , i ) ;
2012-03-02 09:30:10 +00:00
interface_data . wtap_encap = int_data . wtap_encap ;
2012-02-20 20:15:51 +00:00
interface_data . time_units_per_second = int_data . time_units_per_second ;
g_array_append_val ( pcapng - > interface_data , interface_data ) ;
pcapng - > number_of_interfaces + + ;
2012-03-02 09:30:10 +00:00
if ( ! pcapng_write_if_descr_block ( wdh , & int_data , err ) ) {
2012-02-20 20:15:51 +00:00
return FALSE ;
}
}
#if 0
interface_id = pcapng_lookup_interface_id_by_encap ( phdr - > pkt_encap , wdh ) ;
if ( interface_id = = G_MAXUINT32 ) {
/*
* We haven ' t yet written out an interface description
* block for an interface with this encapsulation .
*
* Is this encapsulation even supported in pcap - ng ?
*/
pcap_encap = wtap_wtap_encap_to_pcap_encap ( phdr - > pkt_encap ) ;
if ( pcap_encap = = - 1 ) {
/*
* No . Fail .
*/
* err = WTAP_ERR_UNSUPPORTED_ENCAP ;
return FALSE ;
}
/* write the interface description block */
wblock . frame_buffer = NULL ;
wblock . pseudo_header = NULL ;
wblock . packet_header = NULL ;
wblock . file_encap = NULL ;
wblock . type = BLOCK_TYPE_IDB ;
wblock . data . if_descr . link_type = pcap_encap ;
wblock . data . if_descr . snap_len = ( wdh - > snaplen ! = 0 ) ? wdh - > snaplen :
WTAP_MAX_PACKET_SIZE ; /* XXX */
/* XXX - options unused */
wblock . data . if_descr . if_speed = - 1 ;
/*wblock.data.if_descr.if_tsresol = 6;*/ /* default: usec */
wblock . data . if_descr . if_os = NULL ;
wblock . data . if_descr . if_fcslen = - 1 ;
2012-03-02 09:03:26 +00:00
if ( ! pcapng_write_if_descr_block ( wdh , & wblock , err ) ) {
2012-02-20 20:15:51 +00:00
return FALSE ;
}
interface_id = pcapng - > number_of_interfaces ;
int_data . wtap_encap = phdr - > pkt_encap ;
int_data . time_units_per_second = 0 ;
g_array_append_val ( pcapng - > interface_data , int_data ) ;
pcapng - > number_of_interfaces + + ;
pcapng_debug3 ( " pcapng_dump: added interface description block with index %u for encap = %d (%s). " ,
interface_id ,
phdr - > pkt_encap ,
wtap_encap_string ( phdr - > pkt_encap ) ) ;
}
# endif
2008-01-13 21:10:09 +00:00
return TRUE ;
}
/* 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
{
2009-06-27 15:20:44 +00:00
pcapng_debug2 ( " pcapng_dump_can_write_encap: encap = %d (%s) " ,
2009-06-27 16:08:18 +00:00
wtap_encap ,
2009-06-27 15:20:44 +00:00
wtap_encap_string ( wtap_encap ) ) ;
2011-02-04 02:08:47 +00:00
2012-03-03 16:17:20 +00:00
/* Per-packet encapsulation is supported. */
2009-06-27 15:20:44 +00:00
if ( wtap_encap = = WTAP_ENCAP_PER_PACKET )
2009-06-15 12:55:42 +00:00
return 0 ;
2008-01-13 21:10:09 +00:00
2009-05-22 07:33:58 +00:00
/* Make sure we can figure out this DLT type */
2009-06-27 15:20:44 +00:00
if ( wtap_wtap_encap_to_pcap_encap ( wtap_encap ) = = - 1 )
2008-01-13 21:10:09 +00:00
return WTAP_ERR_UNSUPPORTED_ENCAP ;
return 0 ;
}