2 * Synchronisation between Ethereal capture parent and child instances
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #ifdef HAVE_SYS_WAIT_H
45 # include <sys/wait.h>
50 * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
51 * macros) on UNIX systems that don't have them.
54 # define WIFEXITED(status) (((status) & 0177) == 0)
57 # define WIFSTOPPED(status) (((status) & 0177) == 0177)
60 # define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
63 # define WEXITSTATUS(status) ((status) >> 8)
66 # define WTERMSIG(status) ((status) & 0177)
69 # define WCOREDUMP(status) ((status) & 0200)
72 # define WSTOPSIG(status) ((status) >> 8)
76 #include <epan/packet.h>
77 #include <epan/prefs.h>
83 #include "capture_sync.h"
84 #include "simple_dialog.h"
87 #include "capture-wpcap.h"
96 #include <process.h> /* For spawning child process */
99 /* Win32 needs the O_BINARY flag for open() */
106 static char *sync_pipe_signame(int);
110 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
111 static void sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report);
113 /* Size of buffer to hold decimal representation of
114 signed/unsigned 64-bit int */
115 #define SP_DECISIZE 20
118 * Indications sent out on the sync pipe.
120 #define SP_FILE 'F' /* the name of the recently opened file */
121 #define SP_ERROR_MSG 'E' /* error message */
122 #define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
123 #define SP_DROPS 'D' /* count of packets dropped in capture */
124 #define SP_QUIT 'Q' /* capture quit message (from parent to child) */
127 /* write a message to the recipient pipe in the standard format
128 (3 digit message length (excluding length and indicator field),
129 1 byte message indicator and the rest is the message) */
131 pipe_write_block(int pipe, char indicator, int len, const char *msg)
133 char lenbuf[3+1+1]; /* 3 digit len + indicator + zero terminator */
136 /*g_warning("write %d enter", pipe);*/
138 g_assert(len < 1000);
139 g_assert(indicator < '0' || indicator > '9');
141 /* write header (3 digit len + indicator) */
142 g_snprintf(lenbuf, 5, "%03u%c", len, indicator);
144 ret = write(pipe, lenbuf, strlen(lenbuf));
149 /* write value (if we have one) */
151 /*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
152 ret = write(pipe, msg, len);
157 /*g_warning("write %d indicator: %c no value", pipe, indicator);*/
160 /*g_warning("write %d leave", pipe);*/
164 /* read a message from the sending pipe in the standard format
165 (3 digit message length (excluding length and indicator field),
166 1 byte message indicator and the rest is the message) */
168 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
175 /* read header (3 digit len and indicator) */
179 newly = read(pipe, &header[offset], required);
182 /*g_warning("read %d header empty (capture closed)", pipe);*/
187 /*g_warning("read %d header error: %s", pipe, strerror(errno));*/
195 /* convert header values */
196 *indicator = header[3];
197 required = atoi(header);
199 /* only indicator with no value? */
201 /*g_warning("read %d indicator: %c empty value", pipe, *indicator);*/
205 g_assert(required <= len);
211 newly = read(pipe, &msg[offset], required);
214 /*g_warning("read %d value error, indicator: %u", pipe, *indicator);*/
222 /*g_warning("read %d ok indicator: %c len: %u msg: %s", pipe, *indicator, len, msg);*/
227 sync_pipe_packet_count_to_parent(int packet_count)
229 char tmp[SP_DECISIZE+1+1];
232 g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
234 pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
238 sync_pipe_filename_to_parent(const char *filename)
240 pipe_write_block(1, SP_FILE, strlen(filename)+1, filename);
244 sync_pipe_errmsg_to_parent(const char *errmsg)
246 pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
250 sync_pipe_drops_to_parent(int drops)
252 char tmp[SP_DECISIZE+1+1];
255 g_snprintf(tmp, sizeof(tmp), "%d", drops);
257 pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
264 signal_pipe_capquit_to_child(capture_options *capture_opts)
268 pipe_write_block(capture_opts->signal_pipe_fd, SP_QUIT, 0, NULL);
273 /* Add a string pointer to a NULL-terminated array of string pointers. */
275 sync_pipe_add_arg(char **args, int *argc, char *arg)
277 /* Grow the array; "*argc" currently contains the number of string
278 pointers, *not* counting the NULL pointer at the end, so we have
279 to add 2 in order to get the new size of the array, including the
280 new pointer and the terminating NULL pointer. */
281 args = g_realloc(args, (*argc + 2) * sizeof (char *));
283 /* Stuff the pointer into the penultimate element of the array, which
284 is the one at the index specified by "*argc". */
287 /* Now bump the count. */
290 /* We overwrite the NULL pointer; put it back right after the
298 /* Given a string, return a pointer to a quote-encapsulated version of
299 the string, so we can pass it as an argument with "spawnvp" even
300 if it contains blanks. */
302 sync_pipe_quote_encapsulate(const char *string)
304 char *encapsulated_string;
306 encapsulated_string = g_new(char, strlen(string) + 3);
307 sprintf(encapsulated_string, "\"%s\"", string);
308 return encapsulated_string;
314 #define ARGV_NUMBER_LEN 24
317 sync_pipe_start(capture_options *capture_opts) {
318 char ssnap[ARGV_NUMBER_LEN];
319 char scount[ARGV_NUMBER_LEN];
320 char sfilesize[ARGV_NUMBER_LEN];
321 char sfile_duration[ARGV_NUMBER_LEN];
322 char sring_num_files[ARGV_NUMBER_LEN];
323 char sautostop_files[ARGV_NUMBER_LEN];
324 char sautostop_filesize[ARGV_NUMBER_LEN];
325 char sautostop_duration[ARGV_NUMBER_LEN];
327 char sync_pipe_fd[ARGV_NUMBER_LEN];
328 char signal_pipe_fd[ARGV_NUMBER_LEN];
331 char *savefilestring;
332 int signal_pipe[2]; /* pipe used to send messages from parent to child (currently only stop) */
338 enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
339 int sync_pipe[2]; /* pipe used to send messages from child to parent */
342 /*g_warning("sync_pipe_start");
343 capture_opts_info(capture_opts);*/
345 capture_opts->fork_child = -1;
347 /* Allocate the string pointer array with enough space for the
348 terminating NULL pointer. */
350 argv = g_malloc(sizeof (char *));
353 /* Now add those arguments used on all platforms. */
354 argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
356 argv = sync_pipe_add_arg(argv, &argc, "-i");
357 argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
359 if (capture_opts->has_snaplen) {
360 argv = sync_pipe_add_arg(argv, &argc, "-s");
361 sprintf(ssnap,"%d",capture_opts->snaplen);
362 argv = sync_pipe_add_arg(argv, &argc, ssnap);
365 if (capture_opts->linktype != -1) {
366 argv = sync_pipe_add_arg(argv, &argc, "-y");
367 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
368 sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts->linktype));
370 /* XXX - just treat it as a number */
371 sprintf(ssnap,"%d",capture_opts->linktype);
373 argv = sync_pipe_add_arg(argv, &argc, ssnap);
376 if(capture_opts->multi_files_on) {
377 if (capture_opts->has_autostop_filesize) {
378 argv = sync_pipe_add_arg(argv, &argc, "-b");
379 sprintf(sfilesize,"filesize:%d",capture_opts->autostop_filesize);
380 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
383 if (capture_opts->has_file_duration) {
384 argv = sync_pipe_add_arg(argv, &argc, "-b");
385 sprintf(sfile_duration,"duration:%d",capture_opts->file_duration);
386 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
389 if (capture_opts->has_ring_num_files) {
390 argv = sync_pipe_add_arg(argv, &argc, "-b");
391 sprintf(sring_num_files,"files:%d",capture_opts->ring_num_files);
392 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
395 if (capture_opts->has_autostop_files) {
396 argv = sync_pipe_add_arg(argv, &argc, "-a");
397 sprintf(sautostop_files,"files:%d",capture_opts->autostop_files);
398 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
401 if (capture_opts->has_autostop_filesize) {
402 argv = sync_pipe_add_arg(argv, &argc, "-a");
403 sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
404 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
408 if (capture_opts->has_autostop_packets) {
409 argv = sync_pipe_add_arg(argv, &argc, "-c");
410 sprintf(scount,"%d",capture_opts->autostop_packets);
411 argv = sync_pipe_add_arg(argv, &argc, scount);
414 if (capture_opts->has_autostop_duration) {
415 argv = sync_pipe_add_arg(argv, &argc, "-a");
416 sprintf(sautostop_duration,"duration:%d",capture_opts->autostop_duration);
417 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
420 if (!capture_opts->show_info) {
421 argv = sync_pipe_add_arg(argv, &argc, "-H");
424 if (!capture_opts->promisc_mode)
425 argv = sync_pipe_add_arg(argv, &argc, "-p");
428 /* Create a pipe for the child process */
429 /* (inrease this value if you have trouble while fast capture file switches) */
430 if(_pipe(sync_pipe, 5120, O_BINARY) < 0) {
431 /* Couldn't create the pipe between parent and child. */
432 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
438 /* Create a pipe for the parent process */
439 if(_pipe(signal_pipe, 512, O_BINARY) < 0) {
440 /* Couldn't create the signal pipe between parent and child. */
441 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
443 close(sync_pipe[PIPE_READ]);
444 close(sync_pipe[PIPE_WRITE]);
449 capture_opts->signal_pipe_fd = signal_pipe[PIPE_WRITE];
451 /* Convert font name to a quote-encapsulated string and pass to child */
452 argv = sync_pipe_add_arg(argv, &argc, "-m");
453 fontstring = sync_pipe_quote_encapsulate(prefs.PREFS_GUI_FONT_NAME);
454 argv = sync_pipe_add_arg(argv, &argc, fontstring);
456 /* Convert sync pipe write handle to a string and pass to child */
457 argv = sync_pipe_add_arg(argv, &argc, "-Z");
458 sprintf(sync_pipe_fd,"sync:%d",sync_pipe[PIPE_WRITE]);
459 argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
461 /* Convert signal pipe read handle to a string and pass to child */
462 argv = sync_pipe_add_arg(argv, &argc, "-Z");
463 sprintf(signal_pipe_fd,"signal:%d",signal_pipe[PIPE_READ]);
464 argv = sync_pipe_add_arg(argv, &argc, signal_pipe_fd);
466 /* Convert filter string to a quote delimited string and pass to child */
468 if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
469 argv = sync_pipe_add_arg(argv, &argc, "-f");
470 filterstring = sync_pipe_quote_encapsulate(capture_opts->cfilter);
471 argv = sync_pipe_add_arg(argv, &argc, filterstring);
474 /* Convert save file name to a quote delimited string and pass to child */
475 if(capture_opts->save_file) {
476 argv = sync_pipe_add_arg(argv, &argc, "-w");
477 savefilestring = sync_pipe_quote_encapsulate(capture_opts->save_file);
478 argv = sync_pipe_add_arg(argv, &argc, savefilestring);
482 capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
485 g_free(filterstring);
488 g_free(savefilestring);
491 /* child own's the read side now, close our handle */
492 close(signal_pipe[PIPE_READ]);
494 if (pipe(sync_pipe) < 0) {
495 /* Couldn't create the pipe between parent and child. */
496 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
502 argv = sync_pipe_add_arg(argv, &argc, "-m");
503 argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
505 if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
506 argv = sync_pipe_add_arg(argv, &argc, "-f");
507 argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
510 if(capture_opts->save_file) {
511 argv = sync_pipe_add_arg(argv, &argc, "-w");
512 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
515 if ((capture_opts->fork_child = fork()) == 0) {
517 * Child process - run Ethereal with the right arguments to make
518 * it just pop up the live capture dialog box and capture with
519 * the specified capture parameters, writing to the specified file.
521 * args: -i interface specification
523 * -W file descriptor to write
524 * -c count to capture
527 * -f "filter expression"
530 dup(sync_pipe[PIPE_WRITE]);
531 close(sync_pipe[PIPE_READ]);
532 execvp(ethereal_path, argv);
533 snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
534 ethereal_path, strerror(errno));
535 sync_pipe_errmsg_to_parent(errmsg);
537 /* Exit with "_exit()", so that we don't close the connection
538 to the X server (and cause stuff buffered up by our parent but
539 not yet sent to be sent, as that stuff should only be sent by
545 /* Parent process - read messages from the child process over the
547 g_free(argv); /* free up arg array */
549 /* Close the write side of the pipe, so that only the child has it
550 open, and thus it completely closes, and thus returns to us
551 an EOF indication, if the child closes it (either deliberately
552 or by exiting abnormally). */
553 close(sync_pipe[PIPE_WRITE]);
555 if (capture_opts->fork_child == -1) {
556 /* We couldn't even create the child process. */
557 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
558 "Couldn't create child process: %s", strerror(errno));
559 close(sync_pipe[PIPE_READ]);
561 close(signal_pipe[PIPE_WRITE]);
566 /* we might wait for a moment till child is ready, so update screen now */
567 main_window_update();
569 /* We were able to set up to read the capture file;
570 arrange that our callback be called whenever it's possible
571 to read from the sync pipe, so that it's called when
572 the child process wants to tell us something. */
574 /* we have a running capture, now wait for the real capture filename */
575 pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts,
576 &capture_opts->fork_child, sync_pipe_input_cb);
582 /* There's stuff to read from the sync pipe, meaning the child has sent
583 us a message, or the sync pipe has closed, meaning the child has
584 closed it (perhaps because it exited). */
586 sync_pipe_input_cb(gint source, gpointer user_data)
588 capture_options *capture_opts = (capture_options *)user_data;
590 char buffer[BUFSIZE+1];
595 nread = pipe_read_block(source, &indicator, BUFSIZE, buffer);
597 /* The child has closed the sync pipe, meaning it's not going to be
598 capturing any more packets. Pick up its exit status, and
599 complain if it did anything other than exit with status 0. */
600 sync_pipe_wait_for_child(capture_opts, FALSE);
602 close(capture_opts->signal_pipe_fd);
604 capture_input_closed(capture_opts);
610 if(!capture_input_new_file(capture_opts, buffer)) {
611 /* We weren't able to open the new capture file; user has been
612 alerted. Close the sync pipe. */
613 /* XXX - is it safe to close the pipe inside this callback? */
616 /* the child has send us a filename which we couldn't open.
617 this probably means, the child is creating files faster than we can handle it.
618 this should only be the case for very fast file switches
619 we can't do much more than telling the child to stop
620 (this is the emergency brake if user e.g. wants to switch files every second) */
621 sync_pipe_stop(capture_opts);
624 case SP_PACKET_COUNT:
625 nread = atoi(buffer);
626 capture_input_new_packets(capture_opts, nread);
629 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
632 cf_set_drops_known(capture_opts->cf, TRUE);
633 cf_set_drops(capture_opts->cf, atoi(buffer));
636 g_assert_not_reached();
644 /* the child process is going down, wait until it's completely terminated */
646 sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report)
651 g_assert(capture_opts->fork_child != -1);
654 /* XXX - analyze the wait status and display more information
656 XXX - set "fork_child" to -1 if we find it exited? */
657 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
658 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
659 "Child capture process stopped unexpectedly");
662 if (wait(&wstatus) != -1) {
663 if (WIFEXITED(wstatus)) {
664 /* The child exited; display its exit status, if it's not zero,
665 and even if it's zero if "always_report" is true. */
666 if (always_report || WEXITSTATUS(wstatus) != 0) {
667 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
668 "Child capture process exited: exit status %d",
669 WEXITSTATUS(wstatus));
671 } else if (WIFSTOPPED(wstatus)) {
672 /* It stopped, rather than exiting. "Should not happen." */
673 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
674 "Child capture process stopped: %s",
675 sync_pipe_signame(WSTOPSIG(wstatus)));
676 } else if (WIFSIGNALED(wstatus)) {
677 /* It died with a signal. */
678 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
679 "Child capture process died: %s%s",
680 sync_pipe_signame(WTERMSIG(wstatus)),
681 WCOREDUMP(wstatus) ? " - core dumped" : "");
683 /* What? It had to either have exited, or stopped, or died with
684 a signal; what happened here? */
685 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
686 "Child capture process died: wait status %#o", wstatus);
690 /* No more child process. */
691 capture_opts->fork_child = -1;
697 /* convert signal to corresponding name */
699 sync_pipe_signame(int sig)
702 static char sigmsg_buf[6+1+3+1];
711 sigmsg = "Interrupted";
719 sigmsg = "Illegal instruction";
723 sigmsg = "Trace trap";
731 sigmsg = "Arithmetic exception";
739 sigmsg = "Bus error";
743 sigmsg = "Segmentation violation";
746 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
747 Linux is POSIX compliant. These are not POSIX-defined signals ---
748 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
750 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
751 were omitted from POSIX.1 because their behavior is
752 implementation dependent and could not be adequately catego-
753 rized. Conforming implementations may deliver these sig-
754 nals, but must document the circumstances under which they
755 are delivered and note any restrictions concerning their
758 So we only check for SIGSYS on those systems that happen to
759 implement them (a system can be POSIX-compliant and implement
760 them, it's just that POSIX doesn't *require* a POSIX-compliant
761 system to implement them).
766 sigmsg = "Bad system call";
771 sigmsg = "Broken pipe";
775 sigmsg = "Alarm clock";
779 sigmsg = "Terminated";
783 sprintf(sigmsg_buf, "Signal %d", sig);
792 /* user wants to stop the capture run */
794 sync_pipe_stop(capture_options *capture_opts)
796 /* XXX - in which cases this will be 0? */
797 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
799 /* send the SIGUSR1 signal to close the capture child gracefully. */
800 kill(capture_opts->fork_child, SIGUSR1);
802 /* Win32 doesn't have the kill() system call, use the special signal pipe
803 instead to close the capture child gracefully. */
804 signal_pipe_capquit_to_child(capture_opts);
810 /* Ethereal has to exit, force the capture child to close */
812 sync_pipe_kill(capture_options *capture_opts)
814 /* XXX - in which cases this will be 0? */
815 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
817 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
819 /* XXX: this is not the preferred method of closing a process!
820 * the clean way would be getting the process id of the child process,
821 * then getting window handle hWnd of that process (using EnumChildWindows),
822 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
824 * Unfortunately, I don't know how to get the process id from the
825 * handle. OpenProcess will get an handle (not a window handle)
826 * from the process ID; it will not get a window handle from the
827 * process ID. (How could it? A process can have more than one
830 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
831 * running in the same console; that's not necessarily the case for
832 * us, as we might not be running in a console.
833 * And this also will require to have the process id.
835 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
840 #endif /* HAVE_LIBPCAP */