From baee2e21f7020c77f41001bd759f8d41063eba3f Mon Sep 17 00:00:00 2001 From: Luis Ontanon Date: Mon, 1 Jul 2013 01:49:34 +0000 Subject: ANother iteration, - started harvesting pieces from tshark. - fixed? signal handlers - interactive test program very hard to debug... set follow-on-fork doesn't seem to work on my mac. Need linux I guess... svn path=/trunk/; revision=50273 --- echld/Makefile.common | 1 + echld/child.c | 111 +++++++++++++++++++++++++++++++++++++++++++------- echld/common.c | 1 + echld/dispatcher.c | 91 +++++++++++++++++++++++++++++++++-------- echld/echld-int.h | 29 ++++++++++--- echld/echld-util.c | 55 ++++++++++++++++++++++++- echld/echld-util.h | 4 ++ 7 files changed, 252 insertions(+), 40 deletions(-) (limited to 'echld') diff --git a/echld/Makefile.common b/echld/Makefile.common index f80eef7c6b..cd19253c90 100644 --- a/echld/Makefile.common +++ b/echld/Makefile.common @@ -44,6 +44,7 @@ LIBECHLD_INCLUDES = \ LIBECHLD_MORE_SRC = \ ../capture_opts.c \ ../capture_stop_conditions.c \ + ../capture-pcap-util-unix.c \ ../cfutils.c \ ../clopts_common.c \ ../sync_pipe_write.c \ diff --git a/echld/child.c b/echld/child.c index 19a04f40e4..db0f6e395d 100644 --- a/echld/child.c +++ b/echld/child.c @@ -51,6 +51,8 @@ typedef struct _child { child_decoder_t* dec; // epan stuff + //capture_file cfile; + } echld_child_t; @@ -129,6 +131,13 @@ static long dbg_resp(GByteArray* em, echld_msg_type_t t) { static struct timeval close_sleep_time; + +static void sig_term(int sig _U_) { + CHILD_DBG((3,"Terminated, Closing")); + exit(0); +} + + void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id) { close_sleep_time.tv_sec = CHILD_CLOSE_SLEEP_TIME / 1000000; @@ -153,6 +162,14 @@ void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int p 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 */ } @@ -195,32 +212,96 @@ static echld_bool_t param_set_cwd(char* val , char** err ) { return TRUE; } -#define COOKIE_SIZE 1024 -static char* cookie = NULL; -static char* param_get_cookie(char** err ) { - if (cookie) - return g_strdup(cookie); +static unsigned packet_count = 0; +static char* param_get_packet_count(char** err) { - *err = g_strdup("cookie not set"); - return NULL; + 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_cookie(char* val , char** err _U_) { - if (cookie) g_free(cookie); +static char* dfilter = NULL; +dfilter_t *df = NULL; - cookie = g_strdup(val); - return TRUE; +static echld_bool_t param_set_dfilter(char* val , char** err _U_) { + dfilter_t *dfn = NULL; + if ( dfilter_compile(val, &dfn) ) { + if (dfilter) g_free(dfilter); + if (df) dfilter_free(df); + df = dfn; + dfilter = g_strdup(val); + return TRUE; + } else { + *err = g_strdup(dfilter_error_msg); + return FALSE; + } +} + +static char* param_get_dfilter(char** err _U_) { return g_strdup(dfilter ? 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=["); + char* s; + 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, "]}"); + + s=str->str; + g_string_free(str,FALSE); + return s; } +PARAM_BOOL(quiet,FALSE); static param_t params[] = { #ifdef DEBUG_CHILD - {"dbg_level", param_get_dbg_level, param_set_dbg_level}, + PARAM(dbg_level), # endif - {"cookie",param_get_cookie,param_set_cookie}, - {"cwd",param_get_cwd,param_set_cwd}, + PARAM(profile), + PARAM(cwd), + PARAM(dfilter), + RO_PARAM(packet_count), + RO_PARAM(file_list), + PARAM(quiet), {NULL,NULL,NULL} }; @@ -510,7 +591,7 @@ static long child_receive(guint8* b, size_t len, echld_chld_id_t chld_id, echld_ misencoded: // dump the misencoded message (b,blen) - child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"misencoded msg msg_type='%s'",TY(type); + child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"misencoded msg msg_type='%s'",TY(type)); return 0; wrong_state: diff --git a/echld/common.c b/echld/common.c index 7eee1817a3..5670175cb1 100644 --- a/echld/common.c +++ b/echld/common.c @@ -73,6 +73,7 @@ static struct _st_map st_map[] = { { READING, "READING"}, { CAPTURING, "CAPTURING"}, { DONE, "DONE"}, + { CLOSING, "CLOSING"}, { CLOSED, "CLOSED"}, { ERRORED, "ERRORED"}, {0,NULL} diff --git a/echld/dispatcher.c b/echld/dispatcher.c index e300c06c1d..910f54255c 100644 --- a/echld/dispatcher.c +++ b/echld/dispatcher.c @@ -36,6 +36,7 @@ struct dispatcher_child { echld_reader_t reader; int write_fd; int pid; + int reqh_id; gboolean closing; }; @@ -290,10 +291,10 @@ static char* param_get_interfaces(char** err) { return s; } -static struct timeval disp_loop_timeout; +static long disp_loop_timeout_usec = DISPATCHER_WAIT_INITIAL; static char* param_get_loop_to(char** err _U_) { - return g_strdup_printf("%d.%06ds",(int)disp_loop_timeout.tv_sec, (int)disp_loop_timeout.tv_usec ); + return g_strdup_printf("%fs", (((float)disp_loop_timeout_usec)/1000000.0) ); } static echld_bool_t param_set_loop_to(char* val , char** err ) { @@ -305,17 +306,39 @@ static echld_bool_t param_set_loop_to(char* val , char** err ) { return FALSE; } - disp_loop_timeout.tv_sec = usec / 1000000; - disp_loop_timeout.tv_usec = usec % 1000000; + disp_loop_timeout_usec = usec; return TRUE; } +GString *comp_info_str; +GString *runtime_info_str; + +static char* param_get_version(char** err _U_) { + char* str; + + str = g_strdup_printf("Echld " VERSION "%s\n" + "\n" + "%s" + "\n" + "%s" + "\n" + "%s", + wireshark_svnversion, get_copyright_info(), comp_info_str->str, + runtime_info_str->str); + + g_string_free(runtime_info_str,TRUE); + g_string_free(comp_info_str,TRUE); + + return str; +} + static param_t disp_params[] = { #ifdef DEBUG_DISPATCHER {"dbg_level", param_get_dbg_level, param_set_dbg_level}, # endif + {"version",param_get_version,NULL}, {"loop_timeout",param_get_loop_to,param_set_loop_to}, {"interfaces",param_get_interfaces,NULL}, {NULL,NULL,NULL} }; @@ -351,6 +374,7 @@ static void dispatcher_clear_child(struct dispatcher_child* c) { c->reader.fd = -1; c->write_fd = -1; c->pid = -1; + c->reqh_id = -1; c->closing = FALSE; } @@ -361,13 +385,34 @@ static void set_dumpcap_pid(int pid) { static void preinit_epan(char* argv0, int (*main)(int, char **)) { char* init_progfile_dir_error = init_progfile_dir(argv0, main); + comp_info_str = g_string_new("Compiled "); + get_compiled_version_info(comp_info_str, NULL, epan_get_compiled_version_info); + + runtime_info_str = g_string_new("Running "); + get_runtime_version_info(runtime_info_str, NULL); + if (init_progfile_dir_error) { DISP_FATAL((CANNOT_PREINIT_EPAN,"Failed epan_preinit: msg='%s'",init_progfile_dir_error)); } + /* Add it to the information to be reported on a crash. */ + ws_add_crash_info("Echld " VERSION "%s\n%s\n%s", + wireshark_svnversion, comp_info_str->str, runtime_info_str->str); + capture_sync_set_fetch_dumpcap_pid_cb(set_dumpcap_pid); +#ifdef _WIN32 + arg_list_utf_16to8(argc, argv); + create_app_running_mutex(); +#if !GLIB_CHECK_VERSION(2,31,0) + g_thread_init(NULL); +#endif +#endif /* _WIN32 */ + + + init_process_policies(); + /* Here we do initialization of parts of epan that will be the same for every child we fork */ DISP_DBG((2,"epan preinit")); @@ -392,7 +437,6 @@ void dispatcher_reaper(int sig) { struct dispatcher_child* cc = dispatcher->children; int max_children = dispatcher->max_children; int pid = waitpid(-1, &status, WNOHANG); - GByteArray* em; int reqh_id_save = dispatcher->reqh_id; dispatcher->reqh_id = 0; @@ -409,9 +453,10 @@ void dispatcher_reaper(int sig) { struct dispatcher_child* c = &(cc[i]); if ( c->pid == pid ) { if (c->closing || dispatcher->closing) { - em = dispatcher->enc.to_parent->child_dead("OK"); + 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( @@ -433,12 +478,12 @@ void dispatcher_reaper(int sig) { 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); - DISP_WRITE(dispatcher->parent_out, em, c->chld_id, ECHLD_CHILD_DEAD, 0); dispatcher_clear_child(c); - g_byte_array_free(em,TRUE); dispatcher->reqh_id = reqh_id_save; return; } @@ -474,8 +519,9 @@ static long dispatch_to_parent(guint8* b, size_t len, echld_chld_id_t chld_id, e GByteArray in_ba; struct dispatcher_child* c = (struct dispatcher_child*)data; - dispatcher->reqh_id = reqh_id; + dispatcher->reqh_id = c->reqh_id = reqh_id; + in_ba.data = b; in_ba.len = (guint)len; @@ -487,7 +533,10 @@ static long dispatch_to_parent(guint8* b, size_t len, echld_chld_id_t chld_id, e case ECHLD_ERROR: break; case ECHLD_TIMED_OUT: break; case ECHLD_HELLO: CHLD_SET_STATE(c,IDLE); break; - case ECHLD_CLOSING: CHLD_SET_STATE(c,CLOSED); 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; @@ -771,12 +820,10 @@ static long dispatch_to_child(guint8* b, size_t len, echld_chld_id_t chld_id, ec - int dispatcher_loop(void) { int parent_out = dispatcher->parent_out; int parent_in = dispatcher->parent_in.fd; struct dispatcher_child* children = dispatcher->children; - volatile int pforce = 0; DISP_DBG((5,"LOOP in_fd=%d out_fd=%d",parent_in, parent_out)); @@ -786,7 +833,7 @@ int dispatcher_loop(void) { struct dispatcher_child* c; int nfds; int nchld = 0; - + struct timeval disp_loop_timeout; FD_ZERO(&rfds); FD_ZERO(&efds); @@ -803,16 +850,21 @@ int dispatcher_loop(void) { } } - DISP_DBG((5,"Select()ing nchld=%d usecs=%d",nchld,disp_loop_timeout.tv_usec)); + 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'",strerror(errno) )); continue; } - if ( pforce || FD_ISSET(parent_in, &rfds)) { + if ( FD_ISSET(parent_in, &rfds)) { long st = echld_read_frame(&(dispatcher->parent_in), dispatch_to_child, dispatcher); if (st < 0) { @@ -865,6 +917,9 @@ int dispatcher_loop(void) { 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; @@ -873,9 +928,6 @@ void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, in int dbg_fd; #endif - disp_loop_timeout.tv_sec = 0; - disp_loop_timeout.tv_usec = DISPATCHER_WAIT_INITIAL; - DISP_DBG_INIT(); #ifdef DEBUG_DISPATCHER dbg_fd = fileno(debug_fp); @@ -889,6 +941,9 @@ void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, in 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; diff --git a/echld/echld-int.h b/echld/echld-int.h index 1c5e563915..0bb9dd34fe 100644 --- a/echld/echld-int.h +++ b/echld/echld-int.h @@ -61,9 +61,11 @@ #include "capture_session.h" #include "capture_ifinfo.h" #include "capture_sync.h" - -#include "../epan/filesystem.h" - +#include "version_info.h" +#include "wsutil/crash_info.h" +#include "wsutil/privileges.h" +#include "epan/filesystem.h" +#include "epan/epan.h" #include "echld.h" #ifdef __cplusplus @@ -71,8 +73,6 @@ extern "C" { #endif /* XXX these shouldn't be needed */ -typedef struct _column_info column_info; -typedef struct _proto_node proto_tree; typedef struct tvbuff tvb_t; struct _hdr { @@ -104,6 +104,7 @@ typedef enum _cst { READING, CAPTURING, DONE, + CLOSING, CLOSED=-1, ERRORED=-2 } child_state_t; @@ -145,6 +146,22 @@ typedef struct _param { echld_bool_t (*set)(char* val , char** err); } param_t; +#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_printf("%s",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) {#Name, param_get_ ## Name, param_set_ ## Name} +#define RO_PARAM(Name) {#Name, param_get_ ## Name, NULL} +#define WO_PARAM(Name) {#Name, NULL, param_set_ ## Name} + /* 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*); @@ -216,7 +233,7 @@ extern void echld_unused(void); #define DEBUG_PARENT 5 /* timers */ -#define DISPATCHER_WAIT_INITIAL 999999 /* almost 1s */ +#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 */ diff --git a/echld/echld-util.c b/echld/echld-util.c index a6552ac7aa..d86adc3758 100644 --- a/echld/echld-util.c +++ b/echld/echld-util.c @@ -29,6 +29,8 @@ #include "echld-int.h" #include "echld-util.h" +#include + struct _ping { struct timeval tv; echld_ping_cb_t cb; @@ -109,7 +111,7 @@ static gboolean got_param(echld_msg_type_t type, GByteArray* ba _U_, void* data) break; } default: - err_msg = g_strdup_printf("other type='%c'",type); + err_msg = g_strdup_printf("other type='%s'",TY(type)); g->cb(NULL,NULL,err_msg,g->cb_data); g_free(err_msg); break; @@ -157,3 +159,54 @@ extern echld_state_t echld_set_param(int chld_id, const char* param, const char* 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 index a1a625d570..2d7e9de4d8 100644 --- a/echld/echld-util.h +++ b/echld/echld-util.h @@ -30,6 +30,10 @@ 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); -- cgit v1.2.1