From 99013aefa81f2d3e14d3e063574e6dea4045d0b1 Mon Sep 17 00:00:00 2001 From: Luis Ontanon Date: Thu, 27 Jun 2013 19:00:01 +0000 Subject: [PATCH] MS: list interfaces! svn path=/trunk/; revision=50195 --- capture_sync.c | 18 +++++++++- capture_sync.h | 3 ++ echld/Makefile.am | 8 +++-- echld/Makefile.common | 22 ++++++++++++ echld/Makefile.nmake | 21 ++++++++++++ echld/common.c | 13 ++++--- echld/dispatcher.c | 57 ++++++++++++++++++++++-------- echld/echld-int.h | 22 +++++++++--- echld/echld-util.c | 80 +++++++++++++++++++++++++++++++++++++++++++ echld/echld-util.h | 12 +++++-- echld/echld.h | 10 +++++- echld/parent.c | 8 ++--- echld_test.c | 41 +++++++++++----------- 13 files changed, 261 insertions(+), 54 deletions(-) create mode 100644 echld/Makefile.nmake diff --git a/capture_sync.c b/capture_sync.c index 9a2136814a..f8a6f83f28 100644 --- a/capture_sync.c +++ b/capture_sync.c @@ -118,6 +118,9 @@ static void pipe_convert_header(const guchar *header, int header_len, char *indi static ssize_t pipe_read_block(int pipe_fd, char *indicator, int len, char *msg, char **err_msg); +static void (*fetch_dumpcap_pid)(int) = NULL; + + void capture_session_init(capture_session *cap_session, void *cf) { @@ -652,6 +655,9 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, voi _exit(1); } + if (fetch_dumpcap_pid && cap_session->fork_child > 0) + fetch_dumpcap_pid(cap_session->fork_child); + sync_pipe_read_fd = sync_pipe[PIPE_READ]; #endif @@ -879,6 +885,9 @@ sync_pipe_open_command(char** argv, int *data_read_fd, _exit(1); } + if (fetch_dumpcap_pid && *fork_child > 0) + fetch_dumpcap_pid(*fork_child); + *data_read_fd = data_pipe[PIPE_READ]; *message_read_fd = sync_pipe[PIPE_READ]; #endif @@ -1862,9 +1871,12 @@ sync_pipe_wait_for_child(int fork_child, gchar **msgp) fork_child_status); ret = -1; } - } else { + } else if (errno != ECHILD) { *msgp = g_strdup_printf("Error from waitpid(): %s", g_strerror(errno)); ret = -1; + } else { + /* errno == ECHILD ; echld might have already reaped the child */ + ret = fetch_dumpcap_pid ? 0 : -1; } #endif @@ -2077,4 +2089,8 @@ sync_pipe_kill(int fork_child) } } +void capture_sync_set_fetch_dumpcap_pid_cb(void(*cb)(int pid)) { + fetch_dumpcap_pid = cb; +} + #endif /* HAVE_LIBPCAP */ diff --git a/capture_sync.h b/capture_sync.h index 8da65956fe..507abfae7d 100644 --- a/capture_sync.h +++ b/capture_sync.h @@ -133,4 +133,7 @@ capture_input_cfilter_error_message(capture_session *cap_session, guint i, extern void capture_input_closed(capture_session *cap_session, gchar *msg); +/* set a callback to be called after fork with the pid of the forked child */ +extern void capture_sync_set_fetch_dumpcap_pid_cb(void(*cb)(int pid)); + #endif /* capture_sync.h */ diff --git a/echld/Makefile.am b/echld/Makefile.am index 4affaf8d74..c58662507a 100644 --- a/echld/Makefile.am +++ b/echld/Makefile.am @@ -43,20 +43,24 @@ if HAVE_WARNINGS_AS_ERRORS AM_CFLAGS += -Werror endif -AM_CPPFLAGS = -I$(srcdir)/.. +AM_CPPFLAGS = -I$(srcdir)/.. -I$(srcdir)/../wiretap libechld_la_SOURCES = \ $(LIBECHLD_SRC) \ - $(LIBECHLD_INCLUDES) + $(LIBECHLD_INCLUDES) \ + $(LIBECHLD_MORE_SRC) + libechld_la_DEPENDENCIES= ../epan/libwireshark.la \ + ../wiretap/libwiretap.la \ ../wsutil/libwsutil.la libechld_la_LIBADD = \ ../epan/libwireshark.la \ ../wsutil/libwsutil.la \ + ../wiretap/libwiretap.la \ @GLIB_LIBS@ EXTRA_DIST = \ diff --git a/echld/Makefile.common b/echld/Makefile.common index 902caa7828..f80eef7c6b 100644 --- a/echld/Makefile.common +++ b/echld/Makefile.common @@ -40,3 +40,25 @@ LIBECHLD_INCLUDES = \ echld-int.h \ echld-util.h \ echld.h + +LIBECHLD_MORE_SRC = \ + ../capture_opts.c \ + ../capture_stop_conditions.c \ + ../cfutils.c \ + ../clopts_common.c \ + ../sync_pipe_write.c \ + ../capture-pcap-util.c \ + ../capture-pcap-util.h \ + ../capture-pcap-util-int.h \ + ../conditions.c \ + ../pcapio.c \ + ../ringbuffer.c \ + ../capture_sync.c \ + ../version_info.c \ + ../capture_ifinfo.c \ + ../ws80211_utils.c + +OTHER = \ + ../dumpcap.c + + diff --git a/echld/Makefile.nmake b/echld/Makefile.nmake new file mode 100644 index 0000000000..15798f9d9b --- /dev/null +++ b/echld/Makefile.nmake @@ -0,0 +1,21 @@ +## Makefile for building wireshark.exe with Microsoft C and nmake +## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake +# +# $Id: Makefile.nmake 47938 2013-02-28 14:09:46Z rbalint $ + +include ..\config.nmake +include +include ..\Makefile.nmake.inc + +############### no need to modify below this line ######### + +include Makefile.common + +CFLAGS=$(WARNINGS_ARE_ERRORS) $(STANDARD_CFLAGS) \ + /I. /I.. $(GLIB_CFLAGS) \ + /I$(PCAP_DIR)\include -DWS_BUILD_DLL + +.c.obj:: + $(CC) $(CFLAGS) -Fd.\ -c $< + +# no fork() on windows this needs some thoughts... diff --git a/echld/common.c b/echld/common.c index 2071fc6bd0..548fd8127b 100644 --- a/echld/common.c +++ b/echld/common.c @@ -30,6 +30,7 @@ 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; @@ -42,21 +43,22 @@ static void common_dbg(int level, const char* fmt, ...) { va_end(ap); if (dbg_fp) { - fprintf(dbg_fp,"Common: level=%d msg='%s'\n",level,str); + 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 -extern void echld_common_set_dbg(int level, FILE* fp) { - dbg_level = level; - dbg_fp = fp; -} /** @@ -404,6 +406,7 @@ static enc_msg_t* x3str_enc(const char* s1, const char* s2, const char* s3) { static echld_parent_encoder_t parent_encoder = { int_str_enc, + str_enc, x2str_enc, int_enc, str_enc, diff --git a/echld/dispatcher.c b/echld/dispatcher.c index 6edff8ae5e..d139c6ac6d 100644 --- a/echld/dispatcher.c +++ b/echld/dispatcher.c @@ -57,6 +57,7 @@ struct dispatcher { parent_decoder_t* from_child; } dec; + int dumpcap_pid; gboolean closing; }; @@ -67,8 +68,7 @@ struct dispatcher* dispatcher; static int debug_lvl = DEBUG_DISPATCHER; static FILE* debug_fp = NULL; -#define DCOM echld_common_set_dbg(debug_lvl,debug_fp) -#define DFL fflush(debug_fp) +#define DCOM() echld_common_set_dbg(debug_lvl,debug_fp,"Disp") int dispatcher_debug(int level, const char* fmt, ...) { va_list ap; @@ -111,15 +111,15 @@ static echld_bool_t param_set_dbg_level(char* val , char** err ) { } debug_lvl = lvl; - DCOM; + 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 = fopen(fname,"a"); DCOM; DISP_DBG((0,"Log Started")); } while(0) +#define DISP_DBG_INIT() do { debug_fp = stderr; DCOM(); } while(0) +#define DISP_DBG_START(fname) do { debug_fp = 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='%c' rh=%d msg='%s'",FD,CH,T,RH, (dbg_r>0?"ok":strerror(errno)))), dbg_r ) #else #define DISP_DBG(attrs) @@ -258,7 +258,8 @@ static char* param_get_interfaces(char** err) { GList* if_list; char* s; *err = NULL; - if_list = capture_interface_list(&err_no, err); + + if_list = capture_interface_list(&err_no, err, NULL); if (*err) { return NULL; @@ -333,9 +334,24 @@ static void dispatcher_clear_child(struct dispatcher_child* c) { c->closing = 0; } -static void preinit_epan(void) { - DISP_DBG((2,"preinit_epan")); +static void set_dumpcap_pid(int pid) { + dispatcher->dumpcap_pid = pid; +} + +static void preinit_epan(char* argv0, int (*main)(int, char **)) { + char* init_progfile_dir_error = init_progfile_dir(argv0, main); + + + if (init_progfile_dir_error) { + DISP_FATAL((CANNOT_PREINIT_EPAN,"Failed epan_preinit: msg='%s'",init_progfile_dir_error)); + } + + capture_sync_set_fetch_dumpcap_pid_cb(set_dumpcap_pid); + /* Here we do initialization of parts of epan that will be the same for every child we fork */ + + DISP_DBG((2,"epan preinit")); + } @@ -357,9 +373,13 @@ void dispatcher_reaper(int sig) { 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; if (sig != SIGCHLD) { DISP_DBG((1,"Reaper got wrong signal=%d",sig)); + dispatcher->reqh_id = reqh_id_save; return; } @@ -398,11 +418,20 @@ void dispatcher_reaper(int sig) { 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; } } + if (pid == dispatcher->dumpcap_pid) { + dispatcher->dumpcap_pid = 0; + dispatcher->reqh_id = reqh_id_save; + return; + } + dispatcher_err(ECHLD_ERR_UNKNOWN_PID, "Unkown child pid: %d", pid); + dispatcher->reqh_id = reqh_id_save; + } @@ -603,7 +632,7 @@ static long dispatch_to_child(guint8* b, size_t len, echld_chld_id_t chld_id, ec if (chld_id == 0) { /* these are messages to the dispatcher itself */ - DISP_DBG((2,"Message to Dispatcher")); + DISP_DBG((2,"Parent => Dispatcher")); switch(type) { case ECHLD_CLOSE_CHILD: dispatcher_destroy(); @@ -691,7 +720,7 @@ static long dispatch_to_child(guint8* b, size_t len, echld_chld_id_t chld_id, ec } else { struct dispatcher_child* c; - DISP_DBG((2,"Message to Child")); + DISP_DBG((2,"Parent => Child")); if (! (c = dispatcher_get_child(dispatcher, chld_id)) ) { dispatcher_err(ECHLD_ERR_NO_SUCH_CHILD, "wrong chld_id %d", chld_id); @@ -841,7 +870,7 @@ int dispatcher_loop(void) { } -void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds) { +void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, int (*main)(int, char **)) { static struct dispatcher d; #ifdef DEBUG_DISPATCHER int dbg_fd; @@ -875,6 +904,7 @@ void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds) { d.nchildren = 0; d.reqh_id = -1; d.pid = getpid(); + d.dumpcap_pid = 0; close(out_pipe_fds[0]); close(in_pipe_fds[1]); @@ -883,12 +913,9 @@ void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds) { DISP_DBG((2,"Dispatcher Configured pid=%d parent_in=%d parent_out=%d",d.pid,in_pipe_fds[0],d.parent_out)); - preinit_epan(); + preinit_epan(argv0,main); exit(dispatcher_loop()); } -extern void echld_dispatcher_unused(void) { - DISP_FATAL((1,"UNUSED")); -} diff --git a/echld/echld-int.h b/echld/echld-int.h index 1085301afc..bb530fc960 100644 --- a/echld/echld-int.h +++ b/echld/echld-int.h @@ -57,11 +57,19 @@ +#include "capture_opts.h" +#include "capture_session.h" #include "capture_ifinfo.h" +#include "capture_sync.h" +#include "../epan/filesystem.h" #include "echld.h" +#ifdef __cplusplus +extern "C" { +#endif + /* XXX these shouldn't be needed */ typedef struct _column_info column_info; typedef struct _proto_node proto_tree; @@ -122,7 +130,7 @@ typedef struct _echld_reader { #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); +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); @@ -142,8 +150,6 @@ typedef struct _child_in { 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); @@ -189,7 +195,7 @@ extern void echld_child_initialize(int pipe_from_parent, int pipe_to_parent, int extern int echld_child_loop(void); /* never returns*/ -extern void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds); +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); @@ -216,6 +222,14 @@ extern void echld_unused(void); #define SHOULD_HAVE_EXITED_BEFORE 129 #define DISPATCHER_PIPE_FAILED 130 #define TERMINATED 140 +#define CANNOT_PREINIT_EPAN 141 +#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 index 02d4e3c2f5..a6552ac7aa 100644 --- a/echld/echld-util.c +++ b/echld/echld-util.c @@ -77,3 +77,83 @@ extern echld_state_t echld_ping(int chld_id, echld_ping_cb_t pcb, void* cb_data) } +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='%c'",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); +} + diff --git a/echld/echld-util.h b/echld/echld-util.h index d7be39a78d..4c236b5854 100644 --- a/echld/echld-util.h +++ b/echld/echld-util.h @@ -26,12 +26,16 @@ #ifndef __ECHLD_UTIL #define __ECHLD_UTIL +#ifdef __cplusplus +extern "C" { +#endif 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_list_interface_cb_t)(char* intf_name, char* params, void* cb_data); -WS_DLL_PUBLIC echld_state_t echld_list_interfaces(int child_id, echld_list_interface_cb_t, 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*); @@ -45,4 +49,8 @@ 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 index 77738213b6..c757760992 100644 --- a/echld/echld.h +++ b/echld/echld.h @@ -27,6 +27,10 @@ #ifndef __ECHLD_H #define __ECHLD_H +#ifdef __cplusplus +extern "C" { +#endif + #include "ws_symbol_export.h" #define ECHLD_VERSION "0.0" @@ -74,7 +78,7 @@ typedef int echld_bool_t; typedef struct timeval tv_t; /* will initialize epan registering protocols and taps */ -WS_DLL_PUBLIC void echld_initialize(echld_encoding_t); +WS_DLL_PUBLIC void echld_initialize(echld_encoding_t, char* argv0, int (*main)(int, char **)); /* cleans up (?) echld and kills the server process(es) */ WS_DLL_PUBLIC echld_state_t echld_terminate(void); @@ -135,6 +139,7 @@ typedef echld_bool_t (*echld_msg_cb_t)(echld_msg_type_t type, enc_msg_t* msg_buf 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); @@ -374,5 +379,8 @@ enum _echld_error { ECHLD_ERR_OTHER }; +#ifdef __cplusplus +}; +#endif #endif diff --git a/echld/parent.c b/echld/parent.c index 53028121bb..6496e4f6e8 100644 --- a/echld/parent.c +++ b/echld/parent.c @@ -100,7 +100,7 @@ static void parent_dbg(int level, const char* fmt, ...) { extern void echld_set_parent_dbg_level(int lvl) { (dbg_level = lvl); if (lvl > 6) { - echld_common_set_dbg(lvl,stderr); + echld_common_set_dbg(lvl,stderr,"parent"); } PARENT_DBG((0,"Debug Level Set: %d",lvl)); } @@ -183,7 +183,7 @@ void parent_reaper(int sig) { } /* will initialize epan registering protocols and taps */ -void echld_initialize(echld_encoding_t enc) { +void echld_initialize(echld_encoding_t enc, char* argv0, int (*main)(int, char **)) { int from_disp[2]; int to_disp[2]; @@ -213,7 +213,7 @@ void echld_initialize(echld_encoding_t enc) { #endif /* child code */ echld_cleanup(); - echld_dispatcher_start(to_disp,from_disp); + echld_dispatcher_start(to_disp,from_disp,argv0,main); PARENT_FATAL((SHOULD_HAVE_EXITED_BEFORE,"This shoudln't happen")); } else { /* parent code */ @@ -221,7 +221,7 @@ void echld_initialize(echld_encoding_t enc) { reader_realloc_buf = parent_realloc_buff; #endif - echld_common_set_dbg(9,stderr); + echld_common_set_dbg(9,stderr,"parent"); PARENT_DBG((3,"Dispatcher forked")); diff --git a/echld_test.c b/echld_test.c index 872d53adfb..8218f80a3c 100644 --- a/echld_test.c +++ b/echld_test.c @@ -68,36 +68,36 @@ void ping_cb(long usec, void* data _U_) { } } +void param_cb(const char* param, const char* value, const char* error, void* data _U_) { + if (error) { + fprintf(stderr, "Param Set Error msg=%s\n", error ); + return; + } -int main(int argc, char** argv) { + fprintf(stderr, "Param: param='%s' val='%s'\n", param, value ); + +} + + +int main(int argc _U_, char** argv _U_) { struct timeval tv; int tot_cycles = 0; - int max_cycles = 30; - int npings; + int max_cycles = 20; + int npings = 2; tv.tv_sec = 0; tv.tv_usec = 250000; echld_set_parent_dbg_level(5); - switch(argc) { - case 1: - npings = 3; - break; - case 2: - npings = (int)atoi(argv[1]); - break; - default: - fprintf(stderr, "usage: %s [num pings, default=10]\n",argv[0]); - return 1; - } - - max_cycles = npings*4; - - echld_initialize(ECHLD_ENCODING_JSON); - + echld_initialize(ECHLD_ENCODING_JSON,argv[0],main); do { - if ( (tot_cycles > npings) && npings && npings-- ) echld_ping(0,ping_cb,NULL); + if ( (tot_cycles > 2) && npings > 0 && npings-- ) echld_ping(0,ping_cb,NULL); + + if ( tot_cycles == 10) echld_set_param(0,"dbg_level","5",param_cb,NULL); + + if ( tot_cycles == 12) echld_get_param(0,"interfaces",param_cb,NULL); + tot_cycles++; echld_wait(&tv); } while( (pings < npings) || (tot_cycles < max_cycles)); @@ -109,3 +109,4 @@ int main(int argc, char** argv) { } +void main_window_update(void) {}