From a4aa8930bb47296704a4689cdbfa8f5b8b3f550f Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Thu, 24 Mar 2016 13:00:07 -0700 Subject: Put pcapio.c into a writecap library, and use it. Change-Id: Ib89f345c072a38bc01f0513366a4bdae3bf6f08e Reviewed-on: https://code.wireshark.org/review/14615 Reviewed-by: Guy Harris --- .gitignore | 1 + CMakeLists.txt | 9 +- Makefile.am | 6 + Makefile.common | 5 - Makefile.nmake | 8 +- configure.ac | 2 + dumpcap.c | 2 +- extcap/Makefile.am | 2 +- extcap/Makefile.nmake | 1 + extcap/ciscodump.c | 2 +- pcapio.c | 744 ----------------------------------------------- pcapio.h | 116 -------- text2pcap.c | 2 +- writecap/.editorconfig | 21 ++ writecap/CMakeLists.txt | 45 +++ writecap/Makefile.am | 81 ++++++ writecap/Makefile.common | 28 ++ writecap/Makefile.nmake | 71 +++++ writecap/doxygen.cfg.in | 81 ++++++ writecap/pcapio.c | 744 +++++++++++++++++++++++++++++++++++++++++++++++ writecap/pcapio.h | 116 ++++++++ 21 files changed, 1212 insertions(+), 875 deletions(-) delete mode 100644 pcapio.c delete mode 100644 pcapio.h create mode 100644 writecap/.editorconfig create mode 100644 writecap/CMakeLists.txt create mode 100644 writecap/Makefile.am create mode 100644 writecap/Makefile.common create mode 100644 writecap/Makefile.nmake create mode 100644 writecap/doxygen.cfg.in create mode 100644 writecap/pcapio.c create mode 100644 writecap/pcapio.h diff --git a/.gitignore b/.gitignore index ddbc038d6b..478ec0ab04 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,7 @@ androiddump autom4te.cache capinfos captype +ciscodump compile config.h config.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b101b71bd..4ad19e13d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1020,6 +1020,7 @@ add_subdirectory( randpkt_core ) add_subdirectory( tools/lemon ) add_subdirectory( ui ) add_subdirectory( wiretap ) +add_subdirectory( writecap ) add_subdirectory( wsutil ) if(NOT WIN32) @@ -1208,6 +1209,7 @@ set( IN_FILES ui/gtk/doxygen.cfg.in ui/qt/doxygen.cfg.in wireshark.pc.in + writecap/doxygen.cfg.in ) foreach( _in_file ${IN_FILES} ) get_filename_component( _path ${_in_file} PATH ) @@ -1232,6 +1234,7 @@ link_directories( ${CMAKE_BINARY_DIR}/epan ${CMAKE_BINARY_DIR}/randpkt_core ${CMAKE_BINARY_DIR}/wiretap + ${CMAKE_BINARY_DIR}/writecap ${CMAKE_BINARY_DIR}/wsutil ) @@ -2142,13 +2145,13 @@ endif() if(BUILD_text2pcap) set(text2pcap_LIBS + writecap wsutil ${M_LIBRARIES} ${ZLIB_LIBRARIES} ) set(text2pcap_CLEAN_FILES text2pcap.c - pcapio.c ) set(text2pcap_FILES ${text2pcap_CLEAN_FILES} @@ -2248,6 +2251,7 @@ endif() if(BUILD_dumpcap AND PCAP_FOUND) set(dumpcap_LIBS + writecap wsutil caputils ${PCAP_LIBRARIES} @@ -2267,7 +2271,6 @@ if(BUILD_dumpcap AND PCAP_FOUND) conditions.c dumpcap.c filter_files.c - pcapio.c ringbuffer.c sync_pipe_write.c ${CMAKE_BINARY_DIR}/image/dumpcap.rc @@ -2376,6 +2379,7 @@ endif() if(ENABLE_EXTCAP AND BUILD_ciscodump AND LIBSSH_FOUND) set(ciscodump_LIBS + writecap wsutil ${GLIB2_LIBRARIES} ${CMAKE_DL_LIBS} @@ -2388,7 +2392,6 @@ if(ENABLE_EXTCAP AND BUILD_ciscodump AND LIBSSH_FOUND) extcap/ciscodump.c extcap/extcap-base.c extcap/ssh-base.c - pcapio.c ) add_executable(ciscodump WIN32 ${ciscodump_FILES}) diff --git a/Makefile.am b/Makefile.am index e3307d811e..f096414730 100644 --- a/Makefile.am +++ b/Makefile.am @@ -518,6 +518,7 @@ text2pcap_CFLAGS = $(GENERATED_CFLAGS) # Libraries with which to link text2pcap. text2pcap_LDADD = \ + writecap/libwritecap.a \ wsutil/libwsutil.la \ @GLIB_LIBS@ @@ -600,6 +601,7 @@ echld_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS) echld_test_LDADD = \ epan/libwireshark.la \ echld/libechld.la \ + writecap/libwritecap.a \ wsutil/libwsutil.la \ @GLIB_LIBS@ \ @PCAP_LIBS@ \ @@ -620,6 +622,7 @@ dumpcap_LDFLAGS = $(AM_LDFLAGS) $(PIE_LDFLAGS) # Libraries with which to link dumpcap. dumpcap_LDADD = \ caputils/libcaputils.a \ + writecap/libwritecap.a \ wsutil/libwsutil.la \ @GLIB_LIBS@ \ @PCAP_LIBS@ \ @@ -775,6 +778,7 @@ DIST_SUBDIRS = \ randpkt_core \ tools \ wiretap \ + writecap \ wsutil \ extcap \ docbook @@ -782,6 +786,7 @@ DIST_SUBDIRS = \ SUBDIRS = \ tools \ wsutil \ + writecap \ wiretap \ epan \ capchild \ @@ -1066,6 +1071,7 @@ checkapi: checkapi_local cd epan/dissectors && $(MAKE) checkapi cd plugins && $(MAKE) checkapi cd randpkt_core && $(MAKE) checkapi + cd writecap && $(MAKE) checkapi cd wsutil && $(MAKE) checkapi wsar_html: doxygen.cfg doxygen_global.cfg FORCE diff --git a/Makefile.common b/Makefile.common index 06236d09d0..0b09f61591 100644 --- a/Makefile.common +++ b/Makefile.common @@ -102,12 +102,10 @@ rawshark_SOURCES = \ # text2pcap specifics text2pcap_SOURCES = \ - pcapio.c \ text2pcap.c \ text2pcap-scanner.l text2pcap_INCLUDES = \ - pcapio.h \ text2pcap.h # mergecap specifics @@ -141,7 +139,6 @@ echld_test_SOURCES = \ capture_stop_conditions.c \ cfile.c \ conditions.c \ - pcapio.c \ ringbuffer.c \ sync_pipe_write.c @@ -156,7 +153,6 @@ dumpcap_SOURCES = \ conditions.c \ dumpcap.c \ filter_files.c \ - pcapio.c \ ringbuffer.c \ sync_pipe_write.c @@ -164,7 +160,6 @@ dumpcap_SOURCES = \ dumpcap_INCLUDES = \ capture_stop_conditions.h \ conditions.h \ - pcapio.h \ ringbuffer.h # this target needed for distribution only diff --git a/Makefile.nmake b/Makefile.nmake index 0ad2c4ebd6..77be3386c9 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -168,12 +168,14 @@ reordercap_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \ text2pcap_LIBS= \ wsock32.lib user32.lib \ + writecap\libwritecap.lib \ wsutil\libwsutil.lib \ $(GLIB_LIBS) dumpcap_LIBS= \ wsock32.lib user32.lib \ caputils\libcaputils.lib \ + writecap\libwritecap.lib \ wsutil\libwsutil.lib \ $(GLIB_LIBS) @@ -393,10 +395,10 @@ reordercap.exe : $(LIBS_CHECK) config.h $(reordercap_OBJECTS) wsutil\libwsutil. mt.exe -nologo -manifest "reordercap.exe.manifest" -outputresource:reordercap.exe;1 !ENDIF -text2pcap.exe : $(LIBS_CHECK) config.h text2pcap.obj text2pcap-scanner.obj pcapio.obj wsutil\libwsutil.lib wiretap\wiretap-$(WTAP_VERSION).lib image\text2pcap.res +text2pcap.exe : $(LIBS_CHECK) config.h text2pcap.obj text2pcap-scanner.obj writecap\libwritecap.lib wsutil\libwsutil.lib wiretap\wiretap-$(WTAP_VERSION).lib image\text2pcap.res @echo Linking $@ $(LINK) @<< - /OUT:text2pcap.exe $(conflags) $(conlibsdll) $(LDFLAGS) text2pcap.obj text2pcap-scanner.obj pcapio.obj $(text2pcap_LIBS) image\text2pcap.res + /OUT:text2pcap.exe $(conflags) $(conlibsdll) $(LDFLAGS) text2pcap.obj text2pcap-scanner.obj $(text2pcap_LIBS) image\text2pcap.res << !IFDEF MANIFEST_INFO_REQUIRED mt.exe -nologo -manifest "text2pcap.exe.manifest" -outputresource:text2pcap.exe;1 @@ -420,7 +422,7 @@ randpkt.exe : $(randpkt_OBJECTS) randpkt_core mt.exe -nologo -manifest "randpkt.exe.manifest" -outputresource:randpkt.exe;1 !ENDIF -dumpcap.exe : $(LIBS_CHECK) config.h $(dumpcap_OBJECTS) caputils wsutil\libwsutil.lib image\dumpcap.res +dumpcap.exe : $(LIBS_CHECK) config.h $(dumpcap_OBJECTS) caputils writecap\libwritecap.lib wsutil\libwsutil.lib image\dumpcap.res @echo Linking $@ $(LINK) @<< /OUT:dumpcap.exe $(conflags) $(conlibsdll) $(LDFLAGS) $(dumpcap_LIBS) $(dumpcap_OBJECTS) image\dumpcap.res diff --git a/configure.ac b/configure.ac index 49079ea8ae..8439a43eca 100644 --- a/configure.ac +++ b/configure.ac @@ -3329,6 +3329,8 @@ AC_OUTPUT( tools/Makefile tools/lemon/Makefile wiretap/Makefile + writecap/Makefile + writecap/doxygen.cfg wsutil/Makefile echld/Makefile _CUSTOM_AC_OUTPUT_ diff --git a/dumpcap.c b/dumpcap.c index 4d91d3c6ab..ccb297ddde 100644 --- a/dumpcap.c +++ b/dumpcap.c @@ -85,7 +85,7 @@ #include "caputils/capture-wpcap.h" #endif /* _WIN32 */ -#include "pcapio.h" +#include "writecap/pcapio.h" #ifdef _WIN32 #include diff --git a/extcap/Makefile.am b/extcap/Makefile.am index d4fee3baa1..ba5ee694e0 100644 --- a/extcap/Makefile.am +++ b/extcap/Makefile.am @@ -88,7 +88,7 @@ endif # Libraries and plugin flags with which to link ciscodump. ciscodump_LDADD = \ - ../wiretap/libwiretap.la \ + ../writecap/libwritecap.a \ ../wsutil/libwsutil.la \ @GLIB_LIBS@ \ @LIBSSH_LIBS@ \ diff --git a/extcap/Makefile.nmake b/extcap/Makefile.nmake index 4eea2b628b..57db68e8ff 100644 --- a/extcap/Makefile.nmake +++ b/extcap/Makefile.nmake @@ -65,6 +65,7 @@ ciscodump_OBJECTS = $(ciscodump_SOURCES:.c=.obj) ciscodump_WSLIBS = \ ..\wiretap\wiretap-$(WTAP_VERSION).lib \ + ..\writecap\libwritecap.lib \ ..\wsutil\libwsutil.lib ciscodump_LIBS = $(ciscodump_WSLIBS) \ diff --git a/extcap/ciscodump.c b/extcap/ciscodump.c index 97965d0bda..1db3f65662 100644 --- a/extcap/ciscodump.c +++ b/extcap/ciscodump.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff --git a/pcapio.c b/pcapio.c deleted file mode 100644 index ce2a90d0c1..0000000000 --- a/pcapio.c +++ /dev/null @@ -1,744 +0,0 @@ -/* pcapio.c - * Our own private code for writing libpcap files when capturing. - * - * We have these because we want a way to open a stream for output given - * only a file descriptor. libpcap 0.9[.x] has "pcap_dump_fopen()", which - * provides that, but - * - * 1) earlier versions of libpcap doesn't have it - * - * and - * - * 2) WinPcap doesn't have it, because a file descriptor opened - * by code built for one version of the MSVC++ C library - * can't be used by library routines built for another version - * (e.g., threaded vs. unthreaded). - * - * Libpcap's pcap_dump() also doesn't return any error indications. - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Derived from code in the Wiretap Library - * Copyright (c) 1998 by Gilbert Ramirez - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -#include -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef _WIN32 -#include -#endif - -#include - -#include "pcapio.h" - -/* Magic numbers in "libpcap" files. - - "libpcap" file records are written in the byte order of the host that - writes them, and the reader is expected to fix this up. - - PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC - is a byte-swapped version of that. - - PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format, - which uses the same common file format as PCAP_MAGIC, but the - timestamps are saved in nanosecond resolution instead of microseconds. - PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */ -#define PCAP_MAGIC 0xa1b2c3d4 -#define PCAP_SWAPPED_MAGIC 0xd4c3b2a1 -#define PCAP_NSEC_MAGIC 0xa1b23c4d -#define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1 - -/* "libpcap" file header. */ -struct pcap_hdr { - guint32 magic; /* magic number */ - guint16 version_major; /* major version number */ - guint16 version_minor; /* minor version number */ - gint32 thiszone; /* GMT to local correction */ - guint32 sigfigs; /* accuracy of timestamps */ - guint32 snaplen; /* max length of captured packets, in octets */ - guint32 network; /* data link type */ -}; - -/* "libpcap" record header. */ -struct pcaprec_hdr { - guint32 ts_sec; /* timestamp seconds */ - guint32 ts_usec; /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */ - guint32 incl_len; /* number of octets of packet saved in file */ - guint32 orig_len; /* actual length of packet */ -}; - -/* Magic numbers in ".pcapng" files. - * - * .pcapng file records are written in the byte order of the host that - * writes them, and the reader is expected to fix this up. - * PCAPNG_MAGIC is the magic number, in host byte order; - * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that. - */ -#define PCAPNG_MAGIC 0x1A2B3C4D -#define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1 - -/* Currently we are only supporting the initial version of - the file format. */ -#define PCAPNG_MAJOR_VERSION 1 -#define PCAPNG_MINOR_VERSION 0 - -/* Section Header Block without options and trailing Block Total Length */ -struct shb { - guint32 block_type; - guint32 block_total_length; - guint32 byte_order_magic; - guint16 major_version; - guint16 minor_version; - guint64 section_length; -}; -#define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A - -/* Interface Description Block without options and trailing Block Total Length */ -struct idb { - guint32 block_type; - guint32 block_total_length; - guint16 link_type; - guint16 reserved; - guint32 snap_len; -}; -#define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001 - -/* Interface Statistics Block without actual packet, options, and trailing - Block Total Length */ -struct isb { - guint32 block_type; - guint32 block_total_length; - guint32 interface_id; - guint32 timestamp_high; - guint32 timestamp_low; -}; -#define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005 - -/* Enhanced Packet Block without actual packet, options, and trailing - Block Total Length */ -struct epb { - guint32 block_type; - guint32 block_total_length; - guint32 interface_id; - guint32 timestamp_high; - guint32 timestamp_low; - guint32 captured_len; - guint32 packet_len; -}; -#define ENHANCED_PACKET_BLOCK_TYPE 0x00000006 - -struct option { - guint16 type; - guint16 value_length; -}; -#define OPT_ENDOFOPT 0 -#define OPT_COMMENT 1 -#define EPB_FLAGS 2 -#define SHB_HARDWARE 2 /* currently not used */ -#define SHB_OS 3 -#define SHB_USERAPPL 4 -#define IDB_NAME 2 -#define IDB_DESCRIPTION 3 -#define IDB_IF_SPEED 8 -#define IDB_TSRESOL 9 -#define IDB_FILTER 11 -#define IDB_OS 12 -#define ISB_STARTTIME 2 -#define ISB_ENDTIME 3 -#define ISB_IFRECV 4 -#define ISB_IFDROP 5 -#define ISB_FILTERACCEPT 6 -#define ISB_OSDROP 7 -#define ISB_USRDELIV 8 -#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2) - -/* Write to capture file */ -static gboolean -write_to_file(FILE* pfile, const guint8* data, size_t data_length, - guint64 *bytes_written, int *err) -{ - size_t nwritten; - - nwritten = fwrite(data, data_length, 1, pfile); - if (nwritten != 1) { - if (ferror(pfile)) { - *err = errno; - } else { - *err = 0; - } - return FALSE; - } - - (*bytes_written) += data_length; - return TRUE; -} - -/* Writing pcap files */ - -/* Write the file header to a dump file. - Returns TRUE on success, FALSE on failure. - Sets "*err" to an error code, or 0 for a short write, on failure*/ -gboolean -libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err) -{ - struct pcap_hdr file_hdr; - - file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC; - /* current "libpcap" format is 2.4 */ - file_hdr.version_major = 2; - file_hdr.version_minor = 4; - file_hdr.thiszone = 0; /* XXX - current offset? */ - file_hdr.sigfigs = 0; /* unknown, but also apparently unused */ - file_hdr.snaplen = snaplen; - file_hdr.network = linktype; - - return write_to_file(pfile, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err); -} - -/* Write a record for a packet to a dump file. - Returns TRUE on success, FALSE on failure. */ -gboolean -libpcap_write_packet(FILE* pfile, - time_t sec, guint32 usec, - guint32 caplen, guint32 len, - const guint8 *pd, - guint64 *bytes_written, int *err) -{ - struct pcaprec_hdr rec_hdr; - - rec_hdr.ts_sec = (guint32)sec; /* Y2.038K issue in pcap format.... */ - rec_hdr.ts_usec = usec; - rec_hdr.incl_len = caplen; - rec_hdr.orig_len = len; - if (!write_to_file(pfile, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err)) - return FALSE; - - return write_to_file(pfile, pd, caplen, bytes_written, err); -} - -/* Writing pcap-ng files */ - -static guint32 -pcapng_count_string_option(const char *option_value) -{ - if ((option_value != NULL) && (strlen(option_value) > 0) && (strlen(option_value) < G_MAXUINT16)) { - /* There's a value to write; get its length */ - return (guint32)(sizeof(struct option) + - (guint16)ADD_PADDING(strlen(option_value))); - } - return 0; /* nothing to write */ -} - -static gboolean -pcapng_write_string_option(FILE* pfile, - guint16 option_type, const char *option_value, - guint64 *bytes_written, int *err) -{ - size_t option_value_length; - struct option option; - const guint32 padding = 0; - - if (option_value == NULL) - return TRUE; /* nothing to write */ - option_value_length = strlen(option_value); - if ((option_value_length > 0) && (option_value_length < G_MAXUINT16)) { - /* something to write */ - option.type = option_type; - option.value_length = (guint16)option_value_length; - - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)option_value, (int) option_value_length, bytes_written, err)) - return FALSE; - - if (option_value_length % 4) { - if (!write_to_file(pfile, (const guint8*)&padding, 4 - option_value_length % 4, bytes_written, err)) - return FALSE; - } - } - return TRUE; -} - -gboolean -pcapng_write_session_header_block(FILE* pfile, - const char *comment, - const char *hw, - const char *os, - const char *appname, - guint64 section_length, - guint64 *bytes_written, - int *err) -{ - struct shb shb; - struct option option; - guint32 block_total_length; - guint32 options_length; - - /* Size of base header */ - block_total_length = sizeof(struct shb) + - sizeof(guint32); - options_length = 0; - options_length += pcapng_count_string_option(comment); - options_length += pcapng_count_string_option(hw); - options_length += pcapng_count_string_option(os); - options_length += pcapng_count_string_option(appname); - /* If we have options add size of end-of-options */ - if (options_length != 0) { - options_length += (guint32)sizeof(struct option); - } - block_total_length += options_length; - - /* write shb header */ - shb.block_type = SECTION_HEADER_BLOCK_TYPE; - shb.block_total_length = block_total_length; - shb.byte_order_magic = PCAPNG_MAGIC; - shb.major_version = PCAPNG_MAJOR_VERSION; - shb.minor_version = PCAPNG_MINOR_VERSION; - shb.section_length = section_length; - - if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err)) - return FALSE; - - if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, - bytes_written, err)) - return FALSE; - if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw, - bytes_written, err)) - return FALSE; - if (!pcapng_write_string_option(pfile, SHB_OS, os, - bytes_written, err)) - return FALSE; - if (!pcapng_write_string_option(pfile, SHB_USERAPPL, appname, - bytes_written, err)) - return FALSE; - if (options_length != 0) { - /* write end of options */ - option.type = OPT_ENDOFOPT; - option.value_length = 0; - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - } - - /* write the trailing block total length */ - return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); -} - -gboolean -pcapng_write_interface_description_block(FILE* pfile, - const char *comment, /* OPT_COMMENT 1 */ - const char *name, /* IDB_NAME 2 */ - const char *descr, /* IDB_DESCRIPTION 3 */ - const char *filter, /* IDB_FILTER 11 */ - const char *os, /* IDB_OS 12 */ - int link_type, - int snap_len, - guint64 *bytes_written, - guint64 if_speed, /* IDB_IF_SPEED 8 */ - guint8 tsresol, /* IDB_TSRESOL 9 */ - int *err) -{ - struct idb idb; - struct option option; - guint32 block_total_length; - guint32 options_length; - const guint32 padding = 0; - - block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32)); - options_length = 0; - /* 01 - OPT_COMMENT */ - options_length += pcapng_count_string_option(comment); - - /* 02 - IDB_NAME */ - options_length += pcapng_count_string_option(name); - - /* 03 - IDB_DESCRIPTION */ - options_length += pcapng_count_string_option(descr); - - /* 08 - IDB_IF_SPEED */ - if (if_speed != 0) { - options_length += (guint32)(sizeof(struct option) + - sizeof(guint64)); - } - - /* 09 - IDB_TSRESOL */ - if (tsresol != 0) { - options_length += (guint32)(sizeof(struct option) + - sizeof(struct option)); - } - - /* 11 - IDB_FILTER */ - if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) { - /* No, this isn't a string, it has an extra type byte */ - options_length += (guint32)(sizeof(struct option) + - (guint16)(ADD_PADDING(strlen(filter)+ 1))); - } - - /* 12 - IDB_OS */ - options_length += pcapng_count_string_option(os); - - /* If we have options add size of end-of-options */ - if (options_length != 0) { - options_length += (guint32)sizeof(struct option); - } - block_total_length += options_length; - - /* write block header */ - idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE; - idb.block_total_length = block_total_length; - idb.link_type = link_type; - idb.reserved = 0; - idb.snap_len = snap_len; - if (!write_to_file(pfile, (const guint8*)&idb, sizeof(struct idb), bytes_written, err)) - return FALSE; - - /* 01 - OPT_COMMENT - write comment string if applicable */ - if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, - bytes_written, err)) - return FALSE; - - /* 02 - IDB_NAME - write interface name string if applicable */ - if (!pcapng_write_string_option(pfile, IDB_NAME, name, - bytes_written, err)) - return FALSE; - - /* 03 - IDB_DESCRIPTION */ - /* write interface description string if applicable */ - if (!pcapng_write_string_option(pfile, IDB_DESCRIPTION, descr, - bytes_written, err)) - return FALSE; - - /* 08 - IDB_IF_SPEED */ - if (if_speed != 0) { - option.type = IDB_IF_SPEED; - option.value_length = sizeof(guint64); - - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err)) - return FALSE; - } - - /* 09 - IDB_TSRESOL */ - if (tsresol != 0) { - option.type = IDB_TSRESOL; - option.value_length = sizeof(guint8); - - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&padding, 3, bytes_written, err)) - return FALSE; - } - - /* 11 - IDB_FILTER - write filter string if applicable - * We only write version 1 of the filter, pcapng string - */ - if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16 - 1)) { - option.type = IDB_FILTER; - option.value_length = (guint16)(strlen(filter) + 1 ); - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */ - if (!write_to_file(pfile, (const guint8*)&padding, 1, bytes_written, err)) - return FALSE; - if (!write_to_file(pfile, (const guint8*)filter, (int) strlen(filter), bytes_written, err)) - return FALSE; - if ((strlen(filter) + 1) % 4) { - if (!write_to_file(pfile, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err)) - return FALSE; - } - } - - /* 12 - IDB_OS - write os string if applicable */ - if (!pcapng_write_string_option(pfile, IDB_OS, os, - bytes_written, err)) - return FALSE; - - if (options_length != 0) { - /* write end of options */ - option.type = OPT_ENDOFOPT; - option.value_length = 0; - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - } - - /* write the trailing Block Total Length */ - return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); -} - -/* Write a record for a packet to a dump file. - Returns TRUE on success, FALSE on failure. */ -gboolean -pcapng_write_enhanced_packet_block(FILE* pfile, - const char *comment, - time_t sec, guint32 usec, - guint32 caplen, guint32 len, - guint32 interface_id, - guint ts_mul, - const guint8 *pd, - guint32 flags, - guint64 *bytes_written, - int *err) -{ - struct epb epb; - struct option option; - guint32 block_total_length; - guint64 timestamp; - guint32 options_length; - const guint32 padding = 0; - - block_total_length = (guint32)(sizeof(struct epb) + - ADD_PADDING(caplen) + - sizeof(guint32)); - options_length = 0; - options_length += pcapng_count_string_option(comment); - if (flags != 0) { - options_length += (guint32)(sizeof(struct option) + - sizeof(guint32)); - } - /* If we have options add size of end-of-options */ - if (options_length != 0) { - options_length += (guint32)sizeof(struct option); - } - block_total_length += options_length; - timestamp = (guint64)sec * ts_mul + (guint64)usec; - epb.block_type = ENHANCED_PACKET_BLOCK_TYPE; - epb.block_total_length = block_total_length; - epb.interface_id = interface_id; - epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff); - epb.timestamp_low = (guint32)(timestamp & 0xffffffff); - epb.captured_len = caplen; - epb.packet_len = len; - if (!write_to_file(pfile, (const guint8*)&epb, sizeof(struct epb), bytes_written, err)) - return FALSE; - if (!write_to_file(pfile, pd, caplen, bytes_written, err)) - return FALSE; - if (caplen % 4) { - if (!write_to_file(pfile, (const guint8*)&padding, 4 - caplen % 4, bytes_written, err)) - return FALSE; - } - if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, - bytes_written, err)) - return FALSE; - if (flags != 0) { - option.type = EPB_FLAGS; - option.value_length = sizeof(guint32); - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - if (!write_to_file(pfile, (const guint8*)&flags, sizeof(guint32), bytes_written, err)) - return FALSE; - } - if (options_length != 0) { - /* write end of options */ - option.type = OPT_ENDOFOPT; - option.value_length = 0; - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - } - - return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); -} - -gboolean -pcapng_write_interface_statistics_block(FILE* pfile, - guint32 interface_id, - guint64 *bytes_written, - const char *comment, /* OPT_COMMENT 1 */ - guint64 isb_starttime, /* ISB_STARTTIME 2 */ - guint64 isb_endtime, /* ISB_ENDTIME 3 */ - guint64 isb_ifrecv, /* ISB_IFRECV 4 */ - guint64 isb_ifdrop, /* ISB_IFDROP 5 */ - int *err) -{ - struct isb isb; -#ifdef _WIN32 - FILETIME now; -#else - struct timeval now; -#endif - struct option option; - guint32 block_total_length; - guint32 options_length; - guint64 timestamp; - -#ifdef _WIN32 - /* - * Current time, represented as 100-nanosecond intervals since - * January 1, 1601, 00:00:00 UTC. - * - * I think DWORD might be signed, so cast both parts of "now" - * to guint32 so that the sign bit doesn't get treated specially. - * - * Windows 8 provides GetSystemTimePreciseAsFileTime which we - * might want to use instead. - */ - GetSystemTimeAsFileTime(&now); - timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) + - (guint32)now.dwLowDateTime; - - /* - * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond, - * intervals. - */ - timestamp /= 10; - - /* - * Subtract difference, in microseconds, between January 1, 1601 - * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC. - */ - timestamp -= G_GUINT64_CONSTANT(11644473600000000); -#else - /* - * Current time, represented as seconds and microseconds since - * January 1, 1970, 00:00:00 UTC. - */ - gettimeofday(&now, NULL); - - /* - * Convert to delta in microseconds. - */ - timestamp = (guint64)(now.tv_sec) * 1000000 + - (guint64)(now.tv_usec); -#endif - block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32)); - options_length = 0; - if (isb_ifrecv != G_MAXUINT64) { - options_length += (guint32)(sizeof(struct option) + - sizeof(guint64)); - } - if (isb_ifdrop != G_MAXUINT64) { - options_length += (guint32)(sizeof(struct option) + - sizeof(guint64)); - } - /* OPT_COMMENT */ - options_length += pcapng_count_string_option(comment); - if (isb_starttime !=0) { - options_length += (guint32)(sizeof(struct option) + - sizeof(guint64)); /* ISB_STARTTIME */ - } - if (isb_endtime !=0) { - options_length += (guint32)(sizeof(struct option) + - sizeof(guint64)); /* ISB_ENDTIME */ - } - /* If we have options add size of end-of-options */ - if (options_length != 0) { - options_length += (guint32)sizeof(struct option); - } - block_total_length += options_length; - - isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE; - isb.block_total_length = block_total_length; - isb.interface_id = interface_id; - isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff); - isb.timestamp_low = (guint32)(timestamp & 0xffffffff); - if (!write_to_file(pfile, (const guint8*)&isb, sizeof(struct isb), bytes_written, err)) - return FALSE; - - /* write comment string if applicable */ - if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, - bytes_written, err)) - return FALSE; - - if (isb_starttime !=0) { - guint32 high, low; - - option.type = ISB_STARTTIME; - option.value_length = sizeof(guint64); - high = (guint32)((isb_starttime>>32) & 0xffffffff); - low = (guint32)(isb_starttime & 0xffffffff); - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err)) - return FALSE; - } - if (isb_endtime !=0) { - guint32 high, low; - - option.type = ISB_ENDTIME; - option.value_length = sizeof(guint64); - high = (guint32)((isb_endtime>>32) & 0xffffffff); - low = (guint32)(isb_endtime & 0xffffffff); - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err)) - return FALSE; - } - if (isb_ifrecv != G_MAXUINT64) { - option.type = ISB_IFRECV; - option.value_length = sizeof(guint64); - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err)) - return FALSE; - } - if (isb_ifdrop != G_MAXUINT64) { - option.type = ISB_IFDROP; - option.value_length = sizeof(guint64); - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - - if (!write_to_file(pfile, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err)) - return FALSE; - } - if (options_length != 0) { - /* write end of options */ - option.type = OPT_ENDOFOPT; - option.value_length = 0; - if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) - return FALSE; - } - - return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); -} - -/* - * Editor modelines - http://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=8 tabstop=8 expandtab: - * :indentSize=8:tabSize=8:noTabs=true: - */ diff --git a/pcapio.h b/pcapio.h deleted file mode 100644 index 9263024f02..0000000000 --- a/pcapio.h +++ /dev/null @@ -1,116 +0,0 @@ -/* pcapio.h - * Declarations of our own routines for writing libpcap files. - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Derived from code in the Wiretap Library - * Copyright (c) 1998 by Gilbert Ramirez - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* Writing pcap files */ - -/** Write the file header to a dump file. - Returns TRUE on success, FALSE on failure. - Sets "*err" to an error code, or 0 for a short write, on failure*/ -extern gboolean -libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, - gboolean ts_nsecs, guint64 *bytes_written, int *err); - -/** Write a record for a packet to a dump file. - Returns TRUE on success, FALSE on failure. */ -extern gboolean -libpcap_write_packet(FILE* pfile, - time_t sec, guint32 usec, - guint32 caplen, guint32 len, - const guint8 *pd, - guint64 *bytes_written, int *err); - -/* Writing pcap-ng files */ - -/** Write a section header block (SHB) - * - */ -extern gboolean -pcapng_write_session_header_block(FILE* pfile, /**< Write information */ - const char *comment, /**< Comment on the section, Optinon 1 opt_comment - * A UTF-8 string containing a comment that is associated to the current block. - */ - const char *hw, /**< HW, Optinon 2 shb_hardware - * An UTF-8 string containing the description of the hardware used to create this section. - */ - const char *os, /**< Operating system name, Optinon 3 shb_os - * An UTF-8 string containing the name of the operating system used to create this section. - */ - const char *appname, /**< Application name, Optinon 4 shb_userappl - * An UTF-8 string containing the name of the application used to create this section. - */ - guint64 section_length, /**< Length of section */ - guint64 *bytes_written, /**< Number of written bytes */ - int *err /**< Error type */ - ); - -extern gboolean -pcapng_write_interface_description_block(FILE* pfile, - const char *comment, /* OPT_COMMENT 1 */ - const char *name, /* IDB_NAME 2 */ - const char *descr, /* IDB_DESCRIPTION 3 */ - const char *filter, /* IDB_FILTER 11 */ - const char *os, /* IDB_OS 12 */ - int link_type, - int snap_len, - guint64 *bytes_written, - guint64 if_speed, /* IDB_IF_SPEED 8 */ - guint8 tsresol, /* IDB_TSRESOL 9 */ - int *err); - -extern gboolean -pcapng_write_interface_statistics_block(FILE* pfile, - guint32 interface_id, - guint64 *bytes_written, - const char *comment, /* OPT_COMMENT 1 */ - guint64 isb_starttime, /* ISB_STARTTIME 2 */ - guint64 isb_endtime, /* ISB_ENDTIME 3 */ - guint64 isb_ifrecv, /* ISB_IFRECV 4 */ - guint64 isb_ifdrop, /* ISB_IFDROP 5 */ - int *err); - -extern gboolean -pcapng_write_enhanced_packet_block(FILE* pfile, - const char *comment, - time_t sec, guint32 usec, - guint32 caplen, guint32 len, - guint32 interface_id, - guint ts_mul, - const guint8 *pd, - guint32 flags, - guint64 *bytes_written, - int *err); - -/* - * Editor modelines - http://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 4 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=4 tabstop=8 expandtab: - * :indentSize=4:tabSize=8:noTabs=true: - */ diff --git a/text2pcap.c b/text2pcap.c index bc958cbb4f..e50dad30b6 100644 --- a/text2pcap.c +++ b/text2pcap.c @@ -138,7 +138,7 @@ # include "wsutil/strptime.h" #endif -#include "pcapio.h" +#include "writecap/pcapio.h" #include "text2pcap.h" #ifdef _WIN32 diff --git a/writecap/.editorconfig b/writecap/.editorconfig new file mode 100644 index 0000000000..cd0ff58912 --- /dev/null +++ b/writecap/.editorconfig @@ -0,0 +1,21 @@ +# +# Editor configuration +# +# http://editorconfig.org/ +# + +[capture-pcap-util-unix.[ch]] +indent_style = tab +indent_size = tab + +[capture-pcap-util.[ch]] +indent_style = tab +indent_size = tab + +[capture-wpcap.[ch]] +indent_style = tab +indent_size = tab + +[ws80211_utils.[ch]] +indent_style = tab +indent_size = tab diff --git a/writecap/CMakeLists.txt b/writecap/CMakeLists.txt new file mode 100644 index 0000000000..582b8959b4 --- /dev/null +++ b/writecap/CMakeLists.txt @@ -0,0 +1,45 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +set(WRITECAP_SRC + pcapio.c +) + +set(CLEAN_FILES + ${WRITECAP_SRC} +) + +if (WERROR_COMMON_FLAGS) + set_source_files_properties( + ${CLEAN_FILES} + PROPERTIES + COMPILE_FLAGS ${WERROR_COMMON_FLAGS} + ) +endif() + + +add_library(writecap STATIC + ${WRITECAP_SRC} +) + +set_target_properties(writecap PROPERTIES + LINK_FLAGS "${WS_LINK_FLAGS}" + FOLDER "Libs") diff --git a/writecap/Makefile.am b/writecap/Makefile.am new file mode 100644 index 0000000000..bdff5c6eb9 --- /dev/null +++ b/writecap/Makefile.am @@ -0,0 +1,81 @@ +# Makefile.am +# Automake file for the "write capture file" routines for Wireshark +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +include Makefile.common +include $(top_srcdir)/Makefile.am.inc + +AM_CPPFLAGS = $(INCLUDEDIRS) $(WS_CPPFLAGS) $(GLIB_CFLAGS) + +noinst_LIBRARIES = libwritecap.a + +CLEANFILES = \ + doxygen-writecap.tag \ + libwritecap.a \ + *~ + +MAINTAINERCLEANFILES = \ + $(GENERATED_FILES) \ + Makefile.in + +EXTRA_DIST = \ + .editorconfig \ + $(GENERATOR_FILES) \ + CMakeLists.txt \ + doxygen.cfg.in \ + Makefile.common \ + Makefile.nmake + +# All sources that should be put in the source distribution tarball +libwritecap_a_SOURCES = \ + $(WRITECAP_SRC) \ + $(noinst_HEADERS) + +# +# This is used to build dumpcap, and dumpcap is, if possible, built as +# a position-independent executable (for address space layout randomization, +# as it might be running with extra privileges), so this library needs +# to be built that way as well. +# +libwritecap_a_CFLAGS = $(AM_CFLAGS) $(PIE_CFLAGS) + +libwritecap_a_DEPENDENCIES = + +doxygen: +if HAVE_DOXYGEN + $(DOXYGEN) doxygen.cfg +endif # HAVE_DOXYGEN + +wsar_html: doxygen.cfg ../doxygen_global.cfg +if HAVE_DOXYGEN + (umask 022 ; $(DOXYGEN) doxygen.cfg) +endif + +checkapi: checkapi-base checkapi-todo + +checkapi-base: + $(PERL) $(top_srcdir)/tools/checkAPIs.pl -g deprecated-gtk -build \ + -sourcedir=$(srcdir) \ + $(WRITECAP_SRC) + +checkapi-todo: + $(PERL) $(top_srcdir)/tools/checkAPIs.pl -M -g deprecated-gtk-todo -build \ + -sourcedir=$(srcdir) \ + $(WRITECAP_SRC) diff --git a/writecap/Makefile.common b/writecap/Makefile.common new file mode 100644 index 0000000000..c33695c873 --- /dev/null +++ b/writecap/Makefile.common @@ -0,0 +1,28 @@ +# Makefile.common +# Contains the stuff from Makefile.am and Makefile.nmake that is +# a) common to both files and +# b) portable between both files +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +WRITECAP_SRC = \ + pcapio.c + +noinst_HEADERS = \ + pcapio.h diff --git a/writecap/Makefile.nmake b/writecap/Makefile.nmake new file mode 100644 index 0000000000..3862ca541f --- /dev/null +++ b/writecap/Makefile.nmake @@ -0,0 +1,71 @@ +## Makefile for building wireshark.exe with Microsoft C and nmake +## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake +# + +include ..\config.nmake +include ..\Makefile.nmake.inc +include Makefile.common + +############### no need to modify below this line ######### + +# We use GENERATED_CFLAGS to get around flex's non-LLP64-compliant output +GENERATED_CFLAGS=\ + $(STANDARD_CFLAGS) \ + /Zm800 \ + /I.. $(GLIB_CFLAGS) + +CFLAGS=$(WARNINGS_ARE_ERRORS) $(GENERATED_CFLAGS) + +.c.obj:: + $(CC) $(CFLAGS) $(WSUG_CFLAGS) -Fd.\ -c $< + +# if you add files here, be sure to include them also in Makefile.am EXTRA_DIST +WRITECAP_OBJECTS = \ + $(WRITECAP_SRC:.c=.obj) + +RUNLEX=../tools/runlex.sh + +libcaputils.lib : ..\config.h $(WRITECAP_OBJECTS) + link /lib /out:libcaputils.lib $(WRITECAP_OBJECTS) + +clean: + rm -f $(WRITECAP_OBJECTS) $(WIRESHARK_TAP_OBJECTS) libcaputils.lib \ + *.nativecodeanalysis.xml *.pdb *.sbr \ + doxygen.cfg html/*.* + if exist html rmdir html + +distclean: clean + +maintainer-clean: distclean + rm -f $(GENERATED_FILES) + +# convert doxygen.cfg.in to doxygen.cfg with stamped version info +doxygen.cfg: ..\config.nmake doxygen.cfg.in +!IFDEF DOXYGEN + sed -e s/@VERSION@/$(VERSION)/ \ + < doxygen.cfg.in > $@ +!ENDIF + +doxygen-run: +!IFDEF DOXYGEN + $(DOXYGEN) doxygen.cfg +!ENDIF + +# MS html help compiler hhc returns 1 on success, but as nmake expects 0 it would stop here. +# the prepended -1 will raise the accepted error levels of nmake, so it will continue +doxygen.chm: +!IFDEF HHC + -1 $(HHC) html\index.hhp +!ENDIF + +doxygen: doxygen.cfg doxygen-run doxygen.chm + +checkapi: checkapi-base checkapi-todo + +checkapi-base: + $(PERL) ../tools/checkAPIs.pl -g deprecated-gtk -build \ + $(WRITECAP_SRC) + +checkapi-todo: + $(PERL) ../tools/checkAPIs.pl -M -g deprecated-gtk-todo -build \ + $(WRITECAP_SRC) diff --git a/writecap/doxygen.cfg.in b/writecap/doxygen.cfg.in new file mode 100644 index 0000000000..cae55f4037 --- /dev/null +++ b/writecap/doxygen.cfg.in @@ -0,0 +1,81 @@ +# @configure_input@ + +@INCLUDE = ../doxygen_global.cfg + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Wireshark Capture Utilities Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../wsar_html + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = caputils + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = ../doxygen-core.tag=.. + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = doxygen-caputils.tag + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = wireshark-caputils.chm diff --git a/writecap/pcapio.c b/writecap/pcapio.c new file mode 100644 index 0000000000..ce2a90d0c1 --- /dev/null +++ b/writecap/pcapio.c @@ -0,0 +1,744 @@ +/* pcapio.c + * Our own private code for writing libpcap files when capturing. + * + * We have these because we want a way to open a stream for output given + * only a file descriptor. libpcap 0.9[.x] has "pcap_dump_fopen()", which + * provides that, but + * + * 1) earlier versions of libpcap doesn't have it + * + * and + * + * 2) WinPcap doesn't have it, because a file descriptor opened + * by code built for one version of the MSVC++ C library + * can't be used by library routines built for another version + * (e.g., threaded vs. unthreaded). + * + * Libpcap's pcap_dump() also doesn't return any error indications. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * Derived from code in the Wiretap Library + * Copyright (c) 1998 by Gilbert Ramirez + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef _WIN32 +#include +#endif + +#include + +#include "pcapio.h" + +/* Magic numbers in "libpcap" files. + + "libpcap" file records are written in the byte order of the host that + writes them, and the reader is expected to fix this up. + + PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC + is a byte-swapped version of that. + + PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format, + which uses the same common file format as PCAP_MAGIC, but the + timestamps are saved in nanosecond resolution instead of microseconds. + PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */ +#define PCAP_MAGIC 0xa1b2c3d4 +#define PCAP_SWAPPED_MAGIC 0xd4c3b2a1 +#define PCAP_NSEC_MAGIC 0xa1b23c4d +#define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1 + +/* "libpcap" file header. */ +struct pcap_hdr { + guint32 magic; /* magic number */ + guint16 version_major; /* major version number */ + guint16 version_minor; /* minor version number */ + gint32 thiszone; /* GMT to local correction */ + guint32 sigfigs; /* accuracy of timestamps */ + guint32 snaplen; /* max length of captured packets, in octets */ + guint32 network; /* data link type */ +}; + +/* "libpcap" record header. */ +struct pcaprec_hdr { + guint32 ts_sec; /* timestamp seconds */ + guint32 ts_usec; /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */ + guint32 incl_len; /* number of octets of packet saved in file */ + guint32 orig_len; /* actual length of packet */ +}; + +/* Magic numbers in ".pcapng" files. + * + * .pcapng file records are written in the byte order of the host that + * writes them, and the reader is expected to fix this up. + * PCAPNG_MAGIC is the magic number, in host byte order; + * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that. + */ +#define PCAPNG_MAGIC 0x1A2B3C4D +#define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1 + +/* Currently we are only supporting the initial version of + the file format. */ +#define PCAPNG_MAJOR_VERSION 1 +#define PCAPNG_MINOR_VERSION 0 + +/* Section Header Block without options and trailing Block Total Length */ +struct shb { + guint32 block_type; + guint32 block_total_length; + guint32 byte_order_magic; + guint16 major_version; + guint16 minor_version; + guint64 section_length; +}; +#define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A + +/* Interface Description Block without options and trailing Block Total Length */ +struct idb { + guint32 block_type; + guint32 block_total_length; + guint16 link_type; + guint16 reserved; + guint32 snap_len; +}; +#define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001 + +/* Interface Statistics Block without actual packet, options, and trailing + Block Total Length */ +struct isb { + guint32 block_type; + guint32 block_total_length; + guint32 interface_id; + guint32 timestamp_high; + guint32 timestamp_low; +}; +#define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005 + +/* Enhanced Packet Block without actual packet, options, and trailing + Block Total Length */ +struct epb { + guint32 block_type; + guint32 block_total_length; + guint32 interface_id; + guint32 timestamp_high; + guint32 timestamp_low; + guint32 captured_len; + guint32 packet_len; +}; +#define ENHANCED_PACKET_BLOCK_TYPE 0x00000006 + +struct option { + guint16 type; + guint16 value_length; +}; +#define OPT_ENDOFOPT 0 +#define OPT_COMMENT 1 +#define EPB_FLAGS 2 +#define SHB_HARDWARE 2 /* currently not used */ +#define SHB_OS 3 +#define SHB_USERAPPL 4 +#define IDB_NAME 2 +#define IDB_DESCRIPTION 3 +#define IDB_IF_SPEED 8 +#define IDB_TSRESOL 9 +#define IDB_FILTER 11 +#define IDB_OS 12 +#define ISB_STARTTIME 2 +#define ISB_ENDTIME 3 +#define ISB_IFRECV 4 +#define ISB_IFDROP 5 +#define ISB_FILTERACCEPT 6 +#define ISB_OSDROP 7 +#define ISB_USRDELIV 8 +#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2) + +/* Write to capture file */ +static gboolean +write_to_file(FILE* pfile, const guint8* data, size_t data_length, + guint64 *bytes_written, int *err) +{ + size_t nwritten; + + nwritten = fwrite(data, data_length, 1, pfile); + if (nwritten != 1) { + if (ferror(pfile)) { + *err = errno; + } else { + *err = 0; + } + return FALSE; + } + + (*bytes_written) += data_length; + return TRUE; +} + +/* Writing pcap files */ + +/* Write the file header to a dump file. + Returns TRUE on success, FALSE on failure. + Sets "*err" to an error code, or 0 for a short write, on failure*/ +gboolean +libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err) +{ + struct pcap_hdr file_hdr; + + file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC; + /* current "libpcap" format is 2.4 */ + file_hdr.version_major = 2; + file_hdr.version_minor = 4; + file_hdr.thiszone = 0; /* XXX - current offset? */ + file_hdr.sigfigs = 0; /* unknown, but also apparently unused */ + file_hdr.snaplen = snaplen; + file_hdr.network = linktype; + + return write_to_file(pfile, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err); +} + +/* Write a record for a packet to a dump file. + Returns TRUE on success, FALSE on failure. */ +gboolean +libpcap_write_packet(FILE* pfile, + time_t sec, guint32 usec, + guint32 caplen, guint32 len, + const guint8 *pd, + guint64 *bytes_written, int *err) +{ + struct pcaprec_hdr rec_hdr; + + rec_hdr.ts_sec = (guint32)sec; /* Y2.038K issue in pcap format.... */ + rec_hdr.ts_usec = usec; + rec_hdr.incl_len = caplen; + rec_hdr.orig_len = len; + if (!write_to_file(pfile, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err)) + return FALSE; + + return write_to_file(pfile, pd, caplen, bytes_written, err); +} + +/* Writing pcap-ng files */ + +static guint32 +pcapng_count_string_option(const char *option_value) +{ + if ((option_value != NULL) && (strlen(option_value) > 0) && (strlen(option_value) < G_MAXUINT16)) { + /* There's a value to write; get its length */ + return (guint32)(sizeof(struct option) + + (guint16)ADD_PADDING(strlen(option_value))); + } + return 0; /* nothing to write */ +} + +static gboolean +pcapng_write_string_option(FILE* pfile, + guint16 option_type, const char *option_value, + guint64 *bytes_written, int *err) +{ + size_t option_value_length; + struct option option; + const guint32 padding = 0; + + if (option_value == NULL) + return TRUE; /* nothing to write */ + option_value_length = strlen(option_value); + if ((option_value_length > 0) && (option_value_length < G_MAXUINT16)) { + /* something to write */ + option.type = option_type; + option.value_length = (guint16)option_value_length; + + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)option_value, (int) option_value_length, bytes_written, err)) + return FALSE; + + if (option_value_length % 4) { + if (!write_to_file(pfile, (const guint8*)&padding, 4 - option_value_length % 4, bytes_written, err)) + return FALSE; + } + } + return TRUE; +} + +gboolean +pcapng_write_session_header_block(FILE* pfile, + const char *comment, + const char *hw, + const char *os, + const char *appname, + guint64 section_length, + guint64 *bytes_written, + int *err) +{ + struct shb shb; + struct option option; + guint32 block_total_length; + guint32 options_length; + + /* Size of base header */ + block_total_length = sizeof(struct shb) + + sizeof(guint32); + options_length = 0; + options_length += pcapng_count_string_option(comment); + options_length += pcapng_count_string_option(hw); + options_length += pcapng_count_string_option(os); + options_length += pcapng_count_string_option(appname); + /* If we have options add size of end-of-options */ + if (options_length != 0) { + options_length += (guint32)sizeof(struct option); + } + block_total_length += options_length; + + /* write shb header */ + shb.block_type = SECTION_HEADER_BLOCK_TYPE; + shb.block_total_length = block_total_length; + shb.byte_order_magic = PCAPNG_MAGIC; + shb.major_version = PCAPNG_MAJOR_VERSION; + shb.minor_version = PCAPNG_MINOR_VERSION; + shb.section_length = section_length; + + if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err)) + return FALSE; + + if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, + bytes_written, err)) + return FALSE; + if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw, + bytes_written, err)) + return FALSE; + if (!pcapng_write_string_option(pfile, SHB_OS, os, + bytes_written, err)) + return FALSE; + if (!pcapng_write_string_option(pfile, SHB_USERAPPL, appname, + bytes_written, err)) + return FALSE; + if (options_length != 0) { + /* write end of options */ + option.type = OPT_ENDOFOPT; + option.value_length = 0; + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + } + + /* write the trailing block total length */ + return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); +} + +gboolean +pcapng_write_interface_description_block(FILE* pfile, + const char *comment, /* OPT_COMMENT 1 */ + const char *name, /* IDB_NAME 2 */ + const char *descr, /* IDB_DESCRIPTION 3 */ + const char *filter, /* IDB_FILTER 11 */ + const char *os, /* IDB_OS 12 */ + int link_type, + int snap_len, + guint64 *bytes_written, + guint64 if_speed, /* IDB_IF_SPEED 8 */ + guint8 tsresol, /* IDB_TSRESOL 9 */ + int *err) +{ + struct idb idb; + struct option option; + guint32 block_total_length; + guint32 options_length; + const guint32 padding = 0; + + block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32)); + options_length = 0; + /* 01 - OPT_COMMENT */ + options_length += pcapng_count_string_option(comment); + + /* 02 - IDB_NAME */ + options_length += pcapng_count_string_option(name); + + /* 03 - IDB_DESCRIPTION */ + options_length += pcapng_count_string_option(descr); + + /* 08 - IDB_IF_SPEED */ + if (if_speed != 0) { + options_length += (guint32)(sizeof(struct option) + + sizeof(guint64)); + } + + /* 09 - IDB_TSRESOL */ + if (tsresol != 0) { + options_length += (guint32)(sizeof(struct option) + + sizeof(struct option)); + } + + /* 11 - IDB_FILTER */ + if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) { + /* No, this isn't a string, it has an extra type byte */ + options_length += (guint32)(sizeof(struct option) + + (guint16)(ADD_PADDING(strlen(filter)+ 1))); + } + + /* 12 - IDB_OS */ + options_length += pcapng_count_string_option(os); + + /* If we have options add size of end-of-options */ + if (options_length != 0) { + options_length += (guint32)sizeof(struct option); + } + block_total_length += options_length; + + /* write block header */ + idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE; + idb.block_total_length = block_total_length; + idb.link_type = link_type; + idb.reserved = 0; + idb.snap_len = snap_len; + if (!write_to_file(pfile, (const guint8*)&idb, sizeof(struct idb), bytes_written, err)) + return FALSE; + + /* 01 - OPT_COMMENT - write comment string if applicable */ + if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, + bytes_written, err)) + return FALSE; + + /* 02 - IDB_NAME - write interface name string if applicable */ + if (!pcapng_write_string_option(pfile, IDB_NAME, name, + bytes_written, err)) + return FALSE; + + /* 03 - IDB_DESCRIPTION */ + /* write interface description string if applicable */ + if (!pcapng_write_string_option(pfile, IDB_DESCRIPTION, descr, + bytes_written, err)) + return FALSE; + + /* 08 - IDB_IF_SPEED */ + if (if_speed != 0) { + option.type = IDB_IF_SPEED; + option.value_length = sizeof(guint64); + + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err)) + return FALSE; + } + + /* 09 - IDB_TSRESOL */ + if (tsresol != 0) { + option.type = IDB_TSRESOL; + option.value_length = sizeof(guint8); + + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&padding, 3, bytes_written, err)) + return FALSE; + } + + /* 11 - IDB_FILTER - write filter string if applicable + * We only write version 1 of the filter, pcapng string + */ + if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16 - 1)) { + option.type = IDB_FILTER; + option.value_length = (guint16)(strlen(filter) + 1 ); + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */ + if (!write_to_file(pfile, (const guint8*)&padding, 1, bytes_written, err)) + return FALSE; + if (!write_to_file(pfile, (const guint8*)filter, (int) strlen(filter), bytes_written, err)) + return FALSE; + if ((strlen(filter) + 1) % 4) { + if (!write_to_file(pfile, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err)) + return FALSE; + } + } + + /* 12 - IDB_OS - write os string if applicable */ + if (!pcapng_write_string_option(pfile, IDB_OS, os, + bytes_written, err)) + return FALSE; + + if (options_length != 0) { + /* write end of options */ + option.type = OPT_ENDOFOPT; + option.value_length = 0; + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + } + + /* write the trailing Block Total Length */ + return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); +} + +/* Write a record for a packet to a dump file. + Returns TRUE on success, FALSE on failure. */ +gboolean +pcapng_write_enhanced_packet_block(FILE* pfile, + const char *comment, + time_t sec, guint32 usec, + guint32 caplen, guint32 len, + guint32 interface_id, + guint ts_mul, + const guint8 *pd, + guint32 flags, + guint64 *bytes_written, + int *err) +{ + struct epb epb; + struct option option; + guint32 block_total_length; + guint64 timestamp; + guint32 options_length; + const guint32 padding = 0; + + block_total_length = (guint32)(sizeof(struct epb) + + ADD_PADDING(caplen) + + sizeof(guint32)); + options_length = 0; + options_length += pcapng_count_string_option(comment); + if (flags != 0) { + options_length += (guint32)(sizeof(struct option) + + sizeof(guint32)); + } + /* If we have options add size of end-of-options */ + if (options_length != 0) { + options_length += (guint32)sizeof(struct option); + } + block_total_length += options_length; + timestamp = (guint64)sec * ts_mul + (guint64)usec; + epb.block_type = ENHANCED_PACKET_BLOCK_TYPE; + epb.block_total_length = block_total_length; + epb.interface_id = interface_id; + epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff); + epb.timestamp_low = (guint32)(timestamp & 0xffffffff); + epb.captured_len = caplen; + epb.packet_len = len; + if (!write_to_file(pfile, (const guint8*)&epb, sizeof(struct epb), bytes_written, err)) + return FALSE; + if (!write_to_file(pfile, pd, caplen, bytes_written, err)) + return FALSE; + if (caplen % 4) { + if (!write_to_file(pfile, (const guint8*)&padding, 4 - caplen % 4, bytes_written, err)) + return FALSE; + } + if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, + bytes_written, err)) + return FALSE; + if (flags != 0) { + option.type = EPB_FLAGS; + option.value_length = sizeof(guint32); + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + if (!write_to_file(pfile, (const guint8*)&flags, sizeof(guint32), bytes_written, err)) + return FALSE; + } + if (options_length != 0) { + /* write end of options */ + option.type = OPT_ENDOFOPT; + option.value_length = 0; + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + } + + return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); +} + +gboolean +pcapng_write_interface_statistics_block(FILE* pfile, + guint32 interface_id, + guint64 *bytes_written, + const char *comment, /* OPT_COMMENT 1 */ + guint64 isb_starttime, /* ISB_STARTTIME 2 */ + guint64 isb_endtime, /* ISB_ENDTIME 3 */ + guint64 isb_ifrecv, /* ISB_IFRECV 4 */ + guint64 isb_ifdrop, /* ISB_IFDROP 5 */ + int *err) +{ + struct isb isb; +#ifdef _WIN32 + FILETIME now; +#else + struct timeval now; +#endif + struct option option; + guint32 block_total_length; + guint32 options_length; + guint64 timestamp; + +#ifdef _WIN32 + /* + * Current time, represented as 100-nanosecond intervals since + * January 1, 1601, 00:00:00 UTC. + * + * I think DWORD might be signed, so cast both parts of "now" + * to guint32 so that the sign bit doesn't get treated specially. + * + * Windows 8 provides GetSystemTimePreciseAsFileTime which we + * might want to use instead. + */ + GetSystemTimeAsFileTime(&now); + timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) + + (guint32)now.dwLowDateTime; + + /* + * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond, + * intervals. + */ + timestamp /= 10; + + /* + * Subtract difference, in microseconds, between January 1, 1601 + * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC. + */ + timestamp -= G_GUINT64_CONSTANT(11644473600000000); +#else + /* + * Current time, represented as seconds and microseconds since + * January 1, 1970, 00:00:00 UTC. + */ + gettimeofday(&now, NULL); + + /* + * Convert to delta in microseconds. + */ + timestamp = (guint64)(now.tv_sec) * 1000000 + + (guint64)(now.tv_usec); +#endif + block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32)); + options_length = 0; + if (isb_ifrecv != G_MAXUINT64) { + options_length += (guint32)(sizeof(struct option) + + sizeof(guint64)); + } + if (isb_ifdrop != G_MAXUINT64) { + options_length += (guint32)(sizeof(struct option) + + sizeof(guint64)); + } + /* OPT_COMMENT */ + options_length += pcapng_count_string_option(comment); + if (isb_starttime !=0) { + options_length += (guint32)(sizeof(struct option) + + sizeof(guint64)); /* ISB_STARTTIME */ + } + if (isb_endtime !=0) { + options_length += (guint32)(sizeof(struct option) + + sizeof(guint64)); /* ISB_ENDTIME */ + } + /* If we have options add size of end-of-options */ + if (options_length != 0) { + options_length += (guint32)sizeof(struct option); + } + block_total_length += options_length; + + isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE; + isb.block_total_length = block_total_length; + isb.interface_id = interface_id; + isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff); + isb.timestamp_low = (guint32)(timestamp & 0xffffffff); + if (!write_to_file(pfile, (const guint8*)&isb, sizeof(struct isb), bytes_written, err)) + return FALSE; + + /* write comment string if applicable */ + if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, + bytes_written, err)) + return FALSE; + + if (isb_starttime !=0) { + guint32 high, low; + + option.type = ISB_STARTTIME; + option.value_length = sizeof(guint64); + high = (guint32)((isb_starttime>>32) & 0xffffffff); + low = (guint32)(isb_starttime & 0xffffffff); + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err)) + return FALSE; + } + if (isb_endtime !=0) { + guint32 high, low; + + option.type = ISB_ENDTIME; + option.value_length = sizeof(guint64); + high = (guint32)((isb_endtime>>32) & 0xffffffff); + low = (guint32)(isb_endtime & 0xffffffff); + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err)) + return FALSE; + } + if (isb_ifrecv != G_MAXUINT64) { + option.type = ISB_IFRECV; + option.value_length = sizeof(guint64); + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err)) + return FALSE; + } + if (isb_ifdrop != G_MAXUINT64) { + option.type = ISB_IFDROP; + option.value_length = sizeof(guint64); + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + + if (!write_to_file(pfile, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err)) + return FALSE; + } + if (options_length != 0) { + /* write end of options */ + option.type = OPT_ENDOFOPT; + option.value_length = 0; + if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err)) + return FALSE; + } + + return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err); +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=8 tabstop=8 expandtab: + * :indentSize=8:tabSize=8:noTabs=true: + */ diff --git a/writecap/pcapio.h b/writecap/pcapio.h new file mode 100644 index 0000000000..9263024f02 --- /dev/null +++ b/writecap/pcapio.h @@ -0,0 +1,116 @@ +/* pcapio.h + * Declarations of our own routines for writing libpcap files. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * Derived from code in the Wiretap Library + * Copyright (c) 1998 by Gilbert Ramirez + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* Writing pcap files */ + +/** Write the file header to a dump file. + Returns TRUE on success, FALSE on failure. + Sets "*err" to an error code, or 0 for a short write, on failure*/ +extern gboolean +libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, + gboolean ts_nsecs, guint64 *bytes_written, int *err); + +/** Write a record for a packet to a dump file. + Returns TRUE on success, FALSE on failure. */ +extern gboolean +libpcap_write_packet(FILE* pfile, + time_t sec, guint32 usec, + guint32 caplen, guint32 len, + const guint8 *pd, + guint64 *bytes_written, int *err); + +/* Writing pcap-ng files */ + +/** Write a section header block (SHB) + * + */ +extern gboolean +pcapng_write_session_header_block(FILE* pfile, /**< Write information */ + const char *comment, /**< Comment on the section, Optinon 1 opt_comment + * A UTF-8 string containing a comment that is associated to the current block. + */ + const char *hw, /**< HW, Optinon 2 shb_hardware + * An UTF-8 string containing the description of the hardware used to create this section. + */ + const char *os, /**< Operating system name, Optinon 3 shb_os + * An UTF-8 string containing the name of the operating system used to create this section. + */ + const char *appname, /**< Application name, Optinon 4 shb_userappl + * An UTF-8 string containing the name of the application used to create this section. + */ + guint64 section_length, /**< Length of section */ + guint64 *bytes_written, /**< Number of written bytes */ + int *err /**< Error type */ + ); + +extern gboolean +pcapng_write_interface_description_block(FILE* pfile, + const char *comment, /* OPT_COMMENT 1 */ + const char *name, /* IDB_NAME 2 */ + const char *descr, /* IDB_DESCRIPTION 3 */ + const char *filter, /* IDB_FILTER 11 */ + const char *os, /* IDB_OS 12 */ + int link_type, + int snap_len, + guint64 *bytes_written, + guint64 if_speed, /* IDB_IF_SPEED 8 */ + guint8 tsresol, /* IDB_TSRESOL 9 */ + int *err); + +extern gboolean +pcapng_write_interface_statistics_block(FILE* pfile, + guint32 interface_id, + guint64 *bytes_written, + const char *comment, /* OPT_COMMENT 1 */ + guint64 isb_starttime, /* ISB_STARTTIME 2 */ + guint64 isb_endtime, /* ISB_ENDTIME 3 */ + guint64 isb_ifrecv, /* ISB_IFRECV 4 */ + guint64 isb_ifdrop, /* ISB_IFDROP 5 */ + int *err); + +extern gboolean +pcapng_write_enhanced_packet_block(FILE* pfile, + const char *comment, + time_t sec, guint32 usec, + guint32 caplen, guint32 len, + guint32 interface_id, + guint ts_mul, + const guint8 *pd, + guint32 flags, + guint64 *bytes_written, + int *err); + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ -- cgit v1.2.3