diff --git a/.editorconfig b/.editorconfig index 345d7cbe08..4e61cdbb6b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -33,7 +33,7 @@ indent_size = 4 [{capinfos,captype,mergecap,tfshark,tshark}.c] indent_size = 2 -[{dftest,echld_test,randpkt,trigcap}.c] +[{dftest,randpkt,trigcap}.c] indent_style = tab indent_size = tab diff --git a/.gitignore b/.gitignore index 1c319508d7..3d2b34fe31 100644 --- a/.gitignore +++ b/.gitignore @@ -85,7 +85,6 @@ depcomp dftest dumpcap editcap -echld_test exntest install-sh libtool diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c12d6eedd..bbe3d1f865 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1173,10 +1173,6 @@ if(NOT WIN32) add_custom_target(dumpabi DEPENDS dumpabi-libwireshark dumpabi-libwiretap dumpabi-libwsutil) endif() -if(ENABLE_ECHLD) - add_subdirectory( echld ) -endif() - if(BUILD_wireshark_gtk AND GTK_FOUND) add_subdirectory( ui/gtk ) endif() diff --git a/CMakeOptions.txt b/CMakeOptions.txt index 0a9ff5909c..b3765343e7 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -53,7 +53,6 @@ else() endif() # todo option(ENABLE_STATIC "Build a static version of Wireshark (not yet working)" OFF) -option(ENABLE_ECHLD "Enable echld support" OFF) option(ENABLE_PLUGINS "Build with plugins" ON) option(ENABLE_PLUGIN_IFDEMO "Build with plugin interface demo" OFF) option(ENABLE_EXTCAP "Build with extcap hooks" ON) diff --git a/Makefile.am b/Makefile.am index 7708681cb5..ce7adf7f32 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,12 +45,11 @@ bin_PROGRAMS = \ @dumpcap_bin@ \ @reordercap_bin@ \ @rawshark_bin@ \ - @sharkd_bin@ \ - @echld_test_bin@ + @sharkd_bin@ EXTRA_PROGRAMS = wireshark-gtk wireshark tshark tfshark capinfos captype \ editcap mergecap dftest randpkt text2pcap dumpcap reordercap \ - rawshark sharkd echld_test + rawshark sharkd # # Wireshark configuration files are put in $(pkgdatadir). @@ -718,30 +717,6 @@ dftest_LDADD = \ @PCAP_LIBS@ \ ${EPAN_EXTRA_LIBS} -echld_test_SOURCES = \ - echld_test.c \ - capture_opts.c \ - capture_stop_conditions.c \ - cfile.c \ - conditions.c \ - ringbuffer.c \ - sync_pipe_write.c - -echld_test_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS) - -echld_test_LDADD = \ - epan/libwireshark.la \ - echld/libechld.la \ - writecap/libwritecap.a \ - wsutil/libwsutil.la \ - @GLIB_LIBS@ \ - @PCAP_LIBS@ \ - @C_ARES_LIBS@ - -echld_test_DEPENDENCIES = \ - echld/libechld.la \ - epan/libwireshark.la - dumpcap_SOURCES = \ capture_opts.c \ capture_stop_conditions.c \ @@ -908,7 +883,6 @@ DIST_SUBDIRS = \ codecs \ doc \ epan \ - echld \ ui \ ui/cli \ ui/gtk \ @@ -932,7 +906,6 @@ SUBDIRS = \ epan \ capchild \ caputils \ - @echld_dir@ \ @plugins_dir@ \ packaging \ help \ diff --git a/configure.ac b/configure.ac index a984955523..d06eda760f 100644 --- a/configure.ac +++ b/configure.ac @@ -1876,26 +1876,6 @@ else fi AC_SUBST(sharkd_bin) -# Enable/disable echld -AC_ARG_ENABLE(echld, - AC_HELP_STRING( [--enable-echld], - [support echld (Experimental) @<:@default=no@:>@]), - have_echld=$enableval,have_echld=no) - -AM_CONDITIONAL(HAVE_ECHLD, test "x$have_echld" = "xyes") -if test "x$have_echld" = "xyes" -then - AC_DEFINE(HAVE_ECHLD, 1, [Define if echld is enabled]) - echld_test_bin="echld_test\$(EXEEXT)" - echld_dir="echld" -else - have_echld="no" - echld_test_bin="" - echld_dir="" -fi -AC_SUBST(echld_test_bin) -AC_SUBST(echld_dir) - # Enable/disable tfshark AC_ARG_ENABLE(tfshark, AC_HELP_STRING( [--enable-tfshark], @@ -3012,7 +2992,6 @@ AC_CONFIG_FILES( writecap/Makefile writecap/doxygen.cfg wsutil/Makefile - echld/Makefile _CUSTOM_AC_OUTPUT_ ) @@ -3161,7 +3140,6 @@ echo " Build sshdump : $enable_sshdump" echo " Build ciscodump : $enable_ciscodump" echo " Build randpktdump : $enable_randpktdump" echo " Build udpdump : $enable_udpdump" -echo " Build echld : $have_echld" echo "" echo " Save files as pcap-ng by default : $enable_pcap_ng_default" echo " Install dumpcap with capabilities : $setcap_message" diff --git a/doc/README.epan_child b/doc/README.epan_child deleted file mode 100644 index b77ae79c6e..0000000000 --- a/doc/README.epan_child +++ /dev/null @@ -1,251 +0,0 @@ -EPAN CHILDREN - - This document is a work in progress. - - This document describes a potential interface between a master process and one or more working children. - The goal is to have along-running epan process without the troubles of epan reinit (leaks, mis-reinits, ...). - Working children are spawn to capture or read files, then terminated. - The long running parent process initializes epan and forks children that require no further initialization to run. - - epan_child.h in the root directory describes the C interface. - - -Appendix A -ECHLD PROTOCOL INTERACTION DIAGRAMS - - parent child dumpcap - | | | - - -A.1. creation - new_child() ---------->| - |<-----HELLO------| - IDLE - - -A.2. keepalive -A.2.1 p->c - ANY_STATE - |-------PING----->| - |<------PONG------| - SAME_STATE -A.2.2 c->p - ANY_STATE - |<------PING------| - |-------PONG----->| - SAME_STATE - - -A.3. destruction -A.3.1 normal - ANY_STATE - |---CLOSE_CHILD-->| - |<----CLOSING-----| - DYING - |<-- SIG_CHLD - delete_child() - -A.3.2 fatal error - ANY_STATE - |<-----ERROR------| (fatal_err,"reason") - |<---SIG_CHLD - delete_child() - -A.3.3 crash - ANY_STATE - |<---SIG_CHLD - delete_child() - - - -A.4. getting current dir - ANY_STATE - |-------PWD------>| - |<------CWD-------| (dirname) - SAME_STATE - - -A.5. changing current dir -A.5.1 dir changed ok - ANY_STATE - |------CHDIR----->| (dirname) - |<------CWD-------| (dirname) - SAME_STATE -A.5.2 dir changed ko - ANY_STATE - |------CHDIR----->| (dirname) - |<-----ERROR------| (cannot_cd, "reason") - SAME_STATE - -A.6. listing current directory -A.6.1 file list ok - ANY_STATE - |----LIST_FILES-->| ("*.*"") - |<---FILE_INFO----| (filename, format, encap, num_pkts, ...); - |<---FILE_INFO----| (filename, format, encap, num_pkts, ...); - ..... - |<---FILE_INFO----| (filename, format, encap, num_pkts, ...); - SAME_STATE -A.6.2 file list ko - ANY_STATE - |----LIST_FILES-->| ("*.*"") - |<-----ERROR------| (no_files, "reason") - SAME_STATE - - -A.7. opening a file -A.7.1 opened ok - IDLE - |----OPEN_FILE---->| (filename, ...) - |<---FILE_OPENED---| (dirname) - READING -A.7.2 not opened - IDLE - |----OPEN_FILE---->| (filename, ...) - |<-----ERROR-------| (cannot_open, "reason") - IDLE - - -A.8. saving a file -A.8.1 save ok - READING/CAPTURING/DONE - |-----SAVE_FILE---->| ("new_filename",opts,...) - |<----FILE_SAVED----| (24, tree) - SAME_STATE - -A.8.1 save ko - READING/CAPTURING/DONE - |-----SAVE_FILE---->| ("new_filename",opts,...) - |<------ERROR-------| (cannot_save, "reason") - SAME_STATE - - -A.9. listing interfaces -A.9.1 intf list ok - IDLE - |--LIST_INTERFACES-->| ("*.*"") - | |-------????------>| - | |<------????-------| - |<--INTERFACE_INFO---| (name, param1=val1, ...) - |<--INTERFACE_INFO---| (name, param1=val1, ...) - ..... - |<--INTERFACE_INFO---| (name, param1=val1, ...) - IDLE -A.9.2 intf list ko - |--LIST_INTERFACES-->| ("*.*"") - | |-------????------>| - | |<------????-------| - |<------ERROR-------| (list_intf, "reason") - - -A.10. opening an interface -A.10.1 interface opened ok - IDLE - |---OPEN_INTERFACE-->| - | |-------????------>| - | |<------????-------| - |<--INTERFACE_OPENED-| - READY - -A.10.2 interface open failure - IDLE - |--OPEN_INTERFACE--->| - | |-------????------>| - | |<------????-------| - |<-------ERROR-------| (intf, "reason") - IDLE - - -A.11. starting capture -A.11.1 started capture ok - READY - |---START_CAPTURE--->| - | |-------????------>| - | |<------????-------| - |<-CAPTURE_STARTED---| - IN_CAPTURE -A.11.2 capture start failure - READY - |----START_CAPTURE-->| - | |-------????------>| - | |<------????-------| - |<-------ERROR-------| (cannot_start, "reason") - READY - -A.12. capturing or reading - IN_CAPTURE/READING - | |<------????-------| - |<----PACKET_SUM-----| (framenum, columns) - IN_CAPTURE - -A.13 getting packet details -A.13.1 just frame - IN_CAPTURE/READING - |----GET_PACKETS--->| (framelist) - |<-----PACKET-------| (1, tree) - |<-----BUFFER-------| ("1", tvb) - |<-----PACKET-------| (2, tree) - |<-----BUFFER-------| ("2", tvb) - SAME_STATE - -A.13.2 frame with reassembled buffer - IN_CAPTURE/READING/DONE - |----GET_PACKETS--->| (framelist) - |<-----PACKET-------| (framenum, tree) - |<-----BUFFER-------| ("framenum", tvb) - |<-----BUFFER-------| ("reas_num", tvb) - SAME_STATE - - -A.13.3 frame with known reassembled buffer - IN_CAPTURE/READING/DONE - |<-----PACKET-------| (framenum+N, tree) - |<-----BUFFER-------| ("framenum+N", tvb) - |<-----BUFFER-------| ("reas_num", NULL) - SAME_STATE - -A.13.4 buffer request (e.g. un-cached buffer) - IN_CAPTURE/READING/DONE - |------GET_BUF----->| (bufname) - |<-----BUFFER-------| (bufname, NULL) - SAME_STATE - -A.14 stpping capture - IN_CAPTURE - |---STOP_CAPTURE--->| - |<-CAPTURE_STOPPED--| - DONE - - -A.15. done reading - READING - |<-- EOF - |<--------EOF--------| - DONE - -A.16 setting a note -A.16.1 note set ok - IN_CAPTURE/READING/DONE - |----ADD_NOTE------>| (framenum,note) - |<----NOTE_ADDED----| - SAME_STATE -A.16.2 note set failure - IN_CAPTURE/READING/DONE - |----ADD_NOTE------>| (framenum,note) - |<----NOTE_ADDED----| - SAME_STATE - -A.17 applying a filter - IN_CAPTURE/READING/DONE - |---APPLY_FILTER--->| (dfilter_str) - |<---PACKET_LIST----| (Packet-Range) - |<---PACKET_LIST----| (Packet-Range) - SAME_STATE - - -A.18 setting a filter - IDLE - |-----SET_FILTER---->| (dfilter_str) - |<---FILTER_SET------| - IDLE - diff --git a/echld/CMakeLists.txt b/echld/CMakeLists.txt deleted file mode 100644 index 37db17fa68..0000000000 --- a/echld/CMakeLists.txt +++ /dev/null @@ -1,106 +0,0 @@ -# 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(CLEAN_FILES - echld-util.c - parent.c -) - -set(DIRTY_FILES - child.c - common.c - dispatcher.c -) - -set(echld_LIBS - ${GLIB2_LIBRARIES} -) - -set(ECHLD_FILES - ${CLEAN_FILES} - ${DIRTY_FILES} -) - -set_source_files_properties( - ${CLEAN_FILES} - PROPERTIES - COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" -) - - -add_library(echld ${LINK_MODE_LIB} - ${ECHLD_FILES} -) - -set(FULL_SO_VERSION "0.0.0") - -set_target_properties(echld PROPERTIES COMPILE_DEFINITIONS "WS_BUILD_DLL") -set_target_properties(echld PROPERTIES COMPILE_OPTIONS "${WS_WARNINGS_C_FLAGS}") -set_target_properties(echld PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") -set_target_properties(echld PROPERTIES VERSION ${FULL_SO_VERSION} SOVERSION 0) - -# discover and substitute list of include directories for ABI compatibility -# checks -#get_directory_property(INCLUDE_DIRS INCLUDE_DIRECTORIES) -#list(REMOVE_DUPLICATES INCLUDE_DIRS) -#string(REGEX REPLACE ";" "\n" INCLUDE_DIRS "${INCLUDE_DIRS}") -#configure_file(../abi-descriptor.template abi-descriptor.xml) - -# ABI compliance checker can be obtained from -# http://ispras.linux-foundation.org/index.php/ABI_compliance_checker -# Checked using version 1.21.12 -#file(GLOB HEADERS *.h) -#file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/abi-check-headers) -# -#file(COPY ${HEADERS} ../ws_symbol_export.h DESTINATION abi-check-headers) - -#add_custom_command(OUTPUT libwsutil.abi.tar.gz -# COMMAND cp ../config.h abi-check-headers/ -# COMMAND abi-compliance-checker -l libwsutil -v1 ${FULL_SO_VERSION} -# -relpath ${CMAKE_CURRENT_BINARY_DIR} -dump-abi abi-descriptor.xml -# || cat logs/libwsutil/[0-9]*/log.txt -# COMMAND cp abi_dumps/libwsutil/libwsutil_* libwsutil.abi.tar.gz -# COMMAND rm -rf abi-check-headers/* abi_dumps -# DEPENDS ${HEADERS} wsutil) -#add_custom_target(dumpabi-libwsutil DEPENDS libwsutil.abi.tar.gz) - -target_link_libraries(echld ${echld_LIBS}) - -if(NOT ${ENABLE_STATIC}) - install(TARGETS echld - LIBRARY DESTINATION lib - RUNTIME DESTINATION lib - ARCHIVE DESTINATION lib - ) -endif() - -# -# Editor modelines - http://www.wireshark.org/tools/modelines.html -# -# Local variables: -# c-basic-offset: 8 -# tab-width: 8 -# indent-tabs-mode: t -# End: -# -# vi: set shiftwidth=8 tabstop=8 noexpandtab: -# :indentSize=8:tabSize=8:noTabs=false: -# diff --git a/echld/Makefile.am b/echld/Makefile.am deleted file mode 100644 index 53d9360f3f..0000000000 --- a/echld/Makefile.am +++ /dev/null @@ -1,63 +0,0 @@ -# Makefile.am -# -# 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 $(top_srcdir)/Makefile.am.inc - -AM_CPPFLAGS = -DWS_BUILD_DLL $(INCLUDEDIRS) $(WS_CPPFLAGS) \ - $(GLIB_CFLAGS) - -lib_LTLIBRARIES = libechld.la - -libechld_la_SOURCES = \ - echld-util.c \ - dispatcher.c \ - child.c \ - parent.c \ - common.c \ - echld-int.h \ - echld-util.h \ - echld.h - -libechld_la_LDFLAGS = -version-info 0:0:0 @LDFLAGS_SHAREDLIB@ - -libechld_la_LIBADD = \ - ../caputils/libcaputils.a \ - ../epan/libwireshark.la \ - ../wsutil/libwsutil.la \ - ../wiretap/libwiretap.la \ - @GLIB_LIBS@ - -libechld_la_DEPENDENCIES = \ - ../caputils/libcaputils.a \ - ../epan/libwireshark.la \ - ../wiretap/libwiretap.la \ - ../wsutil/libwsutil.la - -EXTRA_DIST = \ - CMakeLists.txt - -CLEANFILES = \ - libechld.a \ - libechld.la \ - *~ - -MAINTAINERCLEANFILES = \ - Makefile.in - diff --git a/echld/child.c b/echld/child.c deleted file mode 100644 index 571d1578f8..0000000000 --- a/echld/child.c +++ /dev/null @@ -1,731 +0,0 @@ -/* echld_child.c - * epan working child internals - * Child process routines and definitions - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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 "echld-int.h" - -typedef struct _child { - child_state_t state; - - int pid; - int dispatcher_pid; - int chld_id; - int reqh_id; - echld_reader_t parent; - struct _fds { - int pipe_to_parent; - int pipe_from_dumpcap; - int pipe_to_dumpcap; - int file_being_read; - } fds; - - struct timeval started; - struct timeval now; - - child_encoder_t* enc; - child_decoder_t* dec; - - /* epan stuff */ - char* cf_name; - char* cfilter; - char* dfilter; - - -#if 0 - capture_file cfile; -#endif - dfilter_t* df; - -} echld_child_t; - -static echld_epan_stuff_t* stuff = NULL; - -static echld_child_t child; - -struct _st_map { - child_state_t id; - const char* str; -}; - - -#ifdef DEBUG_CHILD -static int debug_lvl = DEBUG_CHILD; -static FILE* debug_fp = NULL; -#define DBG_BUF_LEN 1024 - -#define DCOM() - -int child_debug(int level, const char* fmt, ...) { - va_list ap; - char str[DBG_BUF_LEN]; - - if (debug_lvl 5) { - *err = g_strdup_printf("invalid level=%d (min=0 max=5)",lvl); - return FALSE; - } - - debug_lvl = lvl; - DCOM(); - return TRUE; -} - - -static long dbg_resp(GByteArray* em, echld_msg_type_t t) { - long st = echld_write_frame(child.fds.pipe_to_parent, em, child.chld_id, t, child.reqh_id, NULL); - child_debug(1, "SND fd=%d ch=%d ty='%s' rh=%d msg='%s'", - child.fds.pipe_to_parent, child.chld_id, TY(t), child.reqh_id, (st>0?"ok":g_strerror(errno)) ); - return st; -} - -#define CHILD_DBG(attrs) ( child_debug attrs ) -#define CHILD_DBG_INIT() do { debug_fp = stderr; DCOM(); } while(0) -#define CHILD_DBG_START(fname) do { debug_fp = ws_fopen(fname,"a"); DCOM(); CHILD_DBG((0,"Log Started")); } while(0) -#define CHILD_RESP(BA,T) dbg_resp(BA,T) -#define CHILD_STATE(ST) do { DISP_DBG((0,"State %s => %s")) } while(0) -#else -#define CHILD_DBG(attrs) -#define CHILD_DBG_INIT() -#define CHILD_DBG_START(fname) -#define CHILD_RESP(BA,T) echld_write_frame(child.fds.pipe_to_parent,(BA),child.chld_id,T,child.reqh_id,NULL) -#endif - - -static struct timeval close_sleep_time; - - -static void sig_term(int sig _U_) { - CHILD_DBG((3,"Terminated, Closing")); - exit(0); -} - -extern void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id, echld_epan_stuff_t* es) { - stuff = es; - - close_sleep_time.tv_sec = CHILD_CLOSE_SLEEP_TIME / 1000000; - close_sleep_time.tv_usec = CHILD_CLOSE_SLEEP_TIME % 1000000; - - child.chld_id = chld_id; - child.state = IDLE; - child.pid = getpid(); - child.dispatcher_pid = getppid(); - child.reqh_id = reqh_id; - echld_init_reader( &(child.parent), pipe_from_parent,4096); - child.fds.pipe_to_parent = pipe_to_parent; - child.fds.pipe_from_dumpcap = -1; - child.fds.pipe_to_dumpcap = -1; - child.fds.file_being_read = -1; - gettimeofday(&child.started,NULL); - child.now.tv_sec = child.started.tv_sec; - child.now.tv_usec = child.started.tv_usec; - - echld_get_all_codecs(&(child.enc), &(child.dec), NULL, NULL); - - CHILD_DBG_INIT(); - CHILD_DBG((5,"Child Initialized ch=%d from=%d to=%d rq=%d",chld_id, pipe_from_parent, pipe_to_parent, reqh_id)); - - /*clear signal handlers */ - signal(SIGALRM,SIG_DFL); - signal(SIGTERM,sig_term); - signal(SIGPIPE,SIG_DFL); - signal(SIGINT,SIG_DFL); - signal(SIGABRT,SIG_DFL); - signal(SIGHUP,SIG_DFL); - - /* epan stuff */ -} - - - -void child_err(int e, unsigned reqh_id, const char* fmt, ...) { - size_t len= 1024; - gchar err_str[len]; - va_list ap; - static GByteArray* ba; - - va_start(ap, fmt); - g_vsnprintf(err_str,len,fmt,ap); - va_end(ap); - - CHILD_DBG((0,"error='%s'",err_str)); - - ba = child.enc->error(e, err_str); - echld_write_frame(child.fds.pipe_to_parent, ba, child.chld_id, ECHLD_ERROR, reqh_id, NULL); - g_byte_array_free(ba,TRUE); -} - - -static char* param_get_cwd(char** err ) { - char* pwd = getcwd(NULL, 128); - - if (!pwd) { - *err = g_strdup(g_strerror(errno)); - } - return pwd; -} - -static echld_bool_t param_set_cwd(char* val , char** err ) { - /* XXX SANITIZE */ - if (chdir(val) != 0) { - *err = g_strdup_printf("cannot chdir reas='%s'",g_strerror(errno)); - return FALSE; - } - - return TRUE; -} - - -static unsigned packet_count = 0; -static char* param_get_packet_count(char** err) { - - if (child.state != CAPTURING && child.state != READING) { - *err = g_strdup("Must be reading or in-capture for packet_count"); - return NULL; - } - return g_strdup_printf("%d",packet_count); -} - - - -static echld_bool_t param_set_dfilter(char* val , char** err) { - dfilter_t *dfn = NULL; - - if (child.state != IDLE && child.state != DONE ) { - *err = g_strdup("Only while idle or done"); - return FALSE; - } else { - if ( dfilter_compile(val, &dfn, err) ) { - if (child.dfilter) g_free(child.dfilter); - if (child.df) dfilter_free(child.df); - child.df = dfn; - child.dfilter = g_strdup(val); - return TRUE; - } else { - return FALSE; - } - } -} - -static char* param_get_dfilter(char** err _U_) { return g_strdup(child.dfilter ? child.dfilter : ""); } - -char* param_profile = NULL; - -static echld_bool_t param_set_profile(char* val , char** err ) { - - if (child.state != IDLE) { - *err = g_strdup_printf("Cannot set Profile \"%s\", too late.", val); - return FALSE; - } - - if (profile_exists (val, FALSE)) { - set_profile_name (val); - if (param_profile) g_free(param_profile); - param_profile = g_strdup(val); - return TRUE; - } else { - *err = g_strdup_printf("Configuration Profile \"%s\" does not exist", val); - return FALSE; - } -} - -static char* param_get_profile(char** err _U_) { return g_strdup(param_profile ? param_profile : ""); } - -static char* param_get_file_list(char** err) { - GError* gerror = NULL; - GDir* dir = g_dir_open(".", 0, &gerror); - GString* str = g_string_new("{ what='file_list', files=["); - const char* file; - - if (gerror) { - *err = g_strdup_printf("Failed to open curr dir reason='%s'",gerror->message); - return NULL; - } - - while(( file = g_dir_read_name(dir) )) { - g_string_append_printf(str,"{filename='%s'},\n",file); - } - g_dir_close(dir); - - g_string_truncate(str, str->len-2); /* ',\n' */ - g_string_append(str, "]}"); - - return g_string_free(str,FALSE); -} - -#ifdef PCAP_NG_DEFAULT -static int out_file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; -#else -static int out_file_type = WTAP_FILE_TYPE_SUBTYPE_PCAP; -#endif - -static echld_bool_t param_set_out_file_type(char* val, char** err) { - int oft = wtap_short_string_to_file_type_subtype(val); - - if (oft < 0) { - *err = g_strdup_printf("\"%s\" isn't a valid capture file type", val); - return FALSE; - } else { - out_file_type = oft; - return TRUE; - } -} - -static char* param_get_out_file_type(char** err _U_) { - return g_strdup_printf("%s(%d): %s", - wtap_file_type_subtype_short_string(out_file_type), - out_file_type, wtap_file_type_subtype_string(out_file_type)); -} - - -static echld_bool_t param_set_add_hosts_file(char* val, char** err) { - if (add_hosts_file(val)) { - return TRUE; - } else { - *err = g_strdup_printf("Can't read host entries from \"%s\"",val); - return FALSE; - } -} - -PARAM_BOOL(quiet,FALSE); -PARAM_BOOL(start_capture,FALSE); -PARAM_BOOL(push_details,FALSE); -PARAM_BOOL(print_hex,FALSE); - -static char* param_get_params(char** err _U_); - -static param_t child_params[] = { -#ifdef DEBUG_CHILD - PARAM(dbg_level,"Debug Level (0set_param && child.dec->set_param(b,len,¶m,&value) ) { - if (! paramset_apply_set (child_params, param, value, &err) ) { - child_err(ECHLD_CANNOT_SET_PARAM,reqh_id,"%s",err); - g_free(err); - return 0; - } - - gba = child.enc->param(param,value); - CHILD_RESP(gba,ECHLD_PARAM); - g_byte_array_free(gba,TRUE); - CHILD_DBG((1,"Set Param: param='%s' value='%s'",param,value)); - - break; - } else { - goto misencoded; - } - } - case ECHLD_GET_PARAM: { - char* param; - if ( child.dec->get_param && child.dec->get_param(b,len,¶m) ) { - char* val; - - if (! (val = paramset_apply_get (child_params, param, &err)) ) { - child_err(ECHLD_CANNOT_GET_PARAM,reqh_id,"%s",err); - g_free(err); - return 0; - } - - gba = child.enc->param(param,val); - CHILD_RESP(gba,ECHLD_PARAM); - g_byte_array_free(gba,TRUE); - CHILD_DBG((2,"Get Param: param='%s' value='%s'",param,val)); - break; - } else { - goto misencoded; - } - } - case ECHLD_CLOSE_CHILD: - CHILD_RESP(NULL,ECHLD_CLOSING); - CHILD_DBG((3,"Closing")); - select(0,NULL,NULL,NULL,&close_sleep_time); - CHILD_DBG((1,"Bye")); - exit(0); - break; - case ECHLD_OPEN_FILE: { - char* filename; - if (child.state != IDLE) goto wrong_state; - - if ( child.dec->open_file(b,len,&filename) ) { - child_open_file(filename); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode open_file"); - } - break; - } - case ECHLD_OPEN_INTERFACE: { - char* intf; - char* pars; - - if (child.state != IDLE) goto wrong_state; - - if ( child.dec->open_interface(b,len,&intf,&pars) ) { - child_open_interface(intf,pars); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id, "cannot decode open_interface"); - } - break; - } - case ECHLD_START_CAPTURE:{ - if (child.state != READY) goto wrong_state; - child_start_capture(); - break; - } - case ECHLD_STOP_CAPTURE: { - if (child.state != CAPTURING) goto wrong_state; - child_stop_capure(); - break; - } - case ECHLD_GET_SUM: { - char* range; - - if (child.state != CAPTURING && child.state != READING && child.state != DONE) goto wrong_state; - - if ( child.dec->get_sum(b,len,&range) ) { - child_get_summary(range); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_summary"); - } - break; - } - case ECHLD_GET_TREE:{ - char* range; - - if (child.state != CAPTURING && child.state != READING && child.state != DONE) goto wrong_state; - - if ( child.dec->get_tree(b,len,&range) ) { - child_get_tree(range); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_tree"); - } - break; - } - case ECHLD_GET_BUFFER:{ - char* name; - - if (child.state != CAPTURING && child.state != READING && child.state != DONE) goto wrong_state; - - if ( child.dec->get_buffer(b,len,&name) ) { - child_get_buffer(name); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_buffer"); - } - break; - } - case ECHLD_ADD_NOTE: { - int framenum; - char* note; - - if (child.state != CAPTURING && child.state != READING && child.state != DONE) goto wrong_state; - - if ( child.dec->add_note(b,len,&framenum,¬e) ) { - child_add_note(framenum,note); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_buffer"); - } - break; - } - case ECHLD_APPLY_FILTER: { - char* filter; - - if (child.state != DONE) goto wrong_state; - - if ( child.dec->apply_filter(b,len,&filter) ) { - child_apply_filter(filter); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode apply_filter"); - } - break; - } - case ECHLD_SAVE_FILE: { - char* filename; - char* pars; - - if (child.state != DONE) goto wrong_state; - - if ( child.dec->save_file(b,len,&filename,&pars) ) { - child_save_file(filename,pars); - } else { - child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode save_file"); - } - break; - } - default: - child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"wrong message: chld_id=%d msg_type='%s'",chld_id,TY(type)); - break; - } - - return 0; - - misencoded: - /* dump the misencoded message (b,blen) */ - child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"misencoded msg msg_type='%s'",TY(type)); - return 0; - - wrong_state: - child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"unexpected message: received in wrong state='%s', msg_type='%s'",ST(child.state),TY(type)); - return 0; - -} - -static int child_dumpcap_read(void) { - /* this folk manages the reading of dumpcap's pipe - * it has to read interface descriptions when doing so - * and managing capture during capture - */ - CHILD_DBG((2,"child_dumpcap_read")); - return FALSE; -} - -static void child_file_read(void) { - -} - -int echld_child_loop(void) { - int disp_from = child.parent.fd; - int disp_to = child.fds.pipe_to_parent; - -#ifdef DEBUG_CHILD - int step = 0; -#endif - - CHILD_DBG((0,"entering child_loop()")); - - do { - fd_set rfds; - fd_set wfds; - fd_set efds; - struct timeval timeout; - int nfds; - gboolean captured = FALSE; - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&efds); - - FD_SET(disp_from,&rfds); - FD_SET(disp_from,&efds); - FD_SET(disp_to,&efds); - - - if (child.fds.pipe_from_dumpcap > 0) { - FD_SET(child.fds.pipe_from_dumpcap,&rfds); - } - -#ifdef DEBUG_CHILD - if (step <= 20) CHILD_DBG((4,"child_loop: select()ing step=%d",step++)); -#endif - timeout.tv_sec = 0; - timeout.tv_usec = 999999; - - nfds = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout); -#ifdef DEBUG_CHILD - if (step <= 20) CHILD_DBG((4,"child_loop: select()ed nfds=%d",nfds)); -#endif - - if ( FD_ISSET(disp_from,&efds) ) { - CHILD_DBG((0,"Broken Parent Pipe 'From' step=%d",step)); - break; - } - - if ( FD_ISSET(disp_to,&efds) ) { - CHILD_DBG((0,"Broken Parent Pipe 'To' step=%d",step)); - break; - } - - if (child.fds.pipe_from_dumpcap > 0 && FD_ISSET(child.fds.pipe_from_dumpcap,&efds) ) { - CHILD_DBG((0,"Broken Dumpcap Pipe step=%d",step)); - break; - } - - if (FD_ISSET(disp_from, &rfds)) { - long st = echld_read_frame(&(child.parent), child_receive, &child); - -#ifdef DEBUG_CHILD - step = 0; -#endif - - if (st < 0) { - CHILD_DBG((0,"Read Frame Failed step=%d",step)); - return (int)st; - } - } - - if (child.fds.pipe_from_dumpcap > 0 && FD_ISSET(child.fds.pipe_from_dumpcap,&rfds) ) { - -#ifdef DEBUG_CHILD - step = 0; -#endif - captured = child_dumpcap_read(); - } - - if ( child.state == READING || captured ) { - child_file_read(); - } - } while(1); - - - CHILD_RESP(NULL,ECHLD_CLOSING); - CHILD_DBG((3,"Closing")); - return 222; -} - - diff --git a/echld/common.c b/echld/common.c deleted file mode 100644 index 564a48e29e..0000000000 --- a/echld/common.c +++ /dev/null @@ -1,922 +0,0 @@ -/* echld_common.h - * common functions of ECHLD - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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 "echld-int.h" - -#ifdef DEBUG_BASE - -static int dbg_level = DEBUG_BASE; -static FILE* dbg_fp; -static const char* dbg_prefix; - -static void common_dbg(int level, const char* fmt, ...) { - va_list ap; - char str[1024]; - - if (level > dbg_level) return; - - va_start(ap,fmt); - g_vsnprintf(str,1024,fmt,ap); - va_end(ap); - - if (dbg_fp) { - fprintf(dbg_fp,"%s: level=%d msg='%s'\n",dbg_prefix,level,str); - fflush(dbg_fp); - } -} - -extern void echld_common_set_dbg(int level, FILE* fp, const char* prefix) { - dbg_prefix = prefix; - dbg_level = level; - dbg_fp = fp; -} -#define DBG(attrs) ( common_dbg attrs ) -#else -#define DBG(attrs) -#endif - - -struct _st_map -{ - child_state_t id; - const char* str; -}; - -static struct _st_map st_map[] = { - { FREE, "FREE"}, - { CREATING, "CREATING"}, - { IDLE, "IDLE"}, - { READY, "READY"}, - { READING, "READING"}, - { CAPTURING, "CAPTURING"}, - { DONE, "DONE"}, - { CLOSING, "CLOSING"}, - { CLOSED, "CLOSED"}, - { ERRORED, "ERRORED"}, - {0,NULL} -}; - -const char* echld_state_str(child_state_t id) { - int i = 0; - - for (;st_map[i].str;i++) { - if (id == st_map[i].id) return st_map[i].str; - } - - return "UNKNOWN"; -} - - -struct _t_map -{ - echld_msg_type_t type; - const char* str; -}; - -static struct _t_map t_map[] = { - {ECHLD_ERROR,"ERROR"}, - {ECHLD_TIMED_OUT,"TIMED_OUT"}, - {ECHLD_NEW_CHILD,"NEW_CHILD"}, - {ECHLD_HELLO,"HELLO"}, - {ECHLD_CHILD_DEAD,"CHILD_DEAD"}, - {ECHLD_CLOSE_CHILD,"CLOSE_CHILD"}, - {ECHLD_CLOSING,"CLOSING"}, - {ECHLD_SET_PARAM,"SET_PARAM"}, - {ECHLD_GET_PARAM,"GET_PARAM"}, - {ECHLD_PARAM,"PARAM"}, - {ECHLD_PING,"PING"}, - {ECHLD_PONG,"PONG"}, - {ECHLD_OPEN_FILE,"OPEN_FILE"}, - {ECHLD_FILE_OPENED,"FILE_OPENED"}, - {ECHLD_OPEN_INTERFACE,"OPEN_INTERFACE"}, - {ECHLD_INTERFACE_OPENED,"INTERFACE_OPENED"}, - {ECHLD_START_CAPTURE,"START_CAPTURE"}, - {ECHLD_CAPTURE_STARTED,"CAPTURE_STARTED"}, - {ECHLD_NOTIFY,"NOTIFY"}, - {ECHLD_GET_SUM,"GET_SUM"}, - {ECHLD_PACKET_SUM,"PACKET_SUM"}, - {ECHLD_GET_TREE,"GET_TREE"}, - {ECHLD_TREE,"TREE"}, - {ECHLD_GET_BUFFER,"GET_BUFFER"}, - {ECHLD_BUFFER,"BUFFER"}, - {ECHLD_EOF,"EOF"}, - {ECHLD_STOP_CAPTURE,"STOP_CAPTURE"}, - {ECHLD_CAPTURE_STOPPED,"CAPTURE_STOPPED"}, - {ECHLD_ADD_NOTE,"ADD_NOTE"}, - {ECHLD_NOTE_ADDED,"NOTE_ADDED"}, - {ECHLD_APPLY_FILTER,"APPLY_FILTER"}, - {ECHLD_PACKET_LIST,"PACKET_LIST"}, - {ECHLD_SAVE_FILE,"SAVE_FILE"}, - {ECHLD_FILE_SAVED,"FILE_SAVED"}, - {ECHLD_NULL,NULL} -}; - -const char* echld_msg_type_str(echld_msg_type_t id) { - int i = 0; - - for (;t_map[i].str;i++) { - if (id == t_map[i].type) return t_map[i].str; - } - - return "UNKNOWN"; -} - - -/** - the "epan pipe" protocol -**/ - -typedef void (*reader_realloc_t)(echld_reader_t*, size_t); - -static void child_realloc_buff(echld_reader_t* r, size_t needed) { - size_t a = r->actual_len; - size_t s = r->len; - long rp_off = r->rp - r->data; - - DBG((2,"REALLOC BUFF needed=%d",needed)); - - if ( a < (s + needed) ) { - guint8* data = r->data; - - do { - a *= 2; - } while( a < (s + needed) ); - - data = (guint8*)g_realloc(data,a); - - r->actual_len = a; - r->len = s; - r->data = data; - r->wp = data + s; - r->rp = data + rp_off; - } -} - -static reader_realloc_t reader_realloc_buff = child_realloc_buff; - -#ifdef PARENT_THREADS -static void parent_realloc_buff(echld_reader_t* b, size_t needed) { - /* parent thread: obtain malloc mutex */ - child_realloc_buff(b,needed); - /* parent thread: release malloc mutex */ -} -#endif - - - -void echld_reset_reader(echld_reader_t* r, int fd, size_t initial) { - r->fd = fd; - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - fprintf(stderr, "Unable to set non blocking on file...\n"); - return; - } - - if (r->data == NULL) { - r->actual_len = initial; - r->data =(guint8*) g_malloc0(initial); - r->wp = r->data; - r->rp = r->data; - r->len = 0; - } else { - r->wp = r->data; - r->rp = r->data; - r->len = 0; - } -} - -void echld_init_reader(echld_reader_t* r, int fd, size_t initial) { - echld_reset_reader(r,fd,initial); -} - - - -void free_reader(echld_reader_t* r) { - g_free(r->data); -} - -static long reader_readv(echld_reader_t* r, size_t len) { - struct iovec iov; - long nread; - - DBG((2,"READV needed=%d",len)); - - if ( (r->actual_len - r->len) < len ) - reader_realloc_buff(r, len); - - iov.iov_base = r->wp; - iov.iov_len = len; - - nread = readv(r->fd, &iov, 1); - - DBG((2,"READV nread=%d msg='%s'",nread, (nread<0) ? g_strerror(errno) : "-" )); - - if (nread >= 0) { - r->wp += nread; - r->len += nread; - } - - if (errno == EAGAIN) return 0; - - return nread; -}; - - -long echld_read_frame(echld_reader_t* r, read_cb_t cb, void* cb_data) { - DBG((4,"READ = echld_read_frame fd=%d",r->fd)); - - /* it will use shared memory instead of inband communication */ - do { - hdr_t* h = (hdr_t*)r->rp; - long nread; - size_t fr_len = 0; - size_t missing; - - DBG((5,"READ reader_len=%d",r->len)); - - if ( r->len < ECHLD_HDR_LEN) { - /* read the header */ - goto incomplete_header; - } else if ( ! reader_has_frame(r) ) { - /* read the (rest of) the frame */ - goto incomplete_frame; - } - - DBG((5,"READ we've got a frame! fr_len=%d ch=%d t='%c' rh=%d",fr_len, h->h.chld_id, HDR_TYPE(h), h->h.reqh_id)); - - - cb( &(r->rp[sizeof(hdr_t)]), HDR_LEN(h), h->h.chld_id, HDR_TYPE(h), h->h.reqh_id, cb_data); - - r->len = 0; - r->wp = r->data; - r->rp = r->data; - - DBG((5,"READ consumed frame!")); - - goto again; - - incomplete_header: - missing = ECHLD_HDR_LEN - (r->len); - DBG((5,"READ incomplete_header missing=%d",missing)); - - nread = reader_readv(r,missing); - - - if (nread < 0 && errno != EAGAIN) { - goto kaput; /*XXX*/ - } else if (nread < (long)missing) { - goto again; - } else { - goto incomplete_frame; - } - - incomplete_frame: - fr_len = HDR_LEN(h) + ECHLD_HDR_LEN; - missing = fr_len - r->len; - - DBG((5,"READ incomplete_frame fr_len=%d missing=%d",fr_len ,missing)); - - if (missing) { - nread = reader_readv(r,missing); - - if (nread < 0 && errno != EAGAIN) { - goto kaput; /*XXX*/ - } else if (nread < (long)missing) { - goto again; - } - } - - } while(1); - - DBG((1,"READ incomplete_frame Cannot happen")); - - return 0; - again: return 1; - kaput: return -1; -} - -long echld_write_frame(int fd, GByteArray* ba, guint16 chld_id, echld_msg_type_t type, guint16 reqh_id, void* data _U_) { - hdr_t h; - struct iovec iov[2]; - int iov_cnt = 1; - - - h.h.type_len = (type<<24) | ((ba?ba->len:0) & 0x00ffffff) ; - h.h.chld_id = chld_id; - h.h.reqh_id = reqh_id; - - iov[0].iov_base = &h; - iov[0].iov_len = 8; - - if ( ba && ba->len > 0 ) { - iov[1].iov_base = ba->data; - iov[1].iov_len = ba->len; - iov_cnt++; - } - - return (long) writev(fd, iov, iov_cnt); -} - -/* paramset management */ - -param_t* paramset_find (param_t* paramsets, char* name, char** err) { - int i; - for (i = 0; paramsets[i].name != NULL;i++) { - if (strcmp(name,paramsets[i].name) == 0 ) return &(paramsets[i]); - } - - *err = g_strdup_printf("Could not find param='%s'",name); - return NULL; -} - -echld_bool_t paramset_apply_set (param_t* paramsets, char* name, char* val, char** err) { - param_t* p = paramset_find(paramsets,name,err); - - if ( !p ) return FALSE; - if ( ! p->set ) { - *err = g_strdup_printf("Cannot set RO param='%s'",name); - return FALSE; - } - - return p->set(val,err); -} - -char* paramset_apply_get (param_t* paramsets, char* name, char** err) { - param_t* p = paramset_find(paramsets,name,err); - - if ( !p ) return NULL; - - if ( ! p->get ) { - *err = g_strdup_printf("Cannot get WO param='%s'",name); - return NULL; - } - - return p->get(err); -} - -echld_bool_t paramset_apply_em(param_t* paramset, enc_msg_t* em, char** err) { - GByteArray* ba = (GByteArray*)em; - char* p = (char*) ba->data; - int tot_len = ba->len; - long rem = tot_len; - p[rem-1] = '\0'; /* make sure last char is null */ - - while(rem > 2) { - char* param = p; - long param_len = strlen(param)+1; - char* value = p + param_len; - long value_len; - - rem -= param_len; - - if (rem < 0) { - *err = g_strdup_printf("Malformed msg param len invalid"); - return FALSE; - } - - value_len = strlen(value)+1; - - rem -= value_len; - p = value + value_len; - - if (rem < 0) { - *err = g_strdup_printf("Malformed msg value len invalid"); - return FALSE; - } - - if (! paramset_apply_set(paramset,param,value,err)) - return FALSE; - } - - return TRUE; -} - -char* paramset_get_params_list(param_t* paramsets,const char* fmt) { - param_t* p = paramsets; - GString* str = g_string_new(""); - - for (;p->name;p++) { - g_string_append_printf(str,fmt, - p->name, - ((p->get && p->set)?"rw":(p->get?"ro":"wo")), - p->desc); - } - - return g_string_free(str,FALSE); -} - - - - -/* encoders and decoders */ - - - - - -/* binary encoders and decoders used for parent->child communication */ - -static enc_msg_t* str_enc(const char* s) { - GByteArray* ba = g_byte_array_new(); - g_byte_array_append(ba,s,(guint)(strlen(s)+1)); - return (enc_msg_t*)ba; -} - -static gboolean str_dec(guint8* b, size_t bs, char** text) { - guint8* end = b+bs; - b[bs-1] = '\0'; /* null terminate the buffer to avoid strlen running */ - *text = (char*)b; - if (b+(strlen(b)+1) > end) return FALSE; - return TRUE; -} - -static gboolean str_deca(enc_msg_t* ba, char** text) { - return str_dec(ba->data,ba->len,text); -} - -static enc_msg_t* int_str_enc(int i, const char* s) { - GByteArray* ba = g_byte_array_new(); - g_byte_array_append(ba,(guint8*)&i,sizeof(int)); - g_byte_array_append(ba,s,(guint)(strlen(s)+1)); - return (enc_msg_t*)ba; -} - -static gboolean int_str_dec(guint8* b, size_t bs, int* ip, char** text) { - guint8* end = b+bs; - b[bs-1] = '\0'; /* null terminate the buffer to avoid strlen running */ - - if ((sizeof(int)) > bs) return FALSE; - *ip = *((int*)b); - b += (sizeof(int)); - *text = (char*)b; - if ((b += (strlen(b)+1)) > end) return FALSE; - - return TRUE; -} - -static gboolean int_str_deca(enc_msg_t* ba, int* ip, char** text) { - return int_str_dec(ba->data,ba->len,ip,text); -} - -static enc_msg_t* int_enc(int i) { - GByteArray* ba = g_byte_array_new(); - g_byte_array_append(ba,(guint8*)&i,sizeof(int)); - return (enc_msg_t*)ba; -} - -static gboolean int_dec(guint8* b, size_t bs, int* ip) { - if ((sizeof(int)) > bs) return FALSE; - *ip = *((int*)b); - return TRUE; -} - -static gboolean int_deca(enc_msg_t* ba, int* ip) { - return int_dec(ba->data,ba->len,ip); -} - -static enc_msg_t* x2str_enc(const char* s1, const char* s2) { - GByteArray* ba = g_byte_array_new(); - g_byte_array_append(ba,s1,(guint)(strlen(s1)+1)); - g_byte_array_append(ba,s2,(guint)(strlen(s2)+1)); - return (enc_msg_t*)ba; -} - -static gboolean x2str_dec(guint8* b, size_t blen, char** str1, char** str2) { - guint8* end = b+blen; - b[blen-1] = '\0'; /* null terminate the buffer to avoid strlen running */ - - *str1 = (char*)b; - if ((b += (strlen(b)+1)) > end) return FALSE; - *str2 = (char*)(b); - if ((b += (strlen(b)+1)) > end) return FALSE; - return TRUE; -} - -static gboolean x2str_deca(enc_msg_t* ba, char** str1, char** str2) { - return x2str_dec(ba->data,ba->len,str1,str2); -} - -static gboolean int_3str_dec (guint8* b, size_t len, int* i, char** s1, char** s2, char** s3) { - guint8* end = b+len; - b[len-1] = '\0'; - - if ((sizeof(int)) > len) return FALSE; - *i = *((int*)b); - b += sizeof(int); - - *s1 = (char*)b; - if ((b += (strlen(b)+1)) > end) return FALSE; - *s2 = (char*)(b); - if ((b += (strlen(b)+1)) > end) return FALSE; - *s3 = (char*)b; - if ((b += (strlen(b)+1)) > end) return FALSE; - return TRUE; -} - -static enc_msg_t* int_3str_enc(int i, const char* s1, const char* s2, const char* s3) { - GByteArray* ba = g_byte_array_new(); - g_byte_array_append(ba,(guint8*)&i,sizeof(int)); - g_byte_array_append(ba,s1,(guint)(strlen(s1)+1)); - g_byte_array_append(ba,s2,(guint)(strlen(s2)+1)); - g_byte_array_append(ba,s3,(guint)(strlen(s3)+1)); - return (enc_msg_t*)ba; -} - -static gboolean int_3str_deca (enc_msg_t* e, int* i, char** s1, char** s2, char** s3) { - return int_3str_dec(e->data,e->len,i,s1,s2,s3); -} - -static gboolean x3str_dec (guint8* b, size_t len, char** s1, char** s2, char** s3) { - guint8* end = b+len; - b[len-1] = '\0'; - - - *s1 = (char*)b; - if ((b += (strlen(b)+1)) > end) return FALSE; - *s2 = (char*)(b); - if ((b += (strlen(b)+1)) > end) return FALSE; - *s3 = (char*)b; - if ((b += (strlen(b)+1)) > end) return FALSE; - return TRUE; -} - -static gboolean x3str_deca (enc_msg_t* e, char** s1, char** s2, char** s3) { - return x3str_dec(e->data,e->len,s1,s2,s3); -} - - -static enc_msg_t* x3str_enc(const char* s1, const char* s2, const char* s3) { - GByteArray* ba = g_byte_array_new(); - g_byte_array_append(ba,s1,(guint)(strlen(s1)+1)); - g_byte_array_append(ba,s2,(guint)(strlen(s2)+1)); - g_byte_array_append(ba,s3,(guint)(strlen(s3)+1)); - return (enc_msg_t*)ba; -} - -static echld_parent_encoder_t parent_encoder = { - int_str_enc, - str_enc, - x2str_enc, - int_enc, - str_enc, - x2str_enc, - str_enc, - str_enc, - str_enc, - int_str_enc, - str_enc, - x2str_enc -}; - -echld_parent_encoder_t* echld_get_encoder(void) { - return &parent_encoder; -} - -static child_decoder_t child_decoder = { - int_str_dec, - x2str_dec, - str_dec, - int_dec, - str_dec, - x2str_dec, - str_dec, - str_dec, - str_dec, - int_str_dec, - str_dec, - x2str_dec -}; - -static child_encoder_t child_encoder = { - int_str_enc, - str_enc, - x2str_enc, - str_enc, - int_str_enc, - int_str_enc, - int_3str_enc, - x3str_enc -}; - -static parent_decoder_t parent_decoder = { - int_str_deca, - str_deca, - x2str_deca, - str_deca, - int_str_deca, - int_str_deca, - int_3str_deca, - x3str_deca -}; - -void echld_get_all_codecs( child_encoder_t **e, child_decoder_t **d, echld_parent_encoder_t **pe, parent_decoder_t** pd) { - e && (*e = &child_encoder); - d && (*d = &child_decoder); - pe && (*pe = &parent_encoder); - pd && (*pd = &parent_decoder); -} - - - -/* output encoders, used in the switch */ - - -static char* packet_summary_json(GByteArray* ba _U_) { - /* dummy */ - return g_strdup("{type='packet_summary', packet_summary={}"); -} - -static char* tree_json(GByteArray* ba _U_) { - /* dummy */ - return g_strdup("{type='tree', tree={}"); -} - -char* tvb_json(GByteArray* ba _U_, tvb_t* tvb _U_, const char* name) { - /* dummy */ - return g_strdup_printf("{type='buffer', buffer={name='%s', range='0-2', data=[0x12,0xff] }",name); -} - -static char* error_json(GByteArray* ba) { - char* s = (char*)(ba->data + sizeof(int)); - int i = *((int*)s); - - s = g_strdup_printf("{type='error', error={errnum=%d, message='%s'}}",i,s); - - return s; -} - -static char* child_dead_json(GByteArray* ba) { - char* s = (char*)(ba->data + sizeof(int)); - int i = *((int*)s); - - s = g_strdup_printf("{type='child_dead', child_dead={childnum=%d, message='%s'}}",i,s); - - return s; -} - -static char* closing_json(GByteArray* ba) { - char* s = (char*)(ba->data); - s = g_strdup_printf("{type='closing', closing={reason='%s'}}",s); - - return s; -} - - - -static char* note_added_json(GByteArray* ba) { - char* s = (char*)(ba->data); - s = g_strdup_printf("{ type='note_added', note_added={msg='%s'}}",s); - - return s; -} - -static char* packet_list_json(GByteArray* ba _U_) { - return g_strdup("{}"); -} - -static char* file_saved_json(GByteArray* ba) { - char* s = (char*)(ba->data); - - s = g_strdup_printf("{ type='file_saved', file_saved={msg='%s'}}",s); - - return s; -} - - - -static char* param_set_json(GByteArray* ba) { - char* s1 = (char*)(ba->data); - char* s2 = ((char*)(ba->data)) + strlen(s1); - - s1 = g_strdup_printf("{type='param_set', param_set={param='%s' value='%s'}}",s1,s2); - - - return s1; -} - -static char* set_param_json(GByteArray* ba) { - char* s1 = (char*)(ba->data); - char* s2 = ((char*)(ba->data)) + strlen(s1); - - s1 = g_strdup_printf("{type='set_param', set_param={param='%s' value='%s'}}",s1,s2); - - - return s1; -} - -static char* get_param_json(GByteArray* ba) { - char* s1 = (char*)(ba->data); - - s1 = g_strdup_printf("{type='get_param', get_param={param='%s'}}",s1); - - - return s1; -} - -static char* file_opened_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* open_file_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* open_interface_json(GByteArray* ba _U_) { - return g_strdup(""); -} - - -static char* interface_opened_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* notify_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* get_tree_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* get_sum_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* get_buffer_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* buffer_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* add_note_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* apply_filter_json(GByteArray* ba _U_) { - return g_strdup(""); -} - -static char* save_file_json(GByteArray* ba _U_) { - return g_strdup(""); -} - - -/* this to be used only at the parent */ -static char* decode_json(echld_msg_type_t type, enc_msg_t* m) { - GByteArray* ba = (GByteArray*)m; - - switch(type) { - case ECHLD_ERROR: return error_json(ba); - case ECHLD_TIMED_OUT: return g_strdup("{type='timed_out'}"); - case ECHLD_NEW_CHILD: return g_strdup("{type='new_child'}"); - case ECHLD_HELLO: return g_strdup("{type='helo'}"); - case ECHLD_CHILD_DEAD: return child_dead_json(ba); - case ECHLD_CLOSE_CHILD: return g_strdup("{type='close_child'}"); - case ECHLD_CLOSING: return closing_json(ba); - case ECHLD_SET_PARAM: return set_param_json(ba); - case ECHLD_GET_PARAM: return get_param_json(ba); - case ECHLD_PARAM: return param_set_json(ba); - case ECHLD_PING: return g_strdup("{type='ping'}"); - case ECHLD_PONG: return g_strdup("{type='pong'}"); - case ECHLD_OPEN_FILE: return open_file_json(ba); - case ECHLD_FILE_OPENED: return file_opened_json(ba); - case ECHLD_OPEN_INTERFACE: return open_interface_json(ba); - case ECHLD_INTERFACE_OPENED: return interface_opened_json(ba); - case ECHLD_START_CAPTURE: return g_strdup("{type='start_capture'}"); - case ECHLD_CAPTURE_STARTED: return g_strdup("{type='capture_started'}"); - case ECHLD_NOTIFY: return notify_json(ba); - case ECHLD_GET_SUM: return get_sum_json(ba); - case ECHLD_PACKET_SUM: return packet_summary_json(ba); - case ECHLD_GET_TREE: return get_tree_json(ba); - case ECHLD_TREE: return tree_json(ba); - case ECHLD_GET_BUFFER: return get_buffer_json(ba); - case ECHLD_BUFFER: return buffer_json(ba); - case ECHLD_EOF: return g_strdup("{type='eof'}"); - case ECHLD_STOP_CAPTURE: return g_strdup("{type='stop_capture'}"); - case ECHLD_CAPTURE_STOPPED: return g_strdup("{type='capture_stopped'}"); - case ECHLD_ADD_NOTE: return add_note_json(ba); - case ECHLD_NOTE_ADDED: return note_added_json(ba); - case ECHLD_APPLY_FILTER: return apply_filter_json(ba); - case ECHLD_PACKET_LIST: return packet_list_json(ba); - case ECHLD_SAVE_FILE: return save_file_json(ba); - case ECHLD_FILE_SAVED: return file_saved_json(ba); - case EC_ACTUAL_ERROR: return g_strdup("{type='actual_error'}"); - default: break; - } - - return NULL; -} -char* echld_decode(echld_msg_type_t t, enc_msg_t* m ) { - return decode_json(t,m); -} - - - -extern void dummy_switch(echld_msg_type_t type) { - switch(type) { - case ECHLD_ERROR: break; - case ECHLD_TIMED_OUT: break; - case ECHLD_NEW_CHILD: break; - case ECHLD_HELLO: break; - case ECHLD_CHILD_DEAD: break; /* S msg */ - case ECHLD_CLOSE_CHILD: break; - case ECHLD_CLOSING: break; - case ECHLD_SET_PARAM: break; - case ECHLD_GET_PARAM: break; - case ECHLD_PARAM: break; /* SS param,val */ - case ECHLD_PING: break; - case ECHLD_PONG: break; - case ECHLD_OPEN_FILE: break; - case ECHLD_FILE_OPENED: break; - case ECHLD_OPEN_INTERFACE: break; - case ECHLD_INTERFACE_OPENED: break; - case ECHLD_START_CAPTURE: break; - case ECHLD_CAPTURE_STARTED: break; - case ECHLD_NOTIFY: break; /* S notification (pre-encoded) */ - case ECHLD_GET_SUM: break; - case ECHLD_PACKET_SUM: break; /* S (pre-encoded) */ - case ECHLD_GET_TREE: break; - case ECHLD_TREE: break; /* IS framenum,tree (pre-encoded) */ - case ECHLD_GET_BUFFER: break; - case ECHLD_BUFFER: break; /* SSIS name,range,totlen,data */ - case ECHLD_EOF: break; - case ECHLD_STOP_CAPTURE: break; - case ECHLD_CAPTURE_STOPPED: break; - case ECHLD_ADD_NOTE: break; - case ECHLD_NOTE_ADDED: break; /* IS */ - case ECHLD_APPLY_FILTER: break; - case ECHLD_PACKET_LIST: break; /* SS name,range */ - case ECHLD_SAVE_FILE: break; - case ECHLD_FILE_SAVED: break; - case EC_ACTUAL_ERROR: break; - } - - switch(type) { - case ECHLD_NEW_CHILD: break; - case ECHLD_CLOSE_CHILD: break; - case ECHLD_SET_PARAM: break; /* set_param(p,v) */ - case ECHLD_GET_PARAM: break; /* get_param(p) */ - case ECHLD_PING: break; - case ECHLD_OPEN_FILE: break; /* open_file(f,mode) */ - case ECHLD_OPEN_INTERFACE: break; /* open_interface(if,param) */ - case ECHLD_START_CAPTURE: break; - case ECHLD_GET_SUM: break; /* get_sum(rng) */ - case ECHLD_GET_TREE: break; /* get_tree(rng) */ - case ECHLD_GET_BUFFER: break; /* get_buffer(rng) */ - case ECHLD_STOP_CAPTURE: break; - case ECHLD_ADD_NOTE: break; /* add_note(framenum,note) */ - case ECHLD_APPLY_FILTER: break; /* apply_filter(df) */ - case ECHLD_SAVE_FILE: break; /* save_file(f,mode) */ - - - case ECHLD_ERROR: break; /* error(err,reason) */ - case ECHLD_TIMED_OUT: break; - case ECHLD_HELLO: break; - case ECHLD_CHILD_DEAD: break; /* child_dead(msg) */ - case ECHLD_CLOSING: break; - case ECHLD_PARAM: break; - case ECHLD_PONG: break; - case ECHLD_FILE_OPENED: break; - case ECHLD_INTERFACE_OPENED: break; - case ECHLD_CAPTURE_STARTED: break; - case ECHLD_NOTIFY: break; /* notify(pre-encoded) */ - case ECHLD_PACKET_SUM: break; /* packet_sum(pre-encoded) */ - case ECHLD_TREE: break; /* tree(framenum, tree(pre-encoded) ) */ - case ECHLD_BUFFER: break; /* buffer (name,range,totlen,data) */ - case ECHLD_EOF: break; - case ECHLD_CAPTURE_STOPPED: break; - case ECHLD_NOTE_ADDED: break; - case ECHLD_PACKET_LIST: break; /* packet_list(name,filter,range); */ - case ECHLD_FILE_SAVED: break; - - case EC_ACTUAL_ERROR: break; - } -} - -static void* unused = int_deca; - -extern void unused_things(void) { - unused = NULL; -} diff --git a/echld/dispatcher.c b/echld/dispatcher.c deleted file mode 100644 index eb749d9b27..0000000000 --- a/echld/dispatcher.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* echld_dispatcher.c - * epan working child API internals - * Dispatcher process routines and definitions - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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 "echld-int.h" -/** - DISPATCHER - **/ - -struct dispatcher_child { - echld_chld_id_t chld_id; - child_state_t state; - echld_reader_t reader; - int write_fd; - int pid; - int reqh_id; - gboolean closing; -}; - -struct dispatcher { - int parent_out; - echld_reader_t parent_in; - struct dispatcher_child* children; - int max_children; - int nchildren; - int reqh_id; - int pid; - int ppid; - struct _encs { - child_encoder_t* to_parent; - echld_parent_encoder_t* to_child; - } enc; - struct _decs { - child_decoder_t* from_parent; - parent_decoder_t* from_child; - } dec; - - int dumpcap_pid; - gboolean closing; - capture_options capture_opts; -}; - -struct dispatcher* dispatcher; - -#ifdef DEBUG_DISPATCHER -static int debug_lvl = DEBUG_DISPATCHER; -static FILE* debug_fp = NULL; - -#define DCOM() /*echld_common_set_dbg(debug_lvl,debug_fp,"Disp")*/ - -int dispatcher_debug(int level, const char* fmt, ...) { - va_list ap; - char* str; - - if (debug_lvlpid, dispatcher->reqh_id, level, str); - } else { - fprintf(debug_fp, "dispatcher: dbg_level=%d message='%s'\n", level, str); - } - - fflush(debug_fp); - - g_free(str); - - return 1; -} - - -static char* param_get_dbg_level(char** err _U_) { - return g_strdup_printf("%d",debug_lvl); -} - -static echld_bool_t param_set_dbg_level(char* val , char** err ) { - char* p; - int lvl = (int)strtol(val, &p, 10); - - if (p<=val) { - *err = g_strdup("not an integer"); - return FALSE; - } else if (lvl < 0 || lvl > 5) { - *err = g_strdup_printf("invalid level=%d (min=0 max=5)",lvl); - return FALSE; - } - - debug_lvl = lvl; - DCOM(); - return TRUE; -} - -static long dbg_r = 0; - -#define DISP_DBG(attrs) ( dispatcher_debug attrs ) -#define DISP_DBG_INIT() do { debug_fp = stderr; DCOM(); } while(0) -#define DISP_DBG_START(fname) do { debug_fp = ws_fopen(fname,"a"); DCOM(); DISP_DBG((0,"Log Started")); } while(0) -#define DISP_WRITE(FD,BA,CH,T,RH) ( dbg_r = echld_write_frame(FD,BA,CH,T,RH,NULL), DISP_DBG((1,"SND fd=%d ch=%d ty='%s' rh=%d msg='%s'",FD,CH,TY(T),RH, (dbg_r>0?"ok":g_strerror(errno))))) -#define CHLD_SET_STATE(c,st) do { DISP_DBG((1,"Child[%d] State %s => %s",(c)->chld_id, ST((c)->state), ST((st)) )); (c)->state=(st); } while(0) -#else -#define DISP_DBG(attrs) -#define DISP_DBG_INIT() -#define DISP_DBG_START(fname) -#define DISP_WRITE(FD,BA,CH,T,RH) echld_write_frame(FD,BA,CH,T,RH,NULL) -#define CHLD_SET_STATE(c,st) ((c)->state = (st)) -#endif - -#define DISP_RESP(B,T) (DISP_WRITE( dispatcher->parent_out, (B), 0, (T), dispatcher->reqh_id)) - - - -static echld_epan_stuff_t stuff; - -static void init_stuff(void) { -#ifdef HAVE_LIBPCAP - capture_opts_init(&stuff.cap_opts); - capture_session_init(&stuff.cap_sess, &stuff.cfile); -#endif - -} - -static void children_massacre(void) { - int i; - struct dispatcher_child* cc = dispatcher->children; - int max_children = dispatcher->max_children; - - for(i = 0; i < max_children; i++) { - struct dispatcher_child* c = &(cc[i]); - if (c->pid > 0) { - DISP_DBG((0,"killing ch=%d pid=%d",c->chld_id,c->pid)); - kill(c->pid,SIGTERM); - } - } -} - - -#define ERR_STR_LEN 1024 -static void dispatcher_fatal(int cause, const char* fmt, ...) { - gchar err_str[ERR_STR_LEN]; - va_list ap; - - va_start(ap, fmt); - g_vsnprintf(err_str, ERR_STR_LEN, fmt,ap); - va_end(ap); - - DISP_DBG((0,"fatal cause=%d msg=\"%s\"",cause ,err_str)); - - children_massacre(); - - exit(cause); -} - -#define DISP_FATAL(attrs) dispatcher_fatal attrs - -static void dispatcher_err(int errnum, const char* fmt, ...) { - gchar err_str[ERR_STR_LEN]; - va_list ap; - static GByteArray* ba; - - va_start(ap, fmt); - g_vsnprintf(err_str, ERR_STR_LEN, fmt,ap); - va_end(ap); - - DISP_DBG((0,"error=\"%s\"",err_str)); - - ba = dispatcher->enc.to_parent->error(errnum, err_str); - DISP_RESP(ba,ECHLD_ERROR); - g_byte_array_free(ba,TRUE); -} - -/* parameters */ - -/* interface listing */ - -static char* intflist2json(GList* if_list, char** if_cap_err) { -#define ADDRSTRLEN 46 /* Covers IPv4 & IPv6 */ - - GList *if_entry; - if_info_t *if_info; - GSList *addr; - if_addr_t *if_addr; - if_capabilities_t *caps; - char addr_str[ADDRSTRLEN]; - GString *str = g_string_new("{ what='interfaces', interfaces={ \n"); - - for (if_entry = g_list_first(if_list); if_entry != NULL; - if_entry = g_list_next(if_entry)) { - if_info = (if_info_t *)if_entry->data; - g_string_append_printf(str," %s={ intf='%s',", if_info->name, if_info->name); - - /* - * Print the contents of the if_entry struct in a parseable format. - * Each if_entry element is tab-separated. Addresses are comma- - * separated. - */ - /* XXX - Make sure our description doesn't contain a tab */ - if (if_info->vendor_description != NULL) - g_string_append_printf(str," vnd_desc='%s',", if_info->vendor_description); - - /* XXX - Make sure our friendly name doesn't contain a tab */ - if (if_info->friendly_name != NULL) - g_string_append_printf(str," name='%s', addrs=[ ", if_info->friendly_name); - - for (addr = g_slist_nth(if_info->addrs, 0); addr != NULL; - addr = g_slist_next(addr)) { - - if_addr = (if_addr_t *)addr->data; - switch(if_addr->ifat_type) { - case IF_AT_IPv4: - if (inet_ntop(AF_INET, &if_addr->addr.ip4_addr, addr_str, - ADDRSTRLEN)) { - g_string_append_printf(str,"'%s',", addr_str); - } else { - g_string_append(str,"'',"); - } - break; - case IF_AT_IPv6: - if (inet_ntop(AF_INET6, &if_addr->addr.ip6_addr, - addr_str, ADDRSTRLEN)) { - g_string_append_printf(str,"'%s',", addr_str); - } else { - g_string_append(str,"'',"); - } - break; - default: - g_string_append_printf(str,"'',", if_addr->ifat_type); - } - - } - - g_string_truncate(str,str->len - 1); /* the last comma or space (on empty list) */ - g_string_append(str," ]"); /* addrs */ - - - if (if_info->loopback) - g_string_append(str,", loopback=1"); - else - g_string_append(str,", loopback=0"); - - - - caps = capture_get_if_capabilities(if_info->name, 0, NULL, if_cap_err, NULL); - - if (caps != NULL) { - if (caps->data_link_types != NULL) { - GList* lt_entry = caps->data_link_types; - data_link_info_t *data_link_info; - - g_string_append(str,", data_link_types=["); - - for (; lt_entry != NULL; lt_entry = g_list_next(lt_entry) ) { - - data_link_info = (data_link_info_t *)lt_entry->data; - g_string_append_printf(str,"{ name='%s', desc='%s' }, ", data_link_info->name, (data_link_info->description) ? data_link_info->description : "" ); - } - - g_string_truncate(str,str->len - 2); /* the comma and space */ - g_string_append(str,"]"); - } - - g_string_append_printf(str,", can_set_rfmon=%s", caps->can_set_rfmon ? "1" : "0"); - - if (caps->can_set_rfmon) { - free_if_capabilities(caps); - caps = capture_get_if_capabilities(if_info->name, 1, NULL, if_cap_err, NULL); - - if (caps->data_link_types != NULL) { - GList* lt_entry = caps->data_link_types; - data_link_info_t *data_link_info; - - g_string_append(str,", data_link_types_rfmon=["); - - for (; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { - data_link_info = (data_link_info_t *)lt_entry->data; - g_string_append_printf(str,"{ name='%s', desc='%s' }, ", data_link_info->name, (data_link_info->description) ? data_link_info->description : "" ); - } - - g_string_truncate(str,str->len - 2); /* the comma and space */ - g_string_append(str,"]"); - } - } - - free_if_capabilities(caps); - } - - g_string_append(str,"},\n"); - } - - g_string_truncate(str,str->len - 2); /* the comma and return */ - g_string_append(str,"}"); - - return g_string_free(str,FALSE); -} - -static char* intf_list = NULL; - -static void get_interfaces(char** err) { - int err_no = 0; - GList* if_list; - - err = NULL; - if_list = capture_interface_list(&err_no, err, NULL); - - if (err) { - DISP_DBG((1,"Could not get capture interface list: %s",err)); - } else { - intf_list = intflist2json(if_list,err); - if (err) { - DISP_DBG((1,"get capabilities error: %s",err)); - } - } - - free_interface_list(if_list); -} - - -static char* param_get_interfaces(char** err _U_) { - return g_strdup(intf_list ? intf_list : ""); -} - -static long disp_loop_timeout_usec = DISPATCHER_WAIT_INITIAL; - -static char* param_get_loop_timeout(char** err _U_) { - return g_strdup_printf("%fs", (((float)disp_loop_timeout_usec)/1000000.0) ); -} - -static echld_bool_t param_set_loop_timeout(char* val , char** err ) { - char* p; - int usec = (int)strtol(val, &p, 10); /* now usecs 2DO: "10ms" or "500us" or "1s" */ - - if (p<=val) { - *err = g_strdup("not an integer"); - return FALSE; - } - - disp_loop_timeout_usec = usec; - - return TRUE; -} - -static GString *comp_info_str; -static GString *runtime_info_str; -static const char* version_str = "Echld " VERSION; -static char* version_long_str = NULL; - - -static char* param_get_long_version(char** err _U_) { - return g_strdup(version_long_str); -} - -static char* param_get_version(char** err _U_) { - return g_strdup(version_str); -} - -static char* param_get_capture_types(char** err _U_) { - GString* str = g_string_new(""); - int i; - - for (i = 0; i < WTAP_NUM_FILE_TYPES_SUBTYPES; i++) { - if (wtap_dump_can_open(i)) { - g_string_append_printf(str,"%s: %s\n", - wtap_file_type_subtype_short_string(i), wtap_file_type_subtype_string(i)); - } - } - - return g_string_free(str,FALSE); -} - -static echld_bool_t param_set_add_hosts_file(char* val, char** err) { - if (add_hosts_file(val)) { - return TRUE; - } else { - *err = g_strdup_printf("Can't read host entries from \"%s\"",val); - return FALSE; - } -} - -static echld_bool_t param_set_x_opt(char* val, char** err) { - if (ex_opt_add(val)) { - return TRUE; - } else { - *err = g_strdup_printf("Cannot set X opt '%s'",val); - return FALSE; - } -} - - - - -static char* param_get_params(char** err _U_); - -static param_t disp_params[] = { -#ifdef DEBUG_DISPATCHER - PARAM(dbg_level,"0>int>5"), -# endif - RO_PARAM(long_version,"long version string"), - RO_PARAM(version,"version string"), - PARAM(loop_timeout,"main loop step timeout"), - RO_PARAM(interfaces,"interface information"), - RO_PARAM(capture_types,"the available capture types"), - WO_PARAM(add_hosts_file,"Add a hosts file"), - WO_PARAM(x_opt,"Set a -X option"), - RO_PARAM(params,"This List"), - {NULL,NULL,NULL,NULL} -}; - -static char* param_get_params(char** err _U_) { - return paramset_get_params_list(disp_params,PARAM_LIST_FMT); -} - -static struct dispatcher_child* dispatcher_get_child(struct dispatcher* d, int chld_id) { - int i; - struct dispatcher_child* cc = d->children; - int max_children = d->max_children; - - for(i = 0; i < max_children; i++) { - struct dispatcher_child* c = &(cc[i]); - if (c->chld_id == chld_id) return c; - } - - return NULL; -} - - -static void dispatcher_clear_child(struct dispatcher_child* c) { - echld_reset_reader(&(c->reader), -1, 4096); - c->chld_id = -1; - c->state = FREE; - c->reader.fd = -1; - c->write_fd = -1; - c->pid = -1; - c->reqh_id = -1; - c->closing = FALSE; -} - -static void set_dumpcap_pid(int pid) { - - dispatcher->dumpcap_pid = pid; -} - -static void preinit_epan(char* argv0, int (*main)(int, char **)) { - char *gdp_path, *dp_path; -#if 0 - char *gpf_path, *pf_path; - int gpf_open_errno, gpf_read_errno; - int pf_open_errno, pf_read_errno; -#endif - int gdp_open_errno, gdp_read_errno; - int dp_open_errno, dp_read_errno; - char* error; - - error = init_progfile_dir(argv0, main); - - comp_info_str = get_compiled_version_info(NULL, epan_get_compiled_version_info); - - runtime_info_str = get_runtime_version_info(NULL); - - version_long_str = g_strdup_printf("Echld %s\n%s\n%s\n%s", - get_ws_vcs_version_info(), get_copyright_info(), - comp_info_str->str, runtime_info_str->str); - - if (error) { - DISP_FATAL((CANNOT_PREINIT_EPAN,"Failed epan_preinit: msg='%s'",error)); - } - - /* Add it to the information to be reported on a crash. */ - ws_add_crash_info("Echld %s\n%s\n%s", - get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str); - - init_stuff(); - - capture_sync_set_fetch_dumpcap_pid_cb(set_dumpcap_pid); - - init_process_policies(); - - get_interfaces(&error); - - if (error) { - DISP_FATAL((CANNOT_PREINIT_EPAN,"Error getting interfaces: %s", error)); - } - - prefs_apply_all(); - - /* disabled protocols as per configuration file */ - set_disabled_protos_list(); - set_enabled_protos_list(); - set_disabled_heur_dissector_list(); - - setlocale(LC_ALL, ""); - DISP_DBG((1,"---5")); - - read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno, &dp_path, &dp_open_errno, &dp_read_errno); - read_enabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno, &dp_path, &dp_open_errno, &dp_read_errno); - read_disabled_heur_dissector_list(&gdp_path, &gdp_open_errno, &gdp_read_errno, &dp_path, &dp_open_errno, &dp_read_errno); - - DISP_DBG((1,"---6")); - - cap_file_init(&stuff.cfile); - DISP_DBG((1,"---7")); - - DISP_DBG((1,"---8")); - timestamp_set_precision(TS_PREC_AUTO); - -#if 0 - sleep(10); - - initialize_funnel_ops(); - stuff.prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path, &pf_open_errno, &pf_read_errno, &pf_path); - check 4 errors -#endif - - DISP_DBG((2,"epan preinit done")); -} - - -static void dispatcher_clear(void) { - DISP_DBG((2,"dispatcher_clear")); - /* remove unnecessary stuff for the working child */ - /* remove signal handlers */ -} - -void dispatcher_sig(int sig) { - DISP_FATAL((TERMINATED,"SIG sig=%d",sig)); - exit(1); -} - -void dispatcher_reaper(int sig) { - int status; - int i; - struct dispatcher_child* cc = dispatcher->children; - int max_children = dispatcher->max_children; - int pid = waitpid(-1, &status, WNOHANG); - int reqh_id_save = dispatcher->reqh_id; - - dispatcher->reqh_id = 0; - - if (sig != SIGCHLD) { - DISP_DBG((1,"Reaper got wrong signal=%d",sig)); - dispatcher->reqh_id = reqh_id_save; - return; - } - - DISP_DBG((2,"Child dead pid=%d",pid)); - - for(i = 0; i < max_children; i++) { - struct dispatcher_child* c = &(cc[i]); - if ( c->pid == pid ) { - if (c->closing || dispatcher->closing) { - DISP_WRITE(dispatcher->parent_out, NULL, c->chld_id, ECHLD_CLOSING, c->reqh_id); - } else { - char* s = NULL; - GByteArray* em; - - if (WIFEXITED(status)) { - s = g_strdup_printf( - "Unexpected dead: reason='exited' pid=%d status=%d", - pid, WEXITSTATUS(status)); - } else if ( WIFSIGNALED(status) ) { - s = g_strdup_printf( - "Unexpected dead: reason='signaled' pid=%d termsig=%d coredump=%s", - pid, WTERMSIG(status), WCOREDUMP(status) ? "yes":"no"); - - /*if (WCOREDUMP(status)) { system("analyze_coredump.sh pid=%d") } */ - - } else if (WIFSTOPPED(status)) { - s = g_strdup_printf( - "Unexpected dead: reason='stopped' pid=%d stopsig=%d", - pid, WSTOPSIG(status)); - } - - em = dispatcher->enc.to_parent->child_dead(s); - dispatcher_err(ECHLD_ERR_CRASHED_CHILD, s); - if (s) g_free(s); - DISP_WRITE(dispatcher->parent_out, em, c->chld_id, ECHLD_CHILD_DEAD, 0); - if (em) g_byte_array_free(em,TRUE); - } - - CHLD_SET_STATE(c,CLOSED); - dispatcher_clear_child(c); - dispatcher->reqh_id = reqh_id_save; - return; - } - } - - if (pid == dispatcher->dumpcap_pid) { - dispatcher->dumpcap_pid = 0; - dispatcher->reqh_id = reqh_id_save; - DISP_DBG((2,"dumpcap dead pid=%d",pid)); - return; - } - - dispatcher_err(ECHLD_ERR_UNKNOWN_PID, "Unknown child pid: %d", pid); - dispatcher->reqh_id = reqh_id_save; -} - - -static void dispatcher_destroy(void) { - /* destroy the dispatcher stuff at closing */ - - dispatcher->closing = TRUE; - - children_massacre(); - - exit(0); -} - -/* stuff coming from child going to parent */ -static long dispatch_to_parent(guint8* b, size_t len, echld_chld_id_t chld_id, echld_msg_type_t type, echld_reqh_id_t reqh_id, void* data) { - /* TODO: timeouts, clear them */ - /* TODO: keep stats */ - - GByteArray in_ba; - - struct dispatcher_child* c = (struct dispatcher_child*)data; - - dispatcher->reqh_id = c->reqh_id = reqh_id; - - in_ba.data = b; - in_ba.len = (guint)len; - - if (chld_id != c->chld_id) { - goto misbehabing; - } - - switch(type) { - case ECHLD_ERROR: break; - case ECHLD_TIMED_OUT: break; - case ECHLD_HELLO: CHLD_SET_STATE(c,IDLE); break; - case ECHLD_CLOSING: - c->closing = TRUE; - CHLD_SET_STATE(c,CLOSING); - break; - case ECHLD_PARAM: break; - case ECHLD_PONG: break; - case ECHLD_FILE_OPENED: CHLD_SET_STATE(c,READING); break; - case ECHLD_INTERFACE_OPENED: CHLD_SET_STATE(c,READY); break; - case ECHLD_CAPTURE_STARTED: CHLD_SET_STATE(c,CAPTURING); break; - case ECHLD_NOTIFY: break; - case ECHLD_PACKET_SUM: break; - case ECHLD_TREE: break; - case ECHLD_BUFFER: break; - - case ECHLD_EOF: - case ECHLD_CAPTURE_STOPPED: CHLD_SET_STATE(c,DONE); break; - - case ECHLD_NOTE_ADDED: break; - case ECHLD_PACKET_LIST: break; - case ECHLD_FILE_SAVED: break; - - default: - goto misbehabing; - } - - DISP_DBG((4,"Dispatching to parent reqh_id=%d chld_id=%d type='%c'",reqh_id,c->chld_id,type)); - return DISP_WRITE(dispatcher->parent_out, &in_ba, chld_id, type, reqh_id); - -misbehabing: - CHLD_SET_STATE(c,ERRORED); - c->closing = TRUE; - kill(c->pid,SIGTERM); - dispatcher_err(ECHLD_ERR_CRASHED_CHILD,"chld_id=%d",chld_id); - return 0; - -} - -static struct timeval start_wait_time; -static long start_wait_time_us = CHILD_START_WAIT_TIME; - -static void detach_new_child(enc_msg_t* em, echld_chld_id_t chld_id) { - struct dispatcher_child* c; - int reqh_id = dispatcher->reqh_id; - int pid; - - if (( c = dispatcher_get_child(dispatcher, chld_id) )) { - dispatcher_err(ECHLD_ERR_CHILD_EXISTS,"chld_id=%d exists already while creating new child",chld_id); - return; - } else if (( c = dispatcher_get_child(dispatcher, -1) )) { - int disp_pipe_fds[2]; - int child_pipe_fds[2]; - - int pipe_to_disp; - int pipe_from_disp; - int pipe_to_child; - int pipe_from_child; - - DISP_DBG((5,"new_child pipe(dispatcher)")); - if( pipe(disp_pipe_fds) < 0) { - dispatcher_err(ECHLD_ERR_CANNOT_FORK,"CANNOT OPEN PARENT PIPE: %s",g_strerror(errno)); - return; - } - - pipe_from_disp = disp_pipe_fds[0]; - pipe_to_child = disp_pipe_fds[1]; - - DISP_DBG((5,"new_child pipe(child)")); - if( pipe(child_pipe_fds) < 0) { - close(pipe_from_disp); - close(pipe_to_child); - dispatcher_err(ECHLD_ERR_CANNOT_FORK,"CANNOT OPEN CHILD PIPE: %s",g_strerror(errno)); - return; - } - - pipe_from_child = child_pipe_fds[0]; - pipe_to_disp = child_pipe_fds[1]; - - DISP_DBG((4,"New Child Forking()")); - switch (( pid = fork() )) { - case -1: { - close(pipe_to_child); - close(pipe_to_disp); - close(pipe_from_child); - close(pipe_from_disp); - dispatcher_err(ECHLD_ERR_CANNOT_FORK,"CANNOT FORK: %s",g_strerror(errno)); - return; - } - case 0: { - /* I'm the child */ - dispatcher_clear(); - - close(pipe_to_child); - close(pipe_from_child); - - echld_child_initialize(chld_id, pipe_from_disp,pipe_to_disp,reqh_id,&stuff); - - exit( echld_child_loop() ); - - /* it won't */ - return; - } - default: { - /* I'm the parent */ - - close(pipe_to_disp); - close(pipe_from_disp); - - echld_reset_reader(&(c->reader), pipe_from_child,4096); - c->write_fd = pipe_to_child; - c->pid = pid; - c->chld_id = chld_id; - c->closing = FALSE; - - CHLD_SET_STATE(c,CREATING); - - DISP_DBG((4,"Child Forked pid=%d chld_id=%d from_fd=%d to_fd=%d", - pid, c->chld_id, pipe_from_child, pipe_to_child)); - - start_wait_time.tv_sec = (int)(start_wait_time_us / 1000000); - start_wait_time.tv_usec = (int)(start_wait_time_us % 1000000); - - select(0,NULL,NULL,NULL,&start_wait_time); - - /* configure child */ - DISP_WRITE(pipe_to_child, em, c->chld_id, ECHLD_NEW_CHILD, dispatcher->reqh_id); - return; - } - } - } else { - dispatcher_err(ECHLD_ERR_CANNOT_FORK, "MAX CHILDREN REACHED: max_children=%d",dispatcher->max_children); - return; - } -} - - -/* process signals sent from parent */ -static long dispatch_to_child(guint8* b, size_t len, echld_chld_id_t chld_id, echld_msg_type_t type, echld_reqh_id_t reqh_id, void* data _U_) { - GByteArray in_ba; - - in_ba.data = b; - in_ba.len = (guint)len; - - dispatcher->reqh_id = reqh_id; - - DISP_DBG((1,"RCV<- type='%s' chld_id=%d reqh_id=%d",TY(type),chld_id,reqh_id)); - - if (chld_id == 0) { /* these are messages sent to the dispatcher itself */ - DISP_DBG((2,"Message to Dispatcher")); - switch(type) { - case ECHLD_CLOSE_CHILD: - dispatcher_destroy(); - return 0; - case ECHLD_PING: - DISP_DBG((2,"PONG reqh_id=%d",reqh_id)); - DISP_WRITE(dispatcher->parent_out, NULL, chld_id, ECHLD_PONG, reqh_id); - return 0; - case ECHLD_SET_PARAM:{ - char* param; - char* value; - if ( dispatcher->dec.from_parent->set_param(b,len,¶m,&value) ) { - GByteArray* ba; - char* err; - if (! paramset_apply_set (disp_params, param, value, &err) ) { - dispatcher_err(ECHLD_CANNOT_SET_PARAM,"%s",err); - g_free(err); - return 0; - } - - ba = dispatcher->enc.to_parent->param(param,value); - DISP_RESP(ba,ECHLD_PARAM); - g_byte_array_free(ba,TRUE); - DISP_DBG((1,"Set Param: param='%s' value='%s'",param,value)); - - return 0; - } else { - dispatcher_err(ECHLD_CANNOT_SET_PARAM,"reason='decoder error'"); - return 0; - } - } - case ECHLD_GET_PARAM: { - GByteArray* ba; - char* param; - if ( dispatcher->dec.from_parent->get_param(b,len,¶m) ) { - char* err; - char* val; - - if (! (val = paramset_apply_get (disp_params, param, &err)) ) { - dispatcher_err(ECHLD_CANNOT_GET_PARAM,"%s",err); - g_free(err); - return 0; - } - - ba = dispatcher->enc.to_parent->param(param,val); - DISP_RESP(ba,ECHLD_PARAM); - g_byte_array_free(ba,TRUE); - DISP_DBG((1,"Get Param: param='%s' value='%s'",param,val)); - return 0; - } else { - dispatcher_err(ECHLD_CANNOT_GET_PARAM,"reason='decoder error'"); - return 0; - } - } - default: - dispatcher_err(ECHLD_ERR_WRONG_MSG, "wrong message to dispatcher type='%c'", type); - return 0; - } - } else { - struct dispatcher_child* c; - - DISP_DBG((2,"Parent => Child")); - - if (! (c = dispatcher_get_child(dispatcher, chld_id)) ) { - if (type == ECHLD_NEW_CHILD) { - detach_new_child(&in_ba,chld_id); - return 0; - } else { - dispatcher_err(ECHLD_ERR_NO_SUCH_CHILD, "wrong chld_id %d", chld_id); - return 0; - } - } else { - switch(type) { - case ECHLD_CLOSE_CHILD: - CHLD_SET_STATE(c,CLOSED); - goto relay_frame; - - case ECHLD_OPEN_FILE: - CHLD_SET_STATE(c,READING); - goto relay_frame; - - case ECHLD_OPEN_INTERFACE: - CHLD_SET_STATE(c,READY); - goto relay_frame; - - case ECHLD_START_CAPTURE: - CHLD_SET_STATE(c,CAPTURING); - goto relay_frame; - - case ECHLD_STOP_CAPTURE: - CHLD_SET_STATE(c,DONE); - goto relay_frame; - - case ECHLD_SAVE_FILE: - case ECHLD_APPLY_FILTER: - case ECHLD_SET_PARAM: - case ECHLD_GET_PARAM: - case ECHLD_PING: - case ECHLD_GET_SUM: - case ECHLD_GET_TREE: - case ECHLD_GET_BUFFER: - case ECHLD_ADD_NOTE: - relay_frame: { - DISP_DBG((3,"Relay to Child chld_id=%d type='%c' req_id=%d",chld_id, type, reqh_id)); - return DISP_WRITE(c->write_fd, &in_ba, chld_id, type, reqh_id); - } - default: - dispatcher_err(ECHLD_ERR_WRONG_MSG, "wrong message %d %c", reqh_id, type); - return 0; - } - } - } -} - - - -int dispatcher_loop(void) { - int parent_out = dispatcher->parent_out; - int parent_in = dispatcher->parent_in.fd; - struct dispatcher_child* children = dispatcher->children; - - DISP_DBG((5,"LOOP in_fd=%d out_fd=%d",parent_in, parent_out)); - - do { - fd_set rfds; - fd_set efds; - struct dispatcher_child* c; - int nfds; - int nchld = 0; - struct timeval disp_loop_timeout; - - FD_ZERO(&rfds); - FD_ZERO(&efds); - - FD_SET(parent_in,&rfds); - FD_SET(parent_in,&efds); - FD_SET(parent_out,&efds); - - for (c = children; c->pid; c++) { - if (c->chld_id > 0) { - nchld++; - FD_SET(c->reader.fd, &rfds); - FD_SET(c->reader.fd, &efds); - } - } - - DISP_DBG((4,"Select()ing nchld=%d",nchld,disp_loop_timeout.tv_usec)); - - disp_loop_timeout.tv_sec = (int)(disp_loop_timeout_usec / 1000000); - disp_loop_timeout.tv_usec = (int)(disp_loop_timeout_usec % 1000000); - - nfds = select(FD_SETSIZE, &rfds, NULL, &efds, &disp_loop_timeout); - - DISP_DBG((5,"Select()ed nfds=%d",nchld,nfds)); - - if (nfds < 0) { - DISP_DBG((1,"select error='%s'",g_strerror(errno) )); - continue; - } - - if ( FD_ISSET(parent_in, &rfds)) { - long st = echld_read_frame(&(dispatcher->parent_in), dispatch_to_child, dispatcher); - - if (st < 0) { - DISP_DBG((1,"read frame returning < 0 for parent")); - /* XXX: ??? */ - continue; - } - } - - if ( FD_ISSET(parent_in, &efds) ) { - DISP_DBG((1,"Parent In Pipe Errored!")); - continue; - } - - if ( FD_ISSET(parent_out, &efds) ) { - DISP_DBG((1,"Parent Out Pipe Errored!")); - continue; - } - - - for (c=children; c->pid; c++) { - if (c->reader.fd > 0) { - if ( FD_ISSET(c->reader.fd,&efds) ) { - struct timeval wait_time; - wait_time.tv_sec = 0; - wait_time.tv_usec = DISP_KILLED_CHILD_WAIT; - - DISP_DBG((1,"errored child pipe chld_id=%d",c->chld_id)); - kill(c->pid,SIGTERM); - select(0,NULL,NULL,NULL,&wait_time); - dispatcher_clear_child(c); - continue; - } - - if (FD_ISSET(c->reader.fd,&rfds)) { - long st = echld_read_frame(&(c->reader), dispatch_to_parent, c); - - if (st < 0) { - DISP_DBG((1,"read_frame returned < 0 for chld_id=%d",c->chld_id)); - /* XXX */ - continue; - } - continue; - } - } - } - } while(1); - - /* won't */ - return 1; -} - -void dispatcher_alrm(int sig _U_) { - DISP_DBG((1,"ALRM received")); -} - -void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, int (*main)(int, char **)) { - static struct dispatcher d; - int i; - int ret; - - DISP_DBG_INIT(); - DISP_DBG((2,"Dispatcher Starting")); - - - signal(SIGCHLD,dispatcher_reaper); - - signal(SIGTERM,dispatcher_sig); - signal(SIGPIPE,dispatcher_sig); - signal(SIGINT,SIG_IGN); - signal(SIGCONT,SIG_IGN); - signal(SIGABRT,dispatcher_sig); - signal(SIGHUP,dispatcher_sig); - signal(SIGALRM,dispatcher_alrm); - - dispatcher = &d; - - echld_init_reader(&(d.parent_in),in_pipe_fds[0],4096); - d.parent_out = out_pipe_fds[1]; - d.children = g_new0(struct dispatcher_child,ECHLD_MAX_CHILDREN); - d.max_children = ECHLD_MAX_CHILDREN; - d.nchildren = 0; - d.reqh_id = -1; - d.pid = getpid(); - d.dumpcap_pid = 0; - - for (i=0;iparent_out, NULL, 0, ECHLD_HELLO, 0); - - ret = dispatcher_loop(); - capture_opts_cleanup(&(dispatcher->capture_opts)); - exit(ret); -} - -/* - * Editor modelines - http://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 4 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=4 tabstop=8 noexpandtab: - * :indentSize=4:tabSize=8:noTabs=false: - */ diff --git a/echld/echld-int.h b/echld/echld-int.h deleted file mode 100644 index 19dadd8213..0000000000 --- a/echld/echld-int.h +++ /dev/null @@ -1,295 +0,0 @@ -/* echld_child-int.h - * epan working child API internals - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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. - */ -#ifndef __ECHLD_HDR_INT_ -#define __ECHLD_HDR_INT_ - -#include - -#ifdef HAVE_FCNTL_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - -#ifdef HAVE_SYS_WAIT_H -# include -#endif - -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include - - -#include -#include - - - -#include "capture_opts.h" -#include -#include -#include -#include "cfile.h" -#include "wsutil/crash_info.h" -#include "wsutil/privileges.h" -#include "wsutil/filesystem.h" -#include "wsutil/copyright_info.h" -#include "ws_version_info.h" -#include "epan/addr_resolv.h" -#include "epan/epan.h" -#include "epan/prefs.h" -#include "epan/ex-opt.h" -#include "epan/funnel.h" -#include "epan/timestamp.h" -#include "epan/disabled_protos.h" -#include "echld.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* XXX these shouldn't be needed */ -typedef struct tvbuff tvb_t; - -struct _hdr { - guint32 type_len; - guint16 chld_id; - guint16 reqh_id; -}; - - -#define ECHLD_HDR_LEN (sizeof(struct _hdr)) - -typedef union _hdr_t { - struct _hdr h; - guint8 b[ECHLD_HDR_LEN]; -} hdr_t; - -#define HDR_TYPE(H) ((((H)->h.type_len)&0xff000000)>>24) -#define HDR_LEN(H) ((((H)->h.type_len)&0x00ffffff)) - -#define GET_HDR_ELEMS(H,T,L,C,R) do { guint32 tl = H->h.type_len; \ - T=HDR_TYPE(H); L=HDR_LEN(H); C=H->h.chld_id; R=H->h.req_id; } while(0) - - -typedef enum _cst { - FREE=0, - CREATING, - IDLE, - READY, - READING, - CAPTURING, - DONE, - CLOSING, - CLOSED=-1, - ERRORED=-2 -} child_state_t; - -extern const char* echld_state_str(child_state_t); -extern const char* echld_msg_type_str(echld_msg_type_t id); -#define ST(st) echld_state_str(st) -#define TY(ty) echld_msg_type_str(ty) - -/* these manage the de-framing machine in the receiver side */ -typedef struct _echld_reader { - guint8* rp; /* the read pointer*/ - size_t len; /* the used size = (.wp - .rp) */ - - guint8* wp; /* the write pointer */ - int fd; /* the filedesc is serving */ - - guint8* data; /* the allocated read buffer */ - size_t actual_len; /* the actual len of the allocated buffer */ -} echld_reader_t; - - -#define reader_is_empty(R) ( (R)->len == 0 ) -#define reader_has_header(R) ((R)->len >= ECHLD_HDR_LEN) -#define reader_has_frame(R) ( reader_has_header(R) && ( (HDR_LEN( (hdr_t*)((R)->rp) ) + ECHLD_HDR_LEN) >= ((R)->len ))) - -#define READER_FD_SET(R,fdset_p) FD_SET(R.fd,&(fdset_p)) -#define READER_FD_ISSET(R,fdset_p) READER_FD_ISSET(R.fd,&(fdset_p)) -#define READER_FD_CLEAR(R,fdset_p) READER_FD_CLEAR(R.fd,&(fdset_p)) - -extern void echld_common_set_dbg(int level, FILE* fp, const char* prefix); - -extern void echld_init_reader(echld_reader_t* r, int fd, size_t initial); -extern void echld_reset_reader(echld_reader_t* r, int fd, size_t initial); - -typedef struct _param { - const char* name; - char* (*get)(char** err ); - echld_bool_t (*set)(char* val , char** err); - const char* desc; -} param_t; - -extern param_t* paramset_find (param_t* paramsets, char* name, char** err); - -extern char* paramset_apply_get (param_t* paramsets, char* name, char** err); -extern echld_bool_t paramset_apply_set (param_t* paramsets, char* name, char* val, char** err); -extern echld_bool_t paramset_apply_em(param_t* paramset, enc_msg_t* em, char** err); - -#define PARAM_LIST_FMT "%s(%s): %s\n" /* name, rw|ro|wo, desc */ -char* paramset_get_params_list(param_t* paramsets, const char* fmt) G_GNUC_PRINTF(2, 0); - -#define PARAM_STR(Name, Default) static char* param_ ## Name = Default; \ - static char* param_get_ ## Name (char** err _U_ ) { return (param_ ## Name) ? g_strdup(param_ ## Name) : (*err = g_strdup( #Name " not set"), NULL); } \ - static echld_bool_t param_set_ ## Name (char* val , char** err _U_) { if (param_ ## Name) g_free(param_ ## Name); param_ ## Name = g_strdup(val); return TRUE; } \ - -#define PARAM_INT(Name, Default) static int param_ ## Name = Default; \ - static char* param_get_ ## Name (char** err _U_ ) { return g_strdup_printf("%d",param_ ## Name); } \ - static echld_bool_t param_set_ ## Name (char* val , char** err _U_) { char* p; int temp = (int)strtol(val, &p, 10); if (p<=val) { *err = g_strdup("not an integer"); return FALSE; } else { param_ ## Name = temp; return TRUE; } } - -#define PARAM_BOOL(Name, Default) static gboolean param_ ## Name = Default; \ - static char* param_get_ ## Name (char** err _U_ ) { return g_strdup(param_ ## Name ? "TRUE" : "FALSE"); } \ - static echld_bool_t param_set_ ## Name (char* val , char** err _U_) { param_ ## Name = (*val == 'T' || *val == 't') ? TRUE : FALSE; return TRUE;} - -#define PARAM(Name,Desc) {#Name, param_get_ ## Name, param_set_ ## Name, Desc} -#define RO_PARAM(Name,Desc) {#Name, param_get_ ## Name, NULL, Desc} -#define WO_PARAM(Name,Desc) {#Name, NULL, param_set_ ## Name, Desc} - -typedef struct _echld_epan_stuff_t { -#ifdef HAVE_LIBPCAP - capture_session cap_sess; - capture_options cap_opts; - capture_file cfile; -#endif - e_prefs* prefs; -} echld_epan_stuff_t; - -/* the call_back used by read_frame() */ -typedef long (*read_cb_t)(guint8*, size_t, echld_chld_id_t, echld_msg_type_t, echld_reqh_id_t, void*); - - -typedef struct _child_in { - echld_bool_t (*error) (guint8*, size_t, int* , char**); - echld_bool_t (*set_param) (guint8*, size_t, char** param, char** value); - echld_bool_t (*get_param) (guint8*, size_t, char** param); - echld_bool_t (*close_child) (guint8*, size_t, int* mode); - echld_bool_t (*open_file) (guint8*, size_t, char** filename); - echld_bool_t (*open_interface) (guint8*, size_t, char** intf_name, char** params); - echld_bool_t (*get_sum) (guint8*, size_t, char** range); - echld_bool_t (*get_tree) (guint8*, size_t, char** range); - echld_bool_t (*get_buffer) (guint8*, size_t, char** name); - echld_bool_t (*add_note) (guint8*, size_t, int* packet_number, char** note); - echld_bool_t (*apply_filter) (guint8*, size_t, char** filter); - echld_bool_t (*save_file) (guint8*, size_t, char** filename, char** params); -} child_decoder_t; - -typedef struct _child_out { - enc_msg_t* (*error) (int , const char*); - enc_msg_t* (*child_dead) (const char*); - enc_msg_t* (*param) (const char*, const char*); - enc_msg_t* (*notify) (const char*); /* pre-encoded */ - enc_msg_t* (*packet_sum) (int, const char*); /* framenum, sum(pre-encoded) */ - enc_msg_t* (*tree) (int, const char*); /* framenum, tree(pre-encoded) */ - enc_msg_t* (*buffer) (int , const char*, const char*, const char*); /* totlen,name,range,data */ - enc_msg_t* (*packet_list) (const char*, const char*, const char*); /* name, filter, range */ -} child_encoder_t; - - -typedef struct _parent_in { - echld_bool_t (*error) (enc_msg_t*, int* , char**); - echld_bool_t (*child_dead) (enc_msg_t*, char**); - echld_bool_t (*param) (enc_msg_t*, char**, char**); - echld_bool_t (*notify) (enc_msg_t*, char**); /* pre-encoded */ - echld_bool_t (*packet_sum) (enc_msg_t*, int*, char**); /* framenum, sum(pre-encoded) */ - echld_bool_t (*packet) (enc_msg_t*, int*, char**); /* framenum, tree(pre-encoded) */ - echld_bool_t (*buffer) (enc_msg_t*, int*, char**, char**, char**); /* totlen,name,range,data */ - echld_bool_t (*packet_list) (enc_msg_t*, char**, char**, char**); /* name, filter, range */ -} parent_decoder_t; - -extern void echld_get_all_codecs(child_encoder_t**, child_decoder_t**, echld_parent_encoder_t**, parent_decoder_t**); - -extern void echld_init_reader(echld_reader_t* r, int fd, size_t initial); -extern void free_reader(echld_reader_t* r); - -extern long echld_read_frame(echld_reader_t* r, read_cb_t cb, void* cb_data); -extern long echld_write_frame(int fd, GByteArray* ba, guint16 chld_id, echld_msg_type_t type, guint16 reqh_id, void* data); - - -extern void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id, echld_epan_stuff_t* es); -extern int echld_child_loop(void); - -/* never returns*/ -extern void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, int (*main)(int, char **)); - - -extern void dummy_switch(echld_msg_type_t type); -extern void echld_unused(void); - -/* config stuff */ - -/* initial debug levels */ -/* undefine to avoid debugging */ -#define DEBUG_BASE 5 -#define DEBUG_CHILD 5 -#define DEBUG_DISPATCHER 5 -#define DEBUG_PARENT 5 - -/* timers */ -#define DISPATCHER_WAIT_INITIAL 5000000 /* 5s */ -#define CHILD_CLOSE_SLEEP_TIME 2000000 /* 2s */ -#define CHILD_START_WAIT_TIME 100000 /* 0.1s */ -#define DISP_KILLED_CHILD_WAIT 100000 /* 0.1s */ - -/* fatalities */ -#define BROKEN_PARENT_PIPE 9 -#define BROKEN_DUMPCAP_PIPE 10 -#define BROKEN_READFILE 11 -#define DISPATCHER_DEAD 12 -#define UNIMPLEMENTED 13 -#define CANNOT_FORK 14 -#define SHOULD_HAVE_EXITED_BEFORE 15 -#define DISPATCHER_PIPE_FAILED 16 -#define TERMINATED 17 -#define CANNOT_PREINIT_EPAN 18 -#define NO_INITIALIZER 19 - -#ifndef DEBUG_BASE -#define echld_common_set_dbg(a,b,c) -#endif - - - - -#ifdef __cplusplus -extern "C" { -#endif - -#endif diff --git a/echld/echld-util.c b/echld/echld-util.c deleted file mode 100644 index a8b5a1c3d4..0000000000 --- a/echld/echld-util.c +++ /dev/null @@ -1,210 +0,0 @@ -/* echld-util.c - * utility for echld - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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 "config.h" - -#include "echld-int.h" -#include "echld-util.h" - -#include - -struct _ping { - struct timeval tv; - echld_ping_cb_t cb; - void* cb_data; -}; - -static long timevaldiff(struct timeval *starttime, struct timeval *finishtime) { - long msec; - msec=(finishtime->tv_sec-starttime->tv_sec)*1000; - msec+=(finishtime->tv_usec-starttime->tv_usec)/1000; - return msec; -} - -static gboolean pong(echld_msg_type_t type, GByteArray* ba _U_, void* data) { - struct _ping* p = (struct _ping*)data; - struct timeval t; - long ret = -1; - gettimeofday(&t,NULL); - - - switch (type) { - case ECHLD_PONG: - ret = timevaldiff(&(p->tv),&t); - break; - default: - ret = -1; - break; - } - - if (p->cb) p->cb(ret, p->cb_data); - - g_free(p); - - return TRUE; -} - - -extern echld_state_t echld_ping(int chld_id, echld_ping_cb_t pcb, void* cb_data) { - struct _ping* p = g_new0(struct _ping,1); - - p->cb = pcb; - p->cb_data = cb_data; - gettimeofday(&(p->tv),NULL); - - return echld_reqh(chld_id, ECHLD_PING, 0, NULL, pong, p); -} - - -struct _get_param { - const char* name; - echld_param_cb_t cb; - void* cb_data; - echld_bool_t (*dec)(enc_msg_t*, char**, char**); - echld_bool_t (*dec_err)(enc_msg_t*, int* , char**); - const char** err_msg; -}; - -#define CHNULL ((char*)NULL) - -static gboolean got_param(echld_msg_type_t type, GByteArray* ba _U_, void* data) { - struct _get_param* g = (struct _get_param*)data; - char* err_msg; - - switch (type) { - case ECHLD_PARAM: - if (g->cb) { - char* param; - char* value; - g->dec(ba,¶m,&value); - g->cb(param,value,NULL,g->cb_data); - - } - break; - case ECHLD_ERROR: { - int errnum; - g->dec_err(ba,&errnum,&err_msg); - g->cb(NULL,NULL,err_msg,g->cb_data); - break; - } - default: - err_msg = g_strdup_printf("other type='%s'",TY(type)); - g->cb(NULL,NULL,err_msg,g->cb_data); - g_free(err_msg); - break; - } - - g_free(g); - return TRUE; -} - -extern echld_state_t echld_get_param(int chld_id, const char* param, echld_param_cb_t acb, void* cb_data) { - struct _get_param* g = g_new0(struct _get_param,1); - echld_parent_encoder_t* enc; - parent_decoder_t* dec; - enc_msg_t* em; - - echld_get_all_codecs(NULL, NULL, &enc, &dec); - - em = enc->get_param(param); - - g->name = param; - g->cb = acb; - g->cb_data = cb_data; - g->dec = dec->param; - g->dec_err = dec->error; - - return echld_reqh(chld_id, ECHLD_GET_PARAM, 0, em, got_param, g); -} - -extern echld_state_t echld_set_param(int chld_id, const char* param, const char* value, echld_param_cb_t acb, void* cb_data) { - struct _get_param* g = g_new0(struct _get_param,1); - echld_parent_encoder_t* enc; - parent_decoder_t* dec; - enc_msg_t* em; - - echld_get_all_codecs(NULL, NULL, &enc, &dec); - - em = enc->set_param(param,value); - - g->name = param; - g->cb = acb; - g->cb_data = cb_data; - g->dec = dec->param; - g->dec_err = dec->error; - - return echld_reqh(chld_id, ECHLD_SET_PARAM, 0, em, got_param, g); -} - -typedef struct _close { - echld_close_cb_t cb; - void* cb_data; -} close_t; - -static gboolean closed(echld_msg_type_t type, GByteArray* ba, void* data) { - close_t* c = (close_t*)data; - parent_decoder_t* dec; - char* err_msg; - - echld_get_all_codecs(NULL, NULL, NULL, &dec); - - switch (type) { - case ECHLD_CLOSING: { - if (c->cb) { - c->cb(NULL,c->cb_data); - } - break; - } - case ECHLD_ERROR: { - int errnum; - - if ( dec->error(ba, &errnum ,&err_msg) ) { - c->cb(err_msg,c->cb_data); - g_free(err_msg); - } else { - c->cb("Canot decode error message",c->cb_data); - } - break; - } - default: - err_msg = g_strdup_printf("other type='%s'",TY(type)); - c->cb(err_msg,c->cb_data); - g_free(err_msg); - break; - } - - g_free(c); - return TRUE; - -} - -echld_state_t echld_close(int child_id, echld_close_cb_t pcb, void* cb_data) { - close_t* c = g_new0(close_t,1); - c->cb = pcb; - c->cb_data = cb_data; - - return echld_reqh(child_id,ECHLD_CLOSE_CHILD, 0, NULL, closed, c); -} - - diff --git a/echld/echld-util.h b/echld/echld-util.h deleted file mode 100644 index 557c4efc80..0000000000 --- a/echld/echld-util.h +++ /dev/null @@ -1,59 +0,0 @@ -/* echld-util.h - * utility for echld - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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. - */ -#ifndef __ECHLD_UTIL -#define __ECHLD_UTIL - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*echld_close_cb_t)(const char* error, void* data); -WS_DLL_PUBLIC echld_state_t echld_close(int child_id, echld_close_cb_t pcb, void* cb_data); - - -typedef void (*echld_ping_cb_t)(long usec, void* data); -WS_DLL_PUBLIC echld_state_t echld_ping(int child_id, echld_ping_cb_t pcb, void* cb_data); - -typedef void (*echld_param_cb_t)(const char* param, const char* value, const char* error, void* data); -WS_DLL_PUBLIC echld_state_t echld_get_param(int chld_id, const char* param, echld_param_cb_t cb, void* cb_data); -WS_DLL_PUBLIC echld_state_t echld_set_param(int chld_id, const char* param, const char* value, echld_param_cb_t acb, void* cb_data); - -typedef void (*echild_get_packet_summary_cb_t)(char* summary, void* data); -WS_DLL_PUBLIC echld_state_t echld_open_file(int child_id, const char* filename,echild_get_packet_summary_cb_t,void*); - - - -WS_DLL_PUBLIC echld_state_t echld_open_interface(int child_id, const char* intf_name, const char* params); -WS_DLL_PUBLIC echld_state_t echld_start_capture(int child_id, echild_get_packet_summary_cb_t); -WS_DLL_PUBLIC echld_state_t echld_stop_capture(int child_id); - -typedef void (*echild_get_packets_cb)(char* tree_text,void* data); -typedef void (*echild_get_buffer_cb)(char* buffer_text, void* data); -WS_DLL_PUBLIC echld_state_t echld_get_packets_range(int child_id, const char* range, echild_get_packets_cb, echild_get_buffer_cb, void* data); - -#ifdef __cplusplus -}; -#endif - -#endif diff --git a/echld/echld.h b/echld/echld.h deleted file mode 100644 index 50b541439b..0000000000 --- a/echld/echld.h +++ /dev/null @@ -1,433 +0,0 @@ -/* echld.h - * epan working child API - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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. - */ - -#ifndef __ECHLD_H -#define __ECHLD_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ws_symbol_export.h" - -#define ECHLD_VERSION "0.0" -#define ECHLD_MAJOR_VERSION 0 /* increases when existing things change */ - /* if this changes an old client may or may not work */ - -#define ECHLD_MINOR_VERSION 0 /* increases when new things are added */ - /* if just this one changes an old client will still work */ - -/* - * You should take a look to doc/README.epan_child before reading this - */ - -/* message types */ -typedef enum _echld_msg_type_t echld_msg_type_t; - -/* error types */ -typedef enum _echld_error echld_error_t; - -/* return codes */ - /* 0 is ok, everything else is ko, or timeout where applicable. */ -typedef int echld_state_t; -#define ECHLD_OK 0 -#define ECHLD_TIMEOUT -222 - -/* id for child working processes, a negative value is an error */ -typedef int echld_chld_id_t; - -/* id of requests, a negative value is an error */ -typedef int echld_reqh_id_t; - -/* id of message handlers, a negative value is an error */ -typedef int echld_msgh_id_t; - -/* enc_msg_t is an obscure object for an encoded message (a GbyteArray for now)*/ -typedef struct _GByteArray enc_msg_t; - -/* sets the codec set by name */ -typedef enum _echld_encoding { - ECHLD_ENCODING_TEXT = 'T', - ECHLD_ENCODING_XML = 'X', - ECHLD_ENCODING_JSON = 'J' -} echld_encoding_t; - -typedef int echld_bool_t; - -/* typedef for a timeval so that sys/time.h is not required in the client */ -typedef struct timeval tv_t; - -typedef void (*cleanup_cb_t)(void*); -typedef int (*main_t)(int, char**); /* a pointer to main() */ - -/* these are called after a new child is created. - * chld_id = -1 on error/timeout - */ -typedef void (*echld_new_cb_t)(void* child_data, const char* err); - -/* I will be passed to echld_initialize() */ -typedef struct _echld_init { - echld_encoding_t encoding; /* only JSON for now */ - - char* argv0; /* the value of argv[0] */ - main_t main; - - echld_new_cb_t dispatcher_hello_cb; /* child_data will be a pointer to this echld_init_t */ - - cleanup_cb_t after_fork_cb; /* to be called by dispatcher just after fork to free - the child processes from entities of the parent */ - void* after_fork_cb_data; - - cleanup_cb_t at_term_cb; /* to be called after echld_terminate() is done */ - void* at_term_cb_data; - - void* user_data; /* free for you to use */ -} echld_init_t; - -/* will initialize echld forking the dispatcher and registering protocols and taps */ -WS_DLL_PUBLIC void echld_initialize(echld_init_t*); - -/* cleans up echld and kills the server process(es) */ -WS_DLL_PUBLIC echld_state_t echld_terminate(void); - - -/* - * returning ECHLD_NO_ERROR means there has being no error - * - * errstr_ptr is a ptr to the error message string, will give NULL if no error - * usable only after the last API call, doesn't have to be freed. - * - * for managing asyncronous errors use a msgh for ECHLD_ERROR - * the response cb of reqh might be a ECHLD_ERROR message - */ -WS_DLL_PUBLIC echld_error_t echld_get_error(const char** errstr_ptr); - - -/* - * prototype of message callbacks passed to echld_reqh() and echld_msgh() - * - * type: for reqh it might be ECHLD_ERROR, ECHLD_TIMEOUT or what you expect, - * in msgh it's always the message for which it was set - * msg_buff: the encoded message - * cb_data: arbitrary data passed by the user in echld_reqh() or echld_msgh() - * - * returns TRUE if other potential handlers are to be run, false otherwise - */ -typedef echld_bool_t (*echld_msg_cb_t)(echld_msg_type_t type, enc_msg_t* msg_buff, void* cb_data); - - -/* encoding and decoding */ - - -/* - * encoder - * the enc_msg_t will be destroyed internally by the req handler - * the resulting enc_msg_t can be used in a reqh just once. - */ - -typedef struct _parent_out { - enc_msg_t* (*error)(int err, const char* text); - enc_msg_t* (*get_param)(const char* param); - enc_msg_t* (*set_param)(const char* param, const char* value); - enc_msg_t* (*close_child)(int mode); - enc_msg_t* (*open_file)(const char* filename); - enc_msg_t* (*open_interface)(const char* intf_name, const char* params); - enc_msg_t* (*get_sum)(const char* range); - enc_msg_t* (*get_tree)(const char* range); - enc_msg_t* (*get_bufer)(const char* name); - enc_msg_t* (*add_note)(int packet_number, const char* note); - enc_msg_t* (*apply_filter)(const char* filter); - enc_msg_t* (*save_file)(const char* filename, const char* params); -} echld_parent_encoder_t; - - -WS_DLL_PUBLIC echld_parent_encoder_t* echld_get_encoder(void); - - -/* - * decoder - * it returns an allocated string with the decoded response of the message, you free it. - * it destroys the enc_msg_t as well. - */ -WS_DLL_PUBLIC char* echld_decode(echld_msg_type_t, enc_msg_t*); - -/* - * Children Management Operations - */ - -WS_DLL_PUBLIC enc_msg_t* echld_new_child_params(void); - - - -/* takes the em, and param=value pairs of strings, NULL to end. - echld_new_child_params_add_params(em,param1_str,val1_str,param2_str,val2_str,NULL); */ -WS_DLL_PUBLIC void echld_new_child_params_add_params(enc_msg_t*, ...); - -WS_DLL_PUBLIC enc_msg_t* echld_new_child_params_merge(enc_msg_t*, enc_msg_t*); - -#define ECHLD_NC_PARAMS_FMT " %s='%s',\n" /* param='value' */ -/* truncate takes off last N chars from the last item's fmt or prefix on empty */ -WS_DLL_PUBLIC char* echld_new_child_params_str(enc_msg_t* em, - const char* prefix, const char* postfix, int truncate, const char* fmt) - G_GNUC_PRINTF(5, 0); - - -/* create a new worker process */ -WS_DLL_PUBLIC echld_chld_id_t echld_new(enc_msg_t* new_child_parameters, echld_new_cb_t cb, void* child_data); - -/* will return NULL on error, if NULL is also ok for you use echld_get_error() */ -WS_DLL_PUBLIC void* echld_get_data(echld_chld_id_t); - -WS_DLL_PUBLIC echld_state_t echld_set_data(echld_chld_id_t id, void* child_data); - -/* for each child call cb(id,child_data,cb_data) */ -typedef echld_bool_t (*echld_iter_cb_t)(echld_chld_id_t, void* child_data, void* cb_data); -WS_DLL_PUBLIC void echld_foreach_child(echld_iter_cb_t cb, void* cb_data); - -/* - * Request Handlers - * - */ - -/* send a request with an optional response handler - * - * ba is a enc_msg_t that contains the encoded message - * resp_cb is the callback and cb_data the data it is going to be passed if executed - * - * returns the reqh id */ -WS_DLL_PUBLIC echld_reqh_id_t echld_reqh(echld_chld_id_t, echld_msg_type_t, int usecs_timeout, enc_msg_t*, echld_msg_cb_t, void*); - -/* get callback data for a live request */ -WS_DLL_PUBLIC void* echld_reqh_get_data(echld_chld_id_t, echld_reqh_id_t); - -/* get the total timeout time for a live request, -1 is err */ -WS_DLL_PUBLIC int echld_reqh_get_to(echld_chld_id_t, echld_reqh_id_t); - -/* get the remaining timeout time for a live request, -1 is err */ -WS_DLL_PUBLIC int echld_reqh_get_remaining_to(echld_chld_id_t, echld_reqh_id_t); - -/* get the callback for a live request */ -WS_DLL_PUBLIC echld_msg_cb_t echld_reqh_get_cb(echld_chld_id_t, echld_reqh_id_t); - -/* set callback data for a live request */ -WS_DLL_PUBLIC echld_state_t echld_reqh_set_data(echld_chld_id_t, echld_reqh_id_t, void* ); - -/* get the callback for a live request */ -WS_DLL_PUBLIC echld_state_t echld_reqh_set_cb(echld_chld_id_t, echld_reqh_id_t, echld_msg_cb_t); - -/* stop receiving a live request */ -WS_DLL_PUBLIC echld_state_t echld_reqh_detach(echld_chld_id_t, echld_reqh_id_t); - - -/* - * Message Handlers - * - */ - -/* start a message handler */ -WS_DLL_PUBLIC echld_msgh_id_t echld_msgh(echld_chld_id_t, echld_msg_type_t, echld_msg_cb_t resp_cb, void* msg_data); - -/* stop it */ -WS_DLL_PUBLIC echld_state_t echld_msgh_detach(echld_chld_id_t, echld_msgh_id_t); - -/* get a msgh's data */ -WS_DLL_PUBLIC void* echld_msgh_get_data(echld_chld_id_t, echld_msgh_id_t); - -/* get a msgh's cb */ -WS_DLL_PUBLIC echld_msg_cb_t echld_msgh_get_cb(echld_chld_id_t, echld_msgh_id_t); - -/* get a msgh's type */ -WS_DLL_PUBLIC echld_msg_type_t echld_msgh_get_type(echld_chld_id_t, echld_msgh_id_t); - -/* get it all from a msgh */ -WS_DLL_PUBLIC echld_state_t echld_msgh_get_all(echld_chld_id_t, int msgh_id, echld_msg_type_t*, echld_msg_cb_t*, void**); - -/* set a msgh's data */ -WS_DLL_PUBLIC echld_state_t echld_msgh_set_data(echld_chld_id_t, int msgh_id, void* ); - -/* set a msgh's cb */ -WS_DLL_PUBLIC echld_state_t echld_msgh_set_cb(echld_chld_id_t, int msgh_id, echld_msg_cb_t); - -/* set a msgh's type */ -WS_DLL_PUBLIC echld_state_t echld_msgh_set_type(echld_chld_id_t, int msgh_id, echld_msg_type_t); - -/* set all elements of a msgh */ -WS_DLL_PUBLIC echld_state_t echld_msgh_set_all(echld_chld_id_t, int msgh_id, echld_msg_type_t, echld_msg_cb_t, void*); - - - - -/* - * Server routines - */ - -/* - * waits until something gets done - * - * returns ECHLD_TIMEOUT or ECHLD_OK if something was done - */ -WS_DLL_PUBLIC echld_state_t echld_wait(tv_t* timeout); - -#define ECHLD_WAIT() do { struct timeval tv; int rfds, efds; \ - echld_select(echld_fdset(&rfds, &efds),&rfds, NULL, &efds, NULL) \ - && echld_fd_read(&rfds, &efds); } while(0) - -/* - to be used in place of select() in the main loop of the parent code - it will serve the children pipes and return as if select() was called. -*/ -WS_DLL_PUBLIC int echld_select(int nfds, fd_set* rfds, fd_set* wfds, fd_set* efds, tv_t* timeout); - -/* or fit these two in your select loop */ - -/* returns nfds set */ -WS_DLL_PUBLIC int echld_fdset(fd_set* rfds, fd_set* efds); - -WS_DLL_PUBLIC int echld_fd_read(fd_set* rfds, fd_set* efds); - -WS_DLL_PUBLIC void echld_set_parent_dbg_level(int lvl); - - -#define ECHLD_MAX_CHILDREN 32 - -enum _echld_msg_type_t { - /* in = child to parent */ - /* out = parent to child */ - - ECHLD_NULL ='\0', /* To terminate array */ - ECHLD_ERROR = '!', /* in: an error has occurred, - * this can be a response to most messages - * some errors are sent asyncronously (some are handled internally, some are then passed) - */ - ECHLD_TIMED_OUT='/', /* in: A reqh has timed out (TO from now on) - * this can be a response to some messages - * some TOs are sent asyncronously (some are handled internally, some are then passed) - */ - - ECHLD_NEW_CHILD = '*', /* out: creates a new working child (handled internally) */ - ECHLD_HELLO = '@', /* in: the working child has being created (handled internally, then passed to msgh) */ - - ECHLD_CHILD_DEAD = '#', /* in: a child has dead (handled internally, then passed to msgh) */ - - ECHLD_CLOSE_CHILD = 'Q', /* out: close the child */ - ECHLD_CLOSING = 'q', /* in: the child is closing, error otherwise */ - /* this handled internally as msgh, if your reqh_cb uses it make sure to return TRUE */ - - ECHLD_SET_PARAM = '>', /* out: set a parameter of a child */ - ECHLD_GET_PARAM = '<', /* out: set a parameter of a child */ - ECHLD_PARAM = 'p', /* in: the parameter's new/current value, error otherwise */ - - /* capture_filter string RO: set at open_capture */ - /* monitor_mode string RW: use monitor mode if possible, error otherwise */ - /* inc_pkt_ntfy_timeout number_string RW: timeout in usec after which notification is sent if no maxpackets have arrived yet */ - /* inc_pkt_ntfy_maxpackets number_string RW: number of packets after which send a notification */ - /* auto_sum RW: get summaries automatically (without a reqh, as msgh) */ - /* auto_tree RW: get trees automatically (without a reqh, as msgh) */ - /* auto_buffer RW: get buffers automatically (without a reqh, as msgh) */ - /* cwd RW: the current working directory */ - /* list_files WO: a file listing of the current dir */ - /* interfaces RO: the interface listing */ - /* dfilter RW: initial display filter*/ - /* dfilter_chk WO: check a display filter */ - /* ... */ - - ECHLD_PING = '}', /* out: ping the child */ - ECHLD_PONG = '{', /* out: ping's response, error or TO otherwise */ - - ECHLD_OPEN_FILE = 'O', /* out: open a file */ - ECHLD_FILE_OPENED = 'o', /* in: the file has being open, error otherwise */ - - ECHLD_OPEN_INTERFACE = 'C', /* out: request an interface to be open (get ready for capture) */ - ECHLD_INTERFACE_OPENED = 'c', /* in: ready to start_capture, error otherwise */ - - ECHLD_START_CAPTURE = 'R', /* out: start capturing */ - ECHLD_CAPTURE_STARTED = 'r', /* in: the capture has started, error otherwise */ - - ECHLD_NOTIFY = '%', /* in: many things can be notified by the child: - number of packets captured/read - other events in the future (?) - */ - - ECHLD_GET_SUM = 'S', /* out: get the summaries of a range of packets (even before they are notify'd) */ - ECHLD_PACKET_SUM = 's', /* in: a packet's summary (when it arrives for a reqh) (in msgh if auto_sum )*/ - /* no timeout, the request hangs until the packets in the range are available */ - /* error at EOF or CAPTURE_STOPPED if the request is still hanging */ - - ECHLD_GET_TREE = 'G', /* out: get the decoded version of the packet */ - ECHLD_TREE = 't', /* Child -> Parent */ - /* no timeout, the request hangs until the packets in the range are available */ - /* error at EOF or CAPTURE_STOPPED if the request is still hanging */ - - - ECHLD_GET_BUFFER = 'B', /* out: get the decoded version of the packet */ - ECHLD_BUFFER = 'b', /* in: get a buffer (or what we have of it... or the next part... same reqh_id) */ - /* no timeout, the request hangs until the packets in the range are available */ - /* error at EOF or CAPTURE_STOPPED if the request is still hanging */ - - ECHLD_EOF = 'z', /* in: will be delivered when a file has being read and all pendin ntfy,sums,trees and buffs have being passed - or after capture has stopped and all pending stuff is done */ - - ECHLD_STOP_CAPTURE = 'X', /* out: stop capturing */ - ECHLD_CAPTURE_STOPPED = 'x', /* in: capture has stopped, error otherwise */ - - ECHLD_ADD_NOTE = 'N', /* out: add a note to the capture */ - ECHLD_NOTE_ADDED = 'n', /* in: a note has being added */ - - ECHLD_APPLY_FILTER = 'A', /* in: apply a filter on the open file/capture */ - ECHLD_PACKET_LIST = 'l', /* out: a packet list, or error or timeout */ - /*(or what we have of it... or the next part... same reqh_id) */ - - ECHLD_SAVE_FILE = 'W', /* out: save the open file/capture */ - ECHLD_FILE_SAVED = 'w', /* in: the file was saved */ - - - EC_ACTUAL_ERROR = 0 /* this is not used in the protocol, - it is returned for an error in calls returning a message type */ -}; - -enum _echld_error { - ECHLD_NO_ERROR = 0, - ECHLD_ERR_UNIMPLEMENTED, - ECHLD_ERR_WRONG_MSG, - ECHLD_ERR_NO_SUCH_CHILD, - ECHLD_ERR_CHILD_EXISTS, - ECHLD_ERR_UNKNOWN_PID, - ECHLD_ERR_CANNOT_FORK, - ECHLD_ERR_SET_FILTER, - ECHLD_ERR_CANNOT_OPEN_FILE, - ECHLD_ERR_CANNOT_OPEN_INTERFACE, - ECHLD_ERR_CANNOT_START_CAPTURE, - ECHLD_ERR_CANNOT_LIST_INTERFACES, - ECHLD_CANNOT_SET_PARAM, - ECHLD_CANNOT_GET_PARAM, - ECHLD_ERR_CRASHED_CHILD, - ECHLD_DECODE_ERROR, - ECHLD_ERR_OTHER -}; - -#ifdef __cplusplus -}; -#endif - -#endif diff --git a/echld/parent.c b/echld/parent.c deleted file mode 100644 index 468291ec60..0000000000 --- a/echld/parent.c +++ /dev/null @@ -1,949 +0,0 @@ -/* parent.c - * epan working child API internals - * Parent process routines and definitions - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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 "config.h" - -#include "echld-int.h" - -/** - PARENT and API - **/ - -#define MAX_PENDING_REQS 16; - -typedef struct _req { - int reqh_id; - echld_msg_cb_t cb; - void* cb_data; - struct timeval tv; -} reqh_t; - -typedef struct _hdlr { - int id; - echld_msg_type_t type; - echld_msg_cb_t cb; - void* cb_data; -} hdlr_t; - -typedef struct _echld_child { - int chld_id; - void* data; - echld_new_cb_t cb; - child_state_t state; - GArray* handlers; - GArray* reqs; -} echld_t; - -struct _echld_parent { - echld_t* children; - echld_reader_t reader; - int dispatcher_fd; - int dispatcher_pid; - int reqh_id; - GByteArray* snd; - int closing; - echld_parent_encoder_t* enc; - parent_decoder_t* dec; -} parent = {NULL,{NULL,0,NULL,-1,NULL,0},-1,-1,1,NULL,0,NULL,NULL}; - - -static int reqh_ids = 1; - - -#ifdef DEBUG_PARENT - -static int dbg_level = DEBUG_PARENT; - -static void parent_dbg(int level, const char* fmt, ...) { - va_list ap; - char str[1024]; - - if (level > dbg_level) return; - - va_start(ap,fmt); - g_vsnprintf(str,1024,fmt,ap); - va_end(ap); - - fprintf(stderr,"ParentDebug: level=%d msg='%s'\n",level,str); - fflush(stderr); -} - -#define PARENT_DBG(attrs) parent_dbg attrs -#define PARENT_SEND(BYTEARR,CHILDNUM,TYPE,R_ID) do { long st = echld_write_frame(parent.dispatcher_fd, BYTEARR, CHILDNUM, TYPE, R_ID, NULL); PARENT_DBG((1,"SEND type='%s' chld_id=%d reqh_id=%d err_msg='%s'",TY(TYPE),CHILDNUM,R_ID, ( st >= 8 ? "ok" : ((st<0)?g_strerror(errno):"?") ) )); } while(0) - -#else -#define PARENT_DBG(attrs) -#define PARENT_SEND(BYTEARR,CHILDNUM,TYPE,R_ID) echld_write_frame(parent.dispatcher_fd, BYTEARR, CHILDNUM, TYPE, R_ID, NULL) -#endif - -extern void echld_set_parent_dbg_level(int lvl) { - (dbg_level = lvl); - if (lvl > 6) { - echld_common_set_dbg(lvl,stderr,"parent"); - } - PARENT_DBG((0,"Debug Level Set: %d",lvl)); -} - - -#define PARENT_FATAL(attrs) parent_fatal attrs - -static void parent_fatal(int exit_code, const char* fmt, ...) { - va_list ap; - char str[1024]; - - va_start(ap,fmt); - g_vsnprintf(str,1024,fmt,ap); - va_end(ap); - -#ifdef DEBUG_PARENT - PARENT_DBG((0,"Fatal error: exit_code=%d str=%s",exit_code,str)); -#else - fprintf(stderr,"Fatal error: exit_code=%d str=%s",exit_code,str); -#endif - - kill(parent.dispatcher_pid,SIGTERM); - exit(exit_code); -} - -static void echld_cleanup(void) { -#if 0 - int i; -#endif - - PARENT_DBG((4,"echld_cleanup starting")); - -#if 0 - for (i=0;ichld_id)); - c->chld_id = -1; - c->data = NULL; - c->state = FREE; - g_array_set_size(c->handlers,0); - g_array_set_size(c->reqs,0); -} - - -void parent_reaper(int sig) { - int pid; - int status; - - if (sig == SIGCHLD) { - PARENT_FATAL((3333,"Must be SIGCHLD!")); - } - - pid = waitpid(-1, &status, WNOHANG); - PARENT_DBG((2,"SIGCHLD pid=%d",pid)); - - if (pid == parent.dispatcher_pid) { - - if (! parent.closing) { - /* crashed */ - sleep(120); - PARENT_FATAL((DISPATCHER_DEAD,"Dispatcher process dead")); - } - - return; - } else { - /* XXX: do we care? */ - return; - } - - return; -} - -static echld_bool_t hello_cb(echld_msg_type_t type, enc_msg_t* msg_buff, void* ud) { - echld_init_t* init = (echld_init_t*)ud; - char* err = NULL; - int errnum = 0; - - if (init && init->dispatcher_hello_cb) { - switch(type) { - case ECHLD_ERROR: - parent.dec->error(msg_buff, &errnum ,&err); - break; - case ECHLD_TIMED_OUT: - err = g_strdup("timedout"); - break; - default: - err = g_strdup_printf("Wrong MSG 'HELLO' expected, got '%s",TY(type)); - break; - case ECHLD_HELLO: - break; - } - - init->dispatcher_hello_cb(ud,err); - if (err) g_free(err); - } - - return TRUE; -} - - - -/* will initialize epan registering protocols and taps */ -void echld_initialize(echld_init_t* init) { - int from_disp[2]; - int to_disp[2]; - PARENT_DBG((1,"Echld Starting")); - - if (!init) { - PARENT_FATAL((NO_INITIALIZER,"Missing Initializer")); - } - - if (init->encoding != ECHLD_ENCODING_JSON) { - PARENT_FATAL((UNIMPLEMENTED,"Only JSON implemented")); - } - - if ( pipe(to_disp) ) { - PARENT_FATAL((DISPATCHER_PIPE_FAILED,"Failed to open pipe to dispatcher")); - } else if( pipe(from_disp) ) { - PARENT_FATAL((DISPATCHER_PIPE_FAILED,"Failed to open pipe from dispatcher")); - } else { - int pid; - int i; - - PARENT_DBG((3,"Pipes Opened fr[0]=%d fr[1]=%d to[0]=%d to[1]=%d",from_disp[0],from_disp[1],to_disp[0],to_disp[1])); - - pid = fork(); - - if ( pid < 0 ) { - PARENT_FATAL((CANNOT_FORK,"Failed to fork() reason='%s'",g_strerror(errno))); - } else if ( pid == 0) { -#ifdef PARENT_THREADS - reader_realloc_buf = child_realloc_buff; -#endif - /* child code */ - echld_cleanup(); - - if (init->after_fork_cb) - init->after_fork_cb(init->after_fork_cb_data); - - echld_dispatcher_start(to_disp,from_disp,init->argv0,init->main); - - PARENT_FATAL((SHOULD_HAVE_EXITED_BEFORE,"This shouldn't happen")); - } else { - /* parent code */ - #ifdef PARENT_THREADS - reader_realloc_buf = parent_realloc_buff; - #endif - - /* echld_common_set_dbg(9,stderr,"parent"); */ - - PARENT_DBG((3,"Dispatcher forked")); - - echld_get_all_codecs(NULL, NULL, &parent.enc, &parent.dec); - parent.children = g_new0(echld_t,ECHLD_MAX_CHILDREN); - parent.snd = g_byte_array_new(); - parent.dispatcher_fd = to_disp[1]; - parent.dispatcher_pid = pid; - - echld_init_reader(&(parent.reader),from_disp[0],4096); - - - for (i=0;idispatcher_hello_cb) echld_msgh(0, ECHLD_HELLO, hello_cb, init); - - PARENT_DBG((3,"Ready")); - } - } -} - - -extern echld_state_t echld_terminate(void) { - - parent.closing = TRUE; - PARENT_SEND(NULL,0,ECHLD_CLOSE_CHILD,++reqh_ids); - - do {;} while(sleep(1)); /* wait a full sec without signals */ - - echld_cleanup(); - close(parent.dispatcher_fd); - kill(parent.dispatcher_pid,SIGTERM); - return TRUE; -} - - - - -static echld_t* get_child(int id) { - int i; - for (i=0;ireqs->len; - reqh_t* rr = (reqh_t*)c->reqs->data; - - for(i=0; i < imax ; i++) { - if (rr[i].reqh_id == reqh_id) - return i; - } - - return -1; -} - - -static echld_state_t reqh_snd(echld_t* c, echld_msg_type_t t, GByteArray* ba, echld_msg_cb_t resp_cb, void* cb_data) { - int idx; - reqh_t* r; - int reqh_id = reqh_ids++; - - if (!c) { - PARENT_DBG((1,"REQH_SND: No such child")); - return 1; - } - - idx = reqh_id_idx(c,-1); - if (idx < 0) { - reqh_t req; - idx = c->reqs->len; - g_array_append_val(c->reqs,req); - } - - r = &(((reqh_t*)c->reqs->data)[idx]); - - r->reqh_id = reqh_id; - r->cb = resp_cb; - r->cb_data = cb_data; - - gettimeofday(&(r->tv),NULL); - - PARENT_DBG((4,"reqh_add: idx='%d'",idx)); - - PARENT_DBG((3,"REQH_SND: type='%s' chld_id=%d reqh_id=%d",TY(t), c->chld_id,reqh_id)); - - PARENT_SEND(ba,c->chld_id,t,reqh_id); - - if (ba) g_byte_array_free(ba,TRUE); /* do we? */ - - return reqh_id; -} - - -extern echld_reqh_id_t echld_reqh( - echld_chld_id_t child_id, - echld_msg_type_t t, - int usecs_timeout _U_, - enc_msg_t* ba, - echld_msg_cb_t resp_cb, - void* cb_data) { - return reqh_snd(get_child(child_id),t,ba,resp_cb,cb_data); -} - -/* get callback data for a live request */ -extern void* echld_reqh_get_data(int child_id, int reqh_id) { - echld_t* c = get_child(child_id); - int idx; - - if (!c) return NULL; - - idx = reqh_id_idx(c,reqh_id); - - if (idx >= 0) - return g_array_index(c->reqs, reqh_t, idx).cb_data; - else - return NULL; -} - -/* get the callback for a live request */ -extern echld_msg_cb_t echld_reqh_get_cb(int child_id, int reqh_id) { - echld_t* c = get_child(child_id); - int idx; - - if (!c) return NULL; - - idx = reqh_id_idx(c,reqh_id); - - if (idx >= 0) - return g_array_index(c->reqs, reqh_t, idx).cb; - else - return NULL; -} - -/* set callback data for a live request */ -extern gboolean echld_reqh_set_data(int child_id, int reqh_id, void* cb_data) { - echld_t* c = get_child(child_id); - int idx; - - if (!c) return FALSE; - - idx = reqh_id_idx(c,reqh_id); - - if (idx < 0) return FALSE; - - g_array_index(c->reqs, reqh_t, idx).cb_data = cb_data; - - return TRUE; -} - -/* get the callback for a live request */ -extern gboolean echld_reqh_set_cb(int child_id, int reqh_id, echld_msg_cb_t cb){ - echld_t* c = get_child(child_id); - int idx; - - if (!c) return FALSE; - - idx = reqh_id_idx(c,reqh_id); - - if (idx < 0) return FALSE; - - g_array_index(c->reqs, reqh_t, idx).cb = cb; - return TRUE; -} - - -/* stop receiving a live request */ -extern gboolean echld_reqh_detach(int child_id, int reqh_id) { - echld_t* c = get_child(child_id); - int idx; - - if (!c) return FALSE; - - idx = reqh_id_idx(c,reqh_id); - - if (idx < 0) return FALSE; - - g_array_remove_index(c->reqs,idx); - - return TRUE; -} - - -static echld_bool_t parent_dead_child(echld_msg_type_t type, enc_msg_t* ba, void* data) { - echld_t* c = (echld_t*)data; - char* s; - - if (type != ECHLD_CHILD_DEAD) { - PARENT_DBG((1, "Must Be ECHLD_CHILD_DEAD")); - return 1; - } - - if ( parent.dec->child_dead(ba,&s) ) { - PARENT_DBG((1,"Dead Child[%d]: %s",c->chld_id,s)); - g_free(s); - } - - parent_child_cleanup(c); - return 0; -} - -static echld_bool_t parent_get_hello(echld_msg_type_t type, enc_msg_t* ba, void* data) { - echld_t* c = (echld_t*)data; - int err_id; - char* err = NULL; - - switch (type) { - case ECHLD_HELLO: - PARENT_DBG((1,"Child[%d]: =>IDLE",c->chld_id)); - c->state = IDLE; - break; - case ECHLD_ERROR: - parent.dec->error(ba,&err_id,&err); - break; - case ECHLD_TIMED_OUT: - err = g_strdup("timedout"); - break; - default: - err = g_strdup_printf("Wrong MSG 'HELLO' expected, got '%s",TY(type)); - break; - } - - if (c->cb) - c->cb(c->data,err); - - if (err) g_free(err); - - return TRUE; -} - - - - - -int chld_cmp(const void *a, const void *b) { - return ((echld_t*)b)->chld_id - ((echld_t*)a)->chld_id; -} - -static int msgh_attach(echld_t* c, echld_msg_type_t t, echld_msg_cb_t resp_cb, void* cb_data); - -static int next_chld_id = 1; - -extern int echld_new(enc_msg_t* new_child_em, echld_new_cb_t cb, void* child_data) { - echld_t* c = get_child(-1); - - if (!c) return -1; - - c->chld_id = (next_chld_id++); - c->data = child_data; - c->state = CREATING; - c->cb = cb; - - PARENT_DBG((1,"Child[%d]: =>CREATING",c->chld_id)); - - msgh_attach(c,ECHLD_CHILD_DEAD, parent_dead_child , c); - reqh_snd(c, ECHLD_NEW_CHILD, (GByteArray*)new_child_em, parent_get_hello, c); - - return c->chld_id; -} - - - -/* XXX these fail silently */ -extern void* echld_get_data(int child_id) { - echld_t* c = get_child(child_id); - return c ? c->data : NULL; -} - -extern echld_state_t echld_set_data(echld_chld_id_t chld_id, void* data) { - echld_t* c = get_child(chld_id); - if (c) { - c->data = data; - return TRUE; - } - - return FALSE; -} - -static int msgh_idx(echld_t* c, int msgh_id) { - int i = 0; - int imax = c->handlers->len; - - for (i=0;ihandlers->data))[i].id == msgh_id) return i; - } - - return -1; -} - -/* start a message handler */ -static int msgh_attach(echld_t* c, echld_msg_type_t t, echld_msg_cb_t resp_cb, void* cb_data) { - hdlr_t h; - static int msgh_id = 1; - - h.id = msgh_id++; - h.type = t; - h.cb = resp_cb; - h.cb_data = cb_data; - - g_array_append_val(c->handlers,h); - return 0; -} - -extern int echld_msgh(int child_id, echld_msg_type_t t, echld_msg_cb_t resp_cb, void* cb_data) { - echld_t* c = get_child(child_id); - - if (c) return msgh_attach(c,t,resp_cb,cb_data); - else return -1; -} - - -/* stop it */ -static echld_state_t msgh_detach(echld_t* c, int msgh_id) { - int idx = msgh_idx(c,msgh_id); - - if (idx < 0) return -1; - - g_array_remove_index(c->handlers,idx); - - return 1; -} - -extern echld_state_t echld_msgh_detach(int child_id, int msgh_id) { - echld_t* c = get_child(child_id); - return msgh_detach(c,msgh_id); -} - -/* get a msgh's data */ - -static void* msgh_get_data(echld_t* c, int msgh_id) { - int idx = msgh_idx(c,msgh_id); - - if (idx < 0) return NULL; - - return ((hdlr_t*)(c->handlers->data))[idx].cb_data; -} - -extern void* echld_msgh_get_data(int child_id, int msgh_id) { - echld_t* c = get_child(child_id); - return msgh_get_data(c,msgh_id); -} - -/* get a msgh's cb */ -static echld_msg_cb_t msgh_get_cb(echld_t* c, int msgh_id) { - int idx = msgh_idx(c,msgh_id); - - if (idx < 0) return NULL; - - return ((hdlr_t*)(c->handlers->data))[idx].cb; -} - -extern echld_msg_cb_t echld_msgh_get_cb(int child_id, int msgh_id) { - echld_t* c = get_child(child_id); - return msgh_get_cb(c,msgh_id); -} - -/* get a msgh's type */ -static echld_msg_type_t msgh_get_type(echld_t* c, int msgh_id) { - int idx = msgh_idx(c,msgh_id); - - if (idx < 0) return EC_ACTUAL_ERROR; - - return ((hdlr_t*)(c->handlers->data))[idx].type; -} - -extern echld_msg_type_t echld_msgh_get_type(int child_id, int msgh_id) { - echld_t* c = get_child(child_id); - return c ? msgh_get_type(c,msgh_id) : EC_ACTUAL_ERROR; -} - -/* get it all from a msgh */ -static echld_state_t msgh_get_all(echld_t* c, int msgh_id, echld_msg_type_t* t, echld_msg_cb_t* cb, void** data) { - int idx = msgh_idx(c,msgh_id); - hdlr_t* h; - - if (idx < 0) return -1; - - h = &(((hdlr_t*)(c->handlers->data))[idx]); - - if (t) *t = h->type; - if (cb) *cb = h->cb; - if (data) *data = h->cb_data; - - return 0; -} - -extern gboolean echld_msgh_get_all(int child_id, int msgh_id, echld_msg_type_t* t, echld_msg_cb_t* cb, void** data) { - echld_t* c = get_child(child_id); - return c && msgh_get_all(c,msgh_id,t,cb,data); -} - -static echld_state_t msgh_set_all(echld_t* c, int msgh_id, echld_msg_type_t t, echld_msg_cb_t cb, void* data) { - int idx = msgh_idx(c,msgh_id); - hdlr_t* h; - - if (idx < 0) return -1; - - h = &(((hdlr_t*)(c->handlers->data))[idx]); - - h->type = t; - h->cb = cb; - h->cb_data = data; - - return 0; -} - -extern gboolean echld_msgh_set_all(int child_id, int msgh_id, echld_msg_type_t t, echld_msg_cb_t cb, void* data) { - echld_t* c = get_child(child_id); - return c ? msgh_set_all(c,msgh_id,t,cb,data) : FALSE; -} - -/* set a msgh's data */ -static gboolean msgh_set_data(echld_t* c, int msgh_id, void* data) { - int idx = msgh_idx(c,msgh_id); - - if (idx < 0) return FALSE; - - ((hdlr_t*)(c->handlers->data))[idx].cb_data = data; - - return TRUE; - -} - -extern gboolean echld_msgh_set_data(int child_id, int msgh_id, void* data){ - echld_t* c = get_child(child_id); - return c ? msgh_set_data(c,msgh_id,data) : FALSE; -} - -/* set a msgh's cb */ -extern gboolean msgh_set_cb(echld_t* c, int msgh_id, echld_msg_cb_t cb) { - int idx = msgh_idx(c,msgh_id); - - if (idx < 0) return FALSE; - - ((hdlr_t*)(c->handlers->data))[idx].cb = cb; - - return TRUE; -} - -extern gboolean echld_msgh_set_cb(int child_id, int msgh_id, echld_msg_cb_t cb) { - echld_t* c = get_child(child_id); - return c ? msgh_set_cb(c,msgh_id,cb) : FALSE; -} - -/* set a msgh's type */ - -static gboolean msgh_set_type(echld_t* c, int msgh_id, echld_msg_type_t t) { - int idx = msgh_idx(c,msgh_id); - - if (idx < 0) return FALSE; - - ((hdlr_t*)(c->handlers->data))[idx].type = t; - - return TRUE; -} - -extern gboolean echld_msgh_set_type(int child_id, int msgh_id, echld_msg_type_t t) { - echld_t* c = get_child(child_id); - return c ? msgh_set_type(c,msgh_id,t) : FALSE; -} - - -/* call cb(id,child_data,cb_data) for each child*/ -extern void echld_foreach_child(echld_iter_cb_t cb, void* cb_data) { - int i; - for(i=0;ichld_id,c->data,cb_data); - } -} - -static reqh_t* get_req(echld_t* c, int reqh_id) { - int idx = reqh_id_idx(c,reqh_id); - if(idx < 0) return NULL; - - return ((reqh_t*)(c->reqs->data))+idx; -} - -static hdlr_t* get_next_hdlr_for_type(echld_t* c, echld_msg_type_t t, int* cookie) { - int imax = c->handlers->len; - hdlr_t* r = NULL; - - for (;(*cookie)handlers->data))[*cookie].type == t) { - r = &( ((hdlr_t*)(c->handlers->data))[*cookie] ); - (*cookie)++; - break; - } - } - - return r; -} - -static long parent_read_frame(guint8* b, size_t len, echld_chld_id_t chld_id, echld_msg_type_t t, echld_reqh_id_t reqh_id, void* data _U_) { - echld_t* c = get_child(chld_id); - GByteArray* ba = g_byte_array_new(); - - PARENT_DBG((1,"MSG_IN<- ch=%d t='%s' rh=%d",chld_id,TY(t),reqh_id)); - g_byte_array_append(ba,b, (guint)len); - - if (c) { - reqh_t* r = get_req(c, reqh_id); - int i; - hdlr_t* h; - gboolean go_ahead = TRUE; - - if (r) { /* got that reqh_id */ - if (r->cb) { - go_ahead = r->cb(t,ba,r->cb_data); - } - - r->reqh_id = -1; - r->cb = NULL; - r->cb_data = 0; - r->tv.tv_sec = 0; - r->tv.tv_usec = 0; - - PARENT_DBG((2,"handled by reqh_id=%d msg='%s'",reqh_id,go_ahead?"retrying":"done")); - } - - i=0; - while(go_ahead && ( h = get_next_hdlr_for_type(c,t,&i))) { - if (h->cb) - go_ahead = h->cb(t,ba,h->cb_data); - - PARENT_DBG((2,"handled by t='%s' msgh_id=%d msg='%s'",TY(h->type), h->id,go_ahead?"retrying":"done")); - } - } else { - PARENT_DBG((1,"parent_read_frame: No such child")); - } - - g_byte_array_free(ba,TRUE); - return 1; -} - -extern int echld_fdset(fd_set* rfds, fd_set* efds) { - FD_SET(parent.reader.fd, rfds); - FD_SET(parent.reader.fd, efds); - FD_SET(parent.dispatcher_fd, efds); - return 2; -} - -extern int echld_fd_read(fd_set* rfds, fd_set* efds) { - int r_nfds=0; - if (FD_ISSET(parent.reader.fd,efds) || FD_ISSET(parent.dispatcher_fd,efds) ) { - /* Handle errored dispatcher */ - PARENT_DBG((1,"parent errored")); - return -1; - } - - if (FD_ISSET(parent.reader.fd,rfds)) { - PARENT_DBG((3,"reading from dispatcher")); - echld_read_frame(&(parent.reader),parent_read_frame,&(parent)); - } - - return r_nfds; -} - -extern int echld_select(int nfds _U_, fd_set* rfds, fd_set* wfds, fd_set* efds, struct timeval* timeout) { - fd_set my_rfds, my_wfds, my_efds; - int r_nfds; - - - if (rfds == NULL) { rfds = &my_rfds; FD_ZERO(rfds); } - if (wfds == NULL) { wfds = &my_wfds; FD_ZERO(wfds); } - if (efds == NULL) { efds = &my_efds; FD_ZERO(efds); } - - echld_fdset(rfds,efds); - - PARENT_DBG((5,"Select()")); - r_nfds = select(FD_SETSIZE, rfds, wfds, efds, timeout); - - echld_fd_read(rfds,efds); - - return r_nfds ; -} - -extern echld_state_t echld_wait(struct timeval* timeout) { - if ( echld_select(0, NULL, NULL, NULL, timeout) < 0) { - return -1; - } else { - return ECHLD_OK; - } -} - -enc_msg_t* echld_new_child_params(void) { - return (enc_msg_t*)g_byte_array_new(); -} - -enc_msg_t* echld_new_child_params_merge(enc_msg_t* em1, enc_msg_t* em2) { - GByteArray* ba = g_byte_array_new(); - GByteArray* b1 = (GByteArray*)em1; - GByteArray* b2 = (GByteArray*)em2; - - g_byte_array_append(ba,b1->data,b1->len); - g_byte_array_append(ba,b2->data,b2->len); - - return (enc_msg_t*)ba; -} - -char* echld_new_child_params_str(enc_msg_t* em, const char* prefix, const char* postfix, int trunc_n, const char* fmt) { - GByteArray* ba = (GByteArray*)em; - GString* str = g_string_new(prefix); - char* p = (char*) ba->data; - int tot_len = ba->len; - long rem = tot_len; - p[rem-1] = '\0'; /* make sure last char is null */ - - while(rem > 2) { - char* param = p; - long param_len = strlen(param)+1; - char* value = p + param_len; - long value_len; - - rem -= param_len; - - if (rem < 0) { - g_string_free(str,TRUE); - return NULL; - } - - value_len = strlen(value)+1; - - rem -= value_len; - p = value + value_len; - - if (rem < 0) { - g_string_free(str,TRUE); - return NULL; - } - - g_string_append_printf(str,fmt,param,value); - } - g_string_truncate(str, str->len - trunc_n); - g_string_append(str,postfix); - return g_string_free(str,FALSE); -} - -void echld_new_child_params_add_params(enc_msg_t* em, ...) { - GByteArray* ba = (GByteArray*) em; - va_list ap; - - va_start(ap,em); - do { - char* param_str = va_arg(ap, char*); - - if (param_str) { - char* val_str = va_arg(ap, char*); - - g_byte_array_append(ba, (guint8*) param_str, (guint)strlen(param_str)+1); - g_byte_array_append(ba, (guint8*) val_str, (guint)strlen(val_str)+1); - continue; - } - - break; - } while(1); - va_end(ap); - -} - - diff --git a/echld_test.c b/echld_test.c deleted file mode 100644 index b2d192edf3..0000000000 --- a/echld_test.c +++ /dev/null @@ -1,422 +0,0 @@ -/* echld-test.c - * basic test framework for echld - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copyright (c) 2013 by Luis Ontanon - * - * 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 - -#ifdef HAVE_FCNTL_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include -#include -#include -#include - -#include -#include - -#include "echld/echld.h" -#include "echld/echld-util.h" - -#include "epan/epan.h" -#include "wsutil/str_util.h" - -typedef char* (*cmd_cb_t)(char** params, char** err); - -typedef struct _cmd_t { - const char* txt; - cmd_cb_t cb; - int args_taken; - const char* help; -} cmd_t; - - -#define MAX_PARAMSETS 16 - -static enc_msg_t* paramsets[MAX_PARAMSETS] = { - NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL -}; - -static int nps = 0; - -static char* ps_cmd(char** pars _U_, char** err _U_) { - int n_id = nps++; - - if (n_id >= MAX_PARAMSETS) { - *err = g_strdup("Max Num of Paramsets reached"); - return NULL; - } - - paramsets[n_id] = echld_new_child_params(); - - return g_strdup_printf("New Paramset ps_id=%d",n_id); -} - -static char* psadd_cmd(char** params _U_, char** err) { - int ps_id = (int) strtol(params[1], NULL, 10); - - if (ps_id >= nps) { - *err = g_strdup_printf("No paramset pd_is=%d",ps_id); - return NULL; - } - - echld_new_child_params_add_params(paramsets[ps_id], params[2], params[3], NULL); - - return g_strdup_printf("PSAdd ps_id=%d %s='%s'", ps_id, params[2], params[3]); -} - -static char* psmerge_cmd(char** params, char** err) { - int ps1_id = (int) strtol(params[1], NULL, 10); - int ps2_id = (int) strtol(params[2], NULL, 10); - int n_id; - - if (ps1_id >= nps) { - *err = g_strdup_printf("No paramset pd_is=%d",ps1_id); - return NULL; - } - - if (ps2_id >= nps) { - *err = g_strdup_printf("No paramset pd_is=%d",ps2_id); - return NULL; - } - - n_id = nps++; - - if (n_id >= MAX_PARAMSETS) { - *err = g_strdup_printf("Max Num of Paramsets reached"); - return NULL; - } - - paramsets[n_id] = echld_new_child_params_merge(paramsets[ps1_id],paramsets[ps2_id]); - - return g_strdup_printf("Merged Paramset ps1_id=%d ps2_id=%d ps_id=%d",ps1_id, ps2_id, n_id); -} - -static char* new_child_cmd(char** params, char** err) { - int ps_id = (int) strtol(params[1], NULL, 10); - int child; - - if (ps_id >= nps) { - *err = g_strdup_printf("No paramset pd_is=%d",ps_id); - return NULL; - } - - child = echld_new(paramsets[ps_id],NULL,NULL); - - if (child <= 0) { - *err = g_strdup("No child\n"); - return NULL; - } - - return g_strdup_printf("New chld_id=%d\n",child); -} - - -void ping_cb(long usec, void* data) { - int ping_id = *((int*)data); - - if (usec >= 0) { - fprintf(stdout, "Ping ping_id=%d returned in %dus\n",ping_id,(int)usec); - } else { - fprintf(stdout, "Ping ping_id=%d erored\n",ping_id); - } - - g_free(data); -} - - -static char* ping_cmd(char** params, char** err) { - int child = (int) strtol(params[1], NULL, 10); - static int ping_id = 0; - int* ping_data = g_new(int,1); - - *ping_data = ping_id++; - - if (!echld_ping(child,ping_cb,ping_data)) { - *err = g_strdup_printf("Could not send ping child=%d",child); - return NULL; - } else { - return g_strdup_printf("Ping sent child=%d",child); - } -} - -void param_cb(const char* param, const char* value, const char* error, void* data _U_) { - if (error) { - fprintf(stdout, "Param Set Error msg=%s\n", error ); - } else { - fprintf(stdout, "Param: param='%s' val='%s'\n", param, value ); - } -} - -static char* set_cmd(char** params, char** err) { - int child = (int) strtol(params[1], NULL, 10); - char* param = params[2]; - char* value = params[3]; - - if ( ! echld_set_param(child,param,value,param_cb,NULL) ) { - *err = g_strdup_printf("Failed to SET child=%d param='%s' value='%s'",child,param,value); - return NULL; - } else { - return g_strdup_printf("Set command sent child=%d param='%s' value='%s'",child,param,value); - } -} - -static char* get_cmd(char** params, char** err) { - int child = (int) strtol(params[1], NULL, 10); - char* param = params[2]; - - if ( ! echld_get_param(child,param,param_cb,NULL) ) { - *err = g_strdup_printf("Failed to GET child=%d param='%s'",child,param); - return NULL; - } else { - return g_strdup_printf("Get command sent child=%d param='%s'",child,param); - } -} - -static void close_cb(const char* error, void* data) { - if (error) { - fprintf(stdout, "Close Error msg=%s\n", error ); - } else { - fprintf(stdout, "Closed: child=%d\n", *((int*)data) ); - } -} - -static char* close_cmd(char** params, char** err) { - int child = (int) strtol(params[1], NULL, 10); - int* cmdp = g_new(int,1); - *cmdp = child; - if ( ! echld_close(child,close_cb,cmdp) ) { - *err = g_strdup_printf("Could not close child=%d",child); - return NULL; - } else { - return g_strdup_printf("CLose command sent child=%d",child); - } -} -int keep_going = 1; - -static char* quit_cmd(char** params _U_, char** err _U_) { - keep_going = 0; - return g_strdup("Quitting"); -} - -static char* help_cmd(char**, char**); - -static char* open_file_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* prepare_capture_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* start_capture_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* get_sum_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* get_tree_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* get_buf_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* stop_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* note_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* apply_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* save_cmd(char** pars _U_, char** err _U_) { - *err = g_strdup("Not Implemented"); - return NULL; -} - -static char* run_cmd(char** pars, char** err _U_); - - - - -cmd_t commands[] = { - { "QUIT", quit_cmd, 0, "QUIT"}, - { "HELP", help_cmd, 0, "HELP"}, - { "RUN", run_cmd, 1, "RUN filename"}, - { "PS", ps_cmd, 1, "PS [dummy]"}, - { "PSADD", psadd_cmd, 4, "PSADD ps_id param value"}, - { "PSMERGE", psmerge_cmd, 4, "PSMERGE ps_id ps_id"}, - { "NEW", new_child_cmd, 1, "NEW ps_id"}, - { "PING", ping_cmd, 1, "PING child_id"}, - { "SET", set_cmd, 3, "SET child_id param_name param_val"}, - { "GET", get_cmd, 2, "GET child_id param_name"}, - { "CLOSE", close_cmd, 1, "CLOSE child_id"}, - { "FILE", open_file_cmd, 2, "FILE child_id filename"}, - { "PREP", prepare_capture_cmd, 2, "PREP child_id intfname params"}, - { "START",start_capture_cmd,1,"START child_id"}, - { "SUM", get_sum_cmd,2,"SUM child_id packet_range"}, - { "TREE", get_tree_cmd,2,"TREE child_id packet_range"}, - { "BUFF", get_buf_cmd,2,"BUFF child_id buffer_name"}, - { "STOP", stop_cmd,1,"STOP child_id"}, - { "NOTE", note_cmd,1,"NOTE child_id framenum note..."}, - { "APPLY", apply_cmd,1,"APPLY child_id dfilter"}, - { "SAVE", save_cmd,1,"SAVE child_id filename params"}, - { NULL, NULL, 0, NULL } -}; - -static char* help_cmd(char** params _U_, char** err _U_) { - GString* out = g_string_new("Commands:\n"); - cmd_t* c = commands; - - for (;c->txt;c++) { - g_string_append_printf(out,"%s\n",c->help); - } - return g_string_free(out,FALSE); -} - - -static int invoke_cmd(FILE* in_fp) { - size_t len; - char* cmd_line; - - if(( cmd_line = fgetln(in_fp,&len) )) { - cmd_t* c = commands; - cmd_line[len] = 0; - g_strchomp(cmd_line); - - for (;c->txt;c++) { - if ( strcasestr(cmd_line, c->txt) == cmd_line ) { - char** params = g_strsplit(cmd_line, " ", c->args_taken+1); - char* err = NULL; - char* str = c->cb(params,&err); - - if (err) { - fprintf(stdout, "Error: %s\n", err); - g_free(err); - } else { - fprintf(stdout, "%s\n", str); - g_free(str); - } - - g_strfreev(params); - return TRUE; - } - } - - fprintf(stdout, "Error: no such command %s\n", cmd_line); - return TRUE; - } else { - return FALSE; - } -} - -static char* run_cmd(char** pars, char** err _U_) { - FILE* fp = ws_stdio_fopen(pars[1],"r"); - while(invoke_cmd(fp)) { ; } - fclose(fp); - return NULL; -} - - -int got_param = 0; - - -int main(int argc _U_, char** argv _U_) { - struct timeval tv; - int tot_cycles = 0; - echld_init_t init = {ECHLD_ENCODING_JSON,argv[0],main,NULL,NULL,NULL,NULL,NULL,NULL}; - - - tv.tv_sec = 5; - tv.tv_usec = 0; - - echld_set_parent_dbg_level(5); - - echld_initialize(&init); - - do { - fd_set rfds; - fd_set efds; - int nfds; - - FD_ZERO(&rfds); - FD_ZERO(&efds); - FD_SET(0,&rfds); - FD_SET(0,&efds); - - nfds = echld_select(FD_SETSIZE, &rfds, NULL, &efds, &tv); - - if (FD_ISSET(0,&rfds)) { - invoke_cmd(stdin); - } - - tot_cycles++; - } while( keep_going ); - - fprintf(stderr, "Done: tot_cycles=%d\n", tot_cycles ); - - echld_terminate(); - return 0; -} - -/* - * Editor modelines - http://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: - */