aboutsummaryrefslogtreecommitdiffstats
path: root/echld
diff options
context:
space:
mode:
authorLuis Ontanon <luis.ontanon@gmail.com>2013-07-01 01:49:34 +0000
committerLuis Ontanon <luis.ontanon@gmail.com>2013-07-01 01:49:34 +0000
commitbaee2e21f7020c77f41001bd759f8d41063eba3f (patch)
treed192ec49151c48a6862b1694b0aefba14fb8b158 /echld
parente03edbf713c9af37b452e1c3f1917f1e2c69ca72 (diff)
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
Diffstat (limited to 'echld')
-rw-r--r--echld/Makefile.common1
-rw-r--r--echld/child.c111
-rw-r--r--echld/common.c1
-rw-r--r--echld/dispatcher.c91
-rw-r--r--echld/echld-int.h29
-rw-r--r--echld/echld-util.c55
-rw-r--r--echld/echld-util.h4
7 files changed, 252 insertions, 40 deletions
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 <glib.h>
+
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);