MSWSP: use GuidPropertySet_find_guid() in parse_CFullPropSpec()
[wireshark-wip.git] / echld / child.c
blobe40de30a411aa3073b2f53f2b938da7f2c48dfcb
1 /* echld_child.c
2 * epan working child internals
3 * Child process routines and definitions
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copyright (c) 2013 by Luis Ontanon <luis@ontanon.org>
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "echld-int.h"
30 // echld_
32 typedef struct _child {
33 child_state_t state;
35 int pid;
36 int dispatcher_pid;
37 int chld_id;
38 int reqh_id;
39 echld_reader_t parent;
40 struct _fds {
41 int pipe_to_parent;
42 int pipe_from_dumpcap;
43 int pipe_to_dumpcap;
44 int file_being_read;
45 } fds;
47 struct timeval started;
48 struct timeval now;
50 child_encoder_t* enc;
51 child_decoder_t* dec;
53 // epan stuff
54 char* cf_name;
55 char* cfilter;
56 char* dfilter;
59 // capture_file cfile;
60 dfilter_t* df;
62 } echld_child_t;
64 static echld_epan_stuff_t* stuff = NULL;
66 static echld_child_t child;
68 struct _st_map {
69 child_state_t id;
70 const char* str;
74 #ifdef DEBUG_CHILD
75 static int debug_lvl = DEBUG_CHILD;
76 static FILE* debug_fp = NULL;
77 #define DBG_BUF_LEN 1024
79 #define DCOM()
81 int child_debug(int level, const char* fmt, ...) {
82 va_list ap;
83 char str[DBG_BUF_LEN];
85 if (debug_lvl<level) return 1;
87 va_start(ap, fmt);
88 vsnprintf(str,DBG_BUF_LEN,fmt,ap);
89 va_end(ap);
91 fprintf(debug_fp, "child[%d-%d]: reqh_id=%d debug_lvl=%d message='%s'\n",
92 child.chld_id, child.pid, child.reqh_id, level, str);
94 return 1;
97 static char* param_get_dbg_level(char** err _U_) {
98 return g_strdup_printf("%d",debug_lvl);
101 static echld_bool_t param_set_dbg_level(char* val , char** err ) {
102 char* p;
103 int lvl = (int)strtol(val, &p, 10);
105 if (p<=val) {
106 *err = g_strdup("not an integer");
107 return FALSE;
108 } else if (lvl < 0 || lvl > 5) {
109 *err = g_strdup_printf("invalid level=%d (min=0 max=5)",lvl);
110 return FALSE;
113 debug_lvl = lvl;
114 DCOM();
115 return TRUE;
119 static long dbg_resp(GByteArray* em, echld_msg_type_t t) {
120 long st = echld_write_frame(child.fds.pipe_to_parent, em, child.chld_id, t, child.reqh_id, NULL);
121 child_debug(1, "SND fd=%d ch=%d ty='%s' rh=%d msg='%s'",
122 child.fds.pipe_to_parent, child.chld_id, TY(t), child.reqh_id, (st>0?"ok":strerror(errno)) );
123 return st;
126 #define CHILD_DBG(attrs) ( child_debug attrs )
127 #define CHILD_DBG_INIT() do { debug_fp = stderr; DCOM(); } while(0)
128 #define CHILD_DBG_START(fname) do { debug_fp = fopen(fname,"a"); DCOM(); CHILD_DBG((0,"Log Started")); } while(0)
129 #define CHILD_RESP(BA,T) dbg_resp(BA,T)
130 #define CHILD_STATE(ST) do { DISP_DBG((0,"State %s => %s")) } while(0)
131 #else
132 #define CHILD_DBG(attrs)
133 #define CHILD_DBG_INIT()
134 #define CHILD_DBG_START(fname)
135 #define CHILD_RESP(BA,T) echld_write_frame(child.fds.pipe_to_parent,(BA),child.chld_id,T,child.reqh_id,NULL)
136 #endif
139 static struct timeval close_sleep_time;
142 static void sig_term(int sig _U_) {
143 CHILD_DBG((3,"Terminated, Closing"));
144 exit(0);
147 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) {
148 stuff = es;
150 close_sleep_time.tv_sec = CHILD_CLOSE_SLEEP_TIME / 1000000;
151 close_sleep_time.tv_usec = CHILD_CLOSE_SLEEP_TIME % 1000000;
153 child.chld_id = chld_id;
154 child.state = IDLE;
155 child.pid = getpid();
156 child.dispatcher_pid = getppid();
157 child.reqh_id = reqh_id;
158 echld_init_reader( &(child.parent), pipe_from_parent,4096);
159 child.fds.pipe_to_parent = pipe_to_parent;
160 child.fds.pipe_from_dumpcap = -1;
161 child.fds.pipe_to_dumpcap = -1;
162 child.fds.file_being_read = -1;
163 gettimeofday(&child.started,NULL);
164 child.now.tv_sec = child.started.tv_sec;
165 child.now.tv_usec = child.started.tv_usec;
167 echld_get_all_codecs(&(child.enc), &(child.dec), NULL, NULL);
169 CHILD_DBG_INIT();
170 CHILD_DBG((5,"Child Initialized ch=%d from=%d to=%d rq=%d",chld_id, pipe_from_parent, pipe_to_parent, reqh_id));
172 /*clear signal handlers */
173 signal(SIGALRM,SIG_DFL);
174 signal(SIGTERM,sig_term);
175 signal(SIGPIPE,SIG_DFL);
176 signal(SIGINT,SIG_DFL);
177 signal(SIGABRT,SIG_DFL);
178 signal(SIGHUP,SIG_DFL);
180 /* epan stuff */
185 void child_err(int e, unsigned reqh_id, const char* fmt, ...) {
186 size_t len= 1024;
187 gchar err_str[len];
188 va_list ap;
189 static GByteArray* ba;
191 va_start(ap, fmt);
192 g_vsnprintf(err_str,len,fmt,ap);
193 va_end(ap);
195 CHILD_DBG((0,"error='%s'",err_str));
197 ba = child.enc->error(e, err_str);
198 echld_write_frame(child.fds.pipe_to_parent, ba, child.chld_id, ECHLD_ERROR, reqh_id, NULL);
199 g_byte_array_free(ba,TRUE);
203 static char* param_get_cwd(char** err ) {
204 char* pwd = getcwd(NULL, 128);
206 if (!pwd) {
207 *err = g_strdup(strerror(errno));
209 return pwd;
212 static echld_bool_t param_set_cwd(char* val , char** err ) {
213 /* XXX SANITIZE */
214 if (chdir(val) != 0) {
215 *err = g_strdup_printf("cannot chdir reas='%s'",strerror(errno));
216 return FALSE;
219 return TRUE;
223 static unsigned packet_count = 0;
224 static char* param_get_packet_count(char** err) {
226 if (child.state != CAPTURING || child.state != READING) {
227 *err = g_strdup("Must be reading or in-capture for packet_count");
228 return NULL;
230 return g_strdup_printf("%d",packet_count);
235 static echld_bool_t param_set_dfilter(char* val , char** err _U_) {
236 dfilter_t *dfn = NULL;
238 if (child.state != IDLE && child.state != DONE ) {
239 *err = g_strdup("Only while idle or done");
240 return FALSE;
241 } else if ( dfilter_compile(val, &dfn) ) {
242 if (child.dfilter) g_free(child.dfilter);
243 if (child.df) dfilter_free(child.df);
244 child.df = dfn;
245 child.dfilter = g_strdup(val);
246 return TRUE;
247 } else {
248 *err = g_strdup(dfilter_error_msg);
249 return FALSE;
253 static char* param_get_dfilter(char** err _U_) { return g_strdup(child.dfilter ? child.dfilter : ""); }
255 char* param_profile = NULL;
257 static echld_bool_t param_set_profile(char* val , char** err ) {
259 if (child.state != IDLE) {
260 *err = g_strdup_printf("Cannot set Profile \"%s\", too late.", val);
261 return FALSE;
264 if (profile_exists (val, FALSE)) {
265 set_profile_name (val);
266 if (param_profile) g_free(param_profile);
267 param_profile = g_strdup(val);
268 return TRUE;
269 } else {
270 *err = g_strdup_printf("Configuration Profile \"%s\" does not exist", val);
271 return FALSE;
275 static char* param_get_profile(char** err _U_) { return g_strdup(param_profile ? param_profile : ""); }
277 static char* param_get_file_list(char** err) {
278 GError* gerror = NULL;
279 GDir* dir = g_dir_open(".", 0, &gerror);
280 GString* str = g_string_new("{ what='file_list', files=[");
281 char* s;
282 const char* file;
284 if (gerror) {
285 *err = g_strdup_printf("Failed to open curr dir reason='%s'",gerror->message);
286 return NULL;
289 while(( file = g_dir_read_name(dir) )) {
290 g_string_append_printf(str,"{filename='%s'},\n",file);
292 g_dir_close(dir);
294 g_string_truncate(str, str->len-2); /* ',\n' */
295 g_string_append(str, "]}");
297 s=str->str;
298 g_string_free(str,FALSE);
299 return s;
302 #ifdef PCAP_NG_DEFAULT
303 static int out_file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
304 #else
305 static int out_file_type = WTAP_FILE_TYPE_SUBTYPE_PCAP;
306 #endif
308 static echld_bool_t param_set_out_file_type(char* val, char** err) {
309 int oft = wtap_short_string_to_file_type(val);
311 if (oft < 0) {
312 *err = g_strdup_printf("\"%s\" isn't a valid capture file type", val);
313 return FALSE;
314 } else {
315 out_file_type = oft;
316 return TRUE;
320 static char* param_get_out_file_type(char** err _U_) {
321 return g_strdup_printf("%s(%d): %s",
322 wtap_file_type_short_string(out_file_type),
323 out_file_type, wtap_file_type_string(out_file_type));
327 static echld_bool_t param_set_add_hosts_file(char* val, char** err) {
328 if (add_hosts_file(val)) {
329 return TRUE;
330 } else {
331 *err = g_strdup_printf("Can't read host entries from \"%s\"",val);
332 return FALSE;
336 PARAM_BOOL(quiet,FALSE);
337 PARAM_BOOL(start_capture,FALSE);
338 PARAM_BOOL(push_details,FALSE);
339 PARAM_BOOL(print_hex,FALSE);
341 static char* param_get_params(char** err _U_);
343 static param_t child_params[] = {
344 #ifdef DEBUG_CHILD
345 PARAM(dbg_level,"Debug Level (0<int<5)"),
346 # endif
347 PARAM(profile,"Configuration Profile (str)"),
348 PARAM(cwd,"Current Directory (str)"),
349 PARAM(dfilter,"Dispay Filter (str)"),
350 RO_PARAM(packet_count,"Packets Read/Captured So Far (str)"),
351 RO_PARAM(file_list,"List of Files in the Current Dir"),
352 PARAM(start_capture,"Automatically start capture"),
353 PARAM(quiet,"Quiet Mode"),
354 PARAM(push_details,"Whether details of dissection should be passed"),
355 PARAM(print_hex,"Output in hex"),
356 PARAM(out_file_type,"Output File Type"),
357 WO_PARAM(add_hosts_file,"Add a Hosts File"),
358 RO_PARAM(params,"This List"),
359 {NULL,NULL,NULL,NULL}
362 static char* param_get_params(char** err _U_) {
363 return paramset_get_params_list(child_params,PARAM_LIST_FMT);
366 static void child_open_file(char* filename) {
367 CHILD_DBG((2,"CMD open file filename='%s'",filename));
368 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"open file not implemented yet!");
369 child.state = READING;
372 static void child_open_interface(char* intf, char* pars) {
373 CHILD_DBG((2,"CMD open interface intf='%s', params='%s'",intf,pars));
374 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"open interface not implemented yet!");
375 child.state = READY;
378 static void child_start_capture(void) {
379 CHILD_DBG((2,"CMD start capture"));
380 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"start capture not implemented yet!");
381 child.state = CAPTURING;
384 static void child_stop_capure(void) {
385 CHILD_DBG((2,"CMD stop capture"));
386 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"stop capture not implemented yet!");
387 child.state = DONE;
390 static void child_get_summary(char* range) {
391 CHILD_DBG((2,"CMD get summary range='%s'",range));
392 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"get_summary not implemented yet!");
395 static void child_get_tree(char* range) {
396 CHILD_DBG((2,"CMD get tree range='%s'",range));
397 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"get_tree not implemented yet!");
400 static void child_get_buffer(char* name) {
401 CHILD_DBG((2,"CMD get buffer name='%s'",name));
402 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"get_buffer not implemented yet!");
405 static void child_add_note(int framenum, char* note) {
406 CHILD_DBG((2,"CMD add note framenum=%d note='%s'",framenum,note));
407 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"add_note not implemented yet!");
410 static void child_apply_filter(char* filter) {
411 CHILD_DBG((2,"CMD apply filter filter='%s'",filter));
412 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"apply_filter not implemented yet!");
415 static void child_save_file(char* filename, char* pars) {
416 CHILD_DBG((2,"CMD save file filename='%s' params='%s'",filename,pars));
417 child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"save_file not implemented yet!");
420 static long child_receive(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_) {
421 GByteArray ba;
422 GByteArray* gba;
423 char* err = NULL;
425 child.reqh_id = reqh_id;
427 CHILD_DBG((2,"RCVD type='%s' len='%d'",TY(type),len));
429 // gettimeofday(&(child.now), NULL);
431 if (child.chld_id != chld_id) {
432 child_err(ECHLD_ERR_WRONG_MSG,reqh_id,
433 "chld_id: own:%d given:%d msg_type='%s'",child.chld_id,chld_id,TY(type));
434 return 0;
437 ba.data = b;
438 ba.len = (guint)len;
440 switch(type) {
441 case ECHLD_NEW_CHILD: {
442 child.state = CREATING;
443 if ( !paramset_apply_em(child_params,(enc_msg_t*)&ba, &err) ) {
444 child_err(ECHLD_ERR_CRASHED_CHILD,reqh_id,
445 "Initial Paramset Error '%s'",err);
446 } else {
447 child.state = IDLE;
448 CHILD_RESP(NULL,ECHLD_HELLO);
450 break;
452 case ECHLD_PING:
453 CHILD_DBG((1,"PONG"));
454 CHILD_RESP(&ba,ECHLD_PONG);
455 break;
456 case ECHLD_SET_PARAM:{
457 char* param;
458 char* value;
460 if ( child.dec->set_param && child.dec->set_param(b,len,&param,&value) ) {
461 if (! paramset_apply_set (child_params, param, value, &err) ) {
462 child_err(ECHLD_CANNOT_SET_PARAM,reqh_id,"%s",err);
463 g_free(err);
464 return 0;
467 gba = child.enc->param(param,value);
468 CHILD_RESP(gba,ECHLD_PARAM);
469 g_byte_array_free(gba,TRUE);
470 CHILD_DBG((1,"Set Param: param='%s' value='%s'",param,value));
472 break;
473 } else {
474 goto misencoded;
477 case ECHLD_GET_PARAM: {
478 char* param;
479 if ( child.dec->get_param && child.dec->get_param(b,len,&param) ) {
480 char* val;
482 if (! (val = paramset_apply_get (child_params, param, &err)) ) {
483 child_err(ECHLD_CANNOT_GET_PARAM,reqh_id,"%s",err);
484 g_free(err);
485 return 0;
488 gba = child.enc->param(param,val);
489 CHILD_RESP(gba,ECHLD_PARAM);
490 g_byte_array_free(gba,TRUE);
491 CHILD_DBG((2,"Get Param: param='%s' value='%s'",param,val));
492 break;
493 } else {
494 goto misencoded;
497 case ECHLD_CLOSE_CHILD:
498 CHILD_RESP(NULL,ECHLD_CLOSING);
499 CHILD_DBG((3,"Closing"));
500 select(0,NULL,NULL,NULL,&close_sleep_time);
501 CHILD_DBG((1,"Bye"));
502 exit(0);
503 break;
504 case ECHLD_OPEN_FILE: {
505 char* filename;
506 if (child.state != IDLE) goto wrong_state;
508 if ( child.dec->open_file(b,len,&filename) ) {
509 child_open_file(filename);
510 } else {
511 child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode open_file");
513 break;
515 case ECHLD_OPEN_INTERFACE: {
516 char* intf;
517 char* pars;
519 if (child.state != IDLE) goto wrong_state;
521 if ( child.dec->open_interface(b,len,&intf,&pars) ) {
522 child_open_interface(intf,pars);
523 } else {
524 child_err(ECHLD_DECODE_ERROR,reqh_id, "cannot decode open_interface");
526 break;
528 case ECHLD_START_CAPTURE:{
529 if (child.state != READY) goto wrong_state;
530 child_start_capture();
531 break;
533 case ECHLD_STOP_CAPTURE: {
534 if (child.state != CAPTURING) goto wrong_state;
535 child_stop_capure();
536 break;
538 case ECHLD_GET_SUM: {
539 char* range;
541 if (child.state != CAPTURING || child.state != READING || child.state != DONE) goto wrong_state;
543 if ( child.dec->get_sum(b,len,&range) ) {
544 child_get_summary(range);
545 } else {
546 child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_summary");
548 break;
550 case ECHLD_GET_TREE:{
551 char* range;
553 if (child.state != CAPTURING && child.state != READING && child.state != DONE) goto wrong_state;
555 if ( child.dec->get_tree(b,len,&range) ) {
556 child_get_tree(range);
557 } else {
558 child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_tree");
560 break;
562 case ECHLD_GET_BUFFER:{
563 char* name;
565 if (child.state != CAPTURING && child.state != READING && child.state != DONE) goto wrong_state;
567 if ( child.dec->get_buffer(b,len,&name) ) {
568 child_get_buffer(name);
569 } else {
570 child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_buffer");
572 break;
574 case ECHLD_ADD_NOTE: {
575 int framenum;
576 char* note;
578 if (child.state != CAPTURING && child.state != READING && child.state != DONE) goto wrong_state;
580 if ( child.dec->add_note(b,len,&framenum,&note) ) {
581 child_add_note(framenum,note);
582 } else {
583 child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode get_buffer");
585 break;
587 case ECHLD_APPLY_FILTER: {
588 char* filter;
590 if (child.state != DONE) goto wrong_state;
592 if ( child.dec->apply_filter(b,len,&filter) ) {
593 child_apply_filter(filter);
594 } else {
595 child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode apply_filter");
597 break;
599 case ECHLD_SAVE_FILE: {
600 char* filename;
601 char* pars;
603 if (child.state != DONE) goto wrong_state;
605 if ( child.dec->save_file(b,len,&filename,&pars) ) {
606 child_save_file(filename,pars);
607 } else {
608 child_err(ECHLD_DECODE_ERROR,reqh_id,"cannot decode save_file");
610 break;
612 default:
613 child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"wrong message: chld_id=%d msg_type='%s'",chld_id,TY(type));
614 break;
617 return 0;
619 misencoded:
620 // dump the misencoded message (b,blen)
621 child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"misencoded msg msg_type='%s'",TY(type));
622 return 0;
624 wrong_state:
625 child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"unexpected message: received in wrong state='%s', msg_type='%s'",ST(child.state),TY(type));
626 return 0;
630 static int child_dumpcap_read(void) {
631 // this folk manages the reading of dumpcap's pipe
632 // it has to read interface descriptions when doing so
633 // and managing capture during capture
634 CHILD_DBG((2,"child_dumpcap_read"));
635 return FALSE;
638 static void child_file_read(void) {
642 int echld_child_loop(void) {
643 int disp_from = child.parent.fd;
644 int disp_to = child.fds.pipe_to_parent;
646 #ifdef DEBUG_CHILD
647 int step = 0;
648 #endif
650 CHILD_DBG((0,"entering child_loop()"));
652 do {
653 fd_set rfds;
654 fd_set wfds;
655 fd_set efds;
656 struct timeval timeout;
657 int nfds;
658 gboolean captured = FALSE;
660 FD_ZERO(&rfds);
661 FD_ZERO(&wfds);
662 FD_ZERO(&efds);
664 FD_SET(disp_from,&rfds);
665 FD_SET(disp_from,&efds);
666 FD_SET(disp_to,&efds);
669 if (child.fds.pipe_from_dumpcap > 0) {
670 FD_SET(child.fds.pipe_from_dumpcap,&rfds);
673 #ifdef DEBUG_CHILD
674 if (step <= 20) CHILD_DBG((4,"child_loop: select()ing step=%d",step++));
675 #endif
676 timeout.tv_sec = 0;
677 timeout.tv_usec = 999999;
679 nfds = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout);
680 #ifdef DEBUG_CHILD
681 if (step <= 20) CHILD_DBG((4,"child_loop: select()ed nfds=%d",nfds));
682 #endif
684 if ( FD_ISSET(disp_from,&efds) ) {
685 CHILD_DBG((0,"Broken Parent Pipe 'From' step=%d",step));
686 break;
689 if ( FD_ISSET(disp_to,&efds) ) {
690 CHILD_DBG((0,"Broken Parent Pipe 'To' step=%d",step));
691 break;
694 if (child.fds.pipe_from_dumpcap > 0 && FD_ISSET(child.fds.pipe_from_dumpcap,&efds) ) {
695 CHILD_DBG((0,"Broken Dumpcap Pipe step=%d",step));
696 break;
699 if (FD_ISSET(disp_from, &rfds)) {
700 long st = echld_read_frame(&(child.parent), child_receive, &child);
702 #ifdef DEBUG_CHILD
703 step = 0;
704 #endif
706 if (st < 0) {
707 CHILD_DBG((0,"Read Frame Failed step=%d",step));
708 return (int)st;
712 if (child.fds.pipe_from_dumpcap > 0 && FD_ISSET(child.fds.pipe_from_dumpcap,&rfds) ) {
714 #ifdef DEBUG_CHILD
715 step = 0;
716 #endif
717 captured = child_dumpcap_read();
720 if ( child.state == READING || captured ) {
721 child_file_read();
723 } while(1);
726 CHILD_RESP(NULL,ECHLD_CLOSING);
727 CHILD_DBG((3,"Closing"));
728 return 222;