support for additionally SIZE constrained Typereference
[obnox/wireshark/wip.git] / capture_sync.c
1 /* capture_sync.c
2  * Synchronisation between Wireshark capture parent and child instances
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <glib.h>
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <string.h>
35
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43
44 #include <signal.h>
45
46 #ifdef _WIN32
47 #include "epan/unicode-utils.h"
48 #endif
49
50 #ifdef HAVE_SYS_WAIT_H
51 # include <sys/wait.h>
52 #endif
53
54 #include "capture-pcap-util.h"
55
56 #ifndef _WIN32
57 /*
58  * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
59  * macros) on UNIX systems that don't have them.
60  */
61 #ifndef WIFEXITED
62 # define WIFEXITED(status)      (((status) & 0177) == 0)
63 #endif
64 #ifndef WIFSTOPPED
65 # define WIFSTOPPED(status)     (((status) & 0177) == 0177)
66 #endif
67 #ifndef WIFSIGNALED
68 # define WIFSIGNALED(status)    (!WIFSTOPPED(status) && !WIFEXITED(status))
69 #endif
70 #ifndef WEXITSTATUS
71 # define WEXITSTATUS(status)    ((status) >> 8)
72 #endif
73 #ifndef WTERMSIG
74 # define WTERMSIG(status)       ((status) & 0177)
75 #endif
76 #ifndef WCOREDUMP
77 # define WCOREDUMP(status)      ((status) & 0200)
78 #endif
79 #ifndef WSTOPSIG
80 # define WSTOPSIG(status)       ((status) >> 8)
81 #endif
82 #endif /* _WIN32 */
83
84 #include <epan/packet.h>
85 #include <epan/prefs.h>
86
87 #include "globals.h"
88 #include "file.h"
89 #include <epan/filesystem.h>
90
91 #include "capture.h"
92 #include "capture_sync.h"
93 #include "simple_dialog.h"
94
95 #include "sync_pipe.h"
96
97 #ifdef _WIN32
98 #include "capture-wpcap.h"
99 #endif
100 #include "ui_util.h"
101 #include "file_util.h"
102 #include "log.h"
103
104 #ifdef _WIN32
105 #include <process.h>    /* For spawning child process */
106 #endif
107
108
109
110 #ifndef _WIN32
111 static const char *sync_pipe_signame(int);
112 #endif
113
114
115 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
116 static void sync_pipe_wait_for_child(capture_options *capture_opts);
117
118
119
120 /* Append an arg (realloc) to an argc/argv array */
121 /* (add a string pointer to a NULL-terminated array of string pointers) */
122 static const char **
123 sync_pipe_add_arg(const char **args, int *argc, const char *arg)
124 {
125   /* Grow the array; "*argc" currently contains the number of string
126      pointers, *not* counting the NULL pointer at the end, so we have
127      to add 2 in order to get the new size of the array, including the
128      new pointer and the terminating NULL pointer. */
129   args = g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
130
131   /* Stuff the pointer into the penultimate element of the array, which
132      is the one at the index specified by "*argc". */
133   args[*argc] = arg;
134
135   /* Now bump the count. */
136   (*argc)++;
137
138   /* We overwrite the NULL pointer; put it back right after the
139      element we added. */
140   args[*argc] = NULL;
141
142   return args;
143 }
144
145
146
147 #ifdef _WIN32
148 /* Quote the argument element if necessary, so that it will get
149  * reconstructed correctly in the C runtime startup code.  Note that
150  * the unquoting algorithm in the C runtime is really weird, and
151  * rather different than what Unix shells do. See stdargv.c in the C
152  * runtime sources (in the Platform SDK, in src/crt).
153  *
154  * Stolen from GLib's protect_argv(), an internal routine that quotes
155  * string in an argument list so that they arguments will be handled
156  * correctly in the command-line string passed to CreateProcess()
157  * if that string is constructed by gluing those strings together.
158  */
159 static gchar *
160 protect_arg (const gchar *argv)
161 {
162     gchar *new_arg;
163     const gchar *p = argv;
164     gchar *q;
165     gint len = 0;
166     gboolean need_dblquotes = FALSE;
167
168     while (*p) {
169         if (*p == ' ' || *p == '\t')
170             need_dblquotes = TRUE;
171         else if (*p == '"')
172             len++;
173         else if (*p == '\\') {
174             const gchar *pp = p;
175
176             while (*pp && *pp == '\\')
177                 pp++;
178             if (*pp == '"')
179                 len++;
180         }
181         len++;
182         p++;
183     }
184
185     q = new_arg = g_malloc (len + need_dblquotes*2 + 1);
186     p = argv;
187
188     if (need_dblquotes)
189         *q++ = '"';
190
191     while (*p) {
192         if (*p == '"')
193             *q++ = '\\';
194         else if (*p == '\\') {
195             const gchar *pp = p;
196
197             while (*pp && *pp == '\\')
198                 pp++;
199             if (*pp == '"')
200                 *q++ = '\\';
201         }
202         *q++ = *p;
203         p++;
204     }
205
206     if (need_dblquotes)
207         *q++ = '"';
208     *q++ = '\0';
209
210     return new_arg;
211 }
212 #endif
213
214 /* Initialize an argument list and add dumpcap to it. */
215 static const char **
216 init_pipe_args(int *argc) {
217     const char **argv;
218     const char *progfile_dir;
219     char *exename;
220
221     progfile_dir = get_progfile_dir();
222     if (progfile_dir == NULL) {
223       return NULL;
224     }
225
226     /* Allocate the string pointer array with enough space for the
227        terminating NULL pointer. */
228     *argc = 0;
229     argv = g_malloc(sizeof (char *));
230     *argv = NULL;
231
232     /* take Wireshark's absolute program path and replace "Wireshark" with "dumpcap" */
233     exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap", progfile_dir);
234
235     /* Make that the first argument in the argument list (argv[0]). */
236     argv = sync_pipe_add_arg(argv, argc, exename);
237
238     return argv;
239 }
240
241 #define ARGV_NUMBER_LEN 24
242 /* a new capture run: start a new dumpcap task and hand over parameters through command line */
243 gboolean
244 sync_pipe_start(capture_options *capture_opts) {
245     char ssnap[ARGV_NUMBER_LEN];
246     char sdlt[ARGV_NUMBER_LEN];
247     char scount[ARGV_NUMBER_LEN];
248     char sfilesize[ARGV_NUMBER_LEN];
249     char sfile_duration[ARGV_NUMBER_LEN];
250     char sring_num_files[ARGV_NUMBER_LEN];
251     char sautostop_files[ARGV_NUMBER_LEN];
252     char sautostop_filesize[ARGV_NUMBER_LEN];
253     char sautostop_duration[ARGV_NUMBER_LEN];
254 #ifdef HAVE_PCAP_REMOTE
255     char sauth[256];
256 #endif
257 #ifdef HAVE_PCAP_SETSAMPLING
258     char ssampling[ARGV_NUMBER_LEN];
259 #endif
260 #ifdef _WIN32
261     char buffer_size[ARGV_NUMBER_LEN];
262     HANDLE sync_pipe_read;                  /* pipe used to send messages from child to parent */
263     HANDLE sync_pipe_write;                 /* pipe used to send messages from child to parent */
264     HANDLE signal_pipe;                     /* named pipe used to send messages from parent to child (currently only stop) */
265     GString *args = g_string_sized_new(200);
266     gchar *quoted_arg;
267     SECURITY_ATTRIBUTES sa;
268     STARTUPINFO si;
269     PROCESS_INFORMATION pi;
270     int i;
271     char control_id[ARGV_NUMBER_LEN];
272     gchar *signal_pipe_name;
273 #else
274     char errmsg[1024+1];
275     int sync_pipe[2];                       /* pipe used to send messages from child to parent */
276     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
277 #endif
278     int sync_pipe_read_fd;
279     int argc;
280     const char **argv;
281
282
283     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
284     capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
285
286     capture_opts->fork_child = -1;
287
288     argv = init_pipe_args(&argc);
289     if (!argv) {
290         /* We don't know where to find dumpcap. */
291         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "We don't know where to find dumpcap.");
292         return FALSE;
293     }
294
295     argv = sync_pipe_add_arg(argv, &argc, "-i");
296     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
297
298     if (capture_opts->has_snaplen) {
299       argv = sync_pipe_add_arg(argv, &argc, "-s");
300       g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
301       argv = sync_pipe_add_arg(argv, &argc, ssnap);
302     }
303
304     if (capture_opts->linktype != -1) {
305       argv = sync_pipe_add_arg(argv, &argc, "-y");
306 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
307       g_snprintf(sdlt, ARGV_NUMBER_LEN, "%s",linktype_val_to_name(capture_opts->linktype));
308 #else
309       /* we can't get the type name, just treat it as a number */
310       g_snprintf(sdlt, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
311 #endif
312       argv = sync_pipe_add_arg(argv, &argc, sdlt);
313     }
314
315     if(capture_opts->multi_files_on) {
316       if (capture_opts->has_autostop_filesize) {
317         argv = sync_pipe_add_arg(argv, &argc, "-b");
318         g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
319         argv = sync_pipe_add_arg(argv, &argc, sfilesize);
320       }
321
322       if (capture_opts->has_file_duration) {
323         argv = sync_pipe_add_arg(argv, &argc, "-b");
324         g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
325         argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
326       }
327
328       if (capture_opts->has_ring_num_files) {
329         argv = sync_pipe_add_arg(argv, &argc, "-b");
330         g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
331         argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
332       }
333
334       if (capture_opts->has_autostop_files) {
335         argv = sync_pipe_add_arg(argv, &argc, "-a");
336         g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
337         argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
338       }
339     } else {
340         if (capture_opts->has_autostop_filesize) {
341           argv = sync_pipe_add_arg(argv, &argc, "-a");
342           g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
343           argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
344         }
345     }
346
347     if (capture_opts->has_autostop_packets) {
348       argv = sync_pipe_add_arg(argv, &argc, "-c");
349       g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
350       argv = sync_pipe_add_arg(argv, &argc, scount);
351     }
352
353     if (capture_opts->has_autostop_duration) {
354       argv = sync_pipe_add_arg(argv, &argc, "-a");
355       g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
356       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
357     }
358
359     if (!capture_opts->promisc_mode)
360       argv = sync_pipe_add_arg(argv, &argc, "-p");
361 #ifdef HAVE_PCAP_REMOTE
362     if (capture_opts->datatx_udp)
363       argv = sync_pipe_add_arg(argv, &argc, "-u");
364
365     if (!capture_opts->nocap_rpcap)
366       argv = sync_pipe_add_arg(argv, &argc, "-r");
367
368     if (capture_opts->auth_type == CAPTURE_AUTH_PWD)
369     {
370         argv = sync_pipe_add_arg(argv, &argc, "-A");
371         g_snprintf(sauth, sizeof(sauth), "%s:%s", capture_opts->auth_username,
372                    capture_opts->auth_password);
373         argv = sync_pipe_add_arg(argv, &argc, sauth);
374     }
375 #endif
376 #ifdef HAVE_PCAP_SETSAMPLING
377     if (capture_opts->sampling_method != CAPTURE_SAMP_NONE)
378     {
379         argv = sync_pipe_add_arg(argv, &argc, "-m");
380         g_snprintf(ssampling, ARGV_NUMBER_LEN, "%s:%d",
381              capture_opts->sampling_method == CAPTURE_SAMP_BY_COUNT ? "count" :
382              capture_opts->sampling_method == CAPTURE_SAMP_BY_TIMER ? "timer" :
383              "undef",
384              capture_opts->sampling_param);
385         argv = sync_pipe_add_arg(argv, &argc, ssampling);
386     }
387 #endif
388
389     /* dumpcap should be running in capture child mode (hidden feature) */
390 #ifndef DEBUG_CHILD
391     argv = sync_pipe_add_arg(argv, &argc, "-Z");
392 #ifdef _WIN32
393     g_snprintf(control_id, ARGV_NUMBER_LEN, "%d", GetCurrentProcessId());
394     argv = sync_pipe_add_arg(argv, &argc, control_id);
395 #else
396     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
397 #endif
398 #endif
399
400 #ifdef _WIN32
401     argv = sync_pipe_add_arg(argv, &argc, "-B");
402     g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
403     argv = sync_pipe_add_arg(argv, &argc, buffer_size);
404 #endif
405
406     if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
407       argv = sync_pipe_add_arg(argv, &argc, "-f");
408       argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
409     }
410
411     if(capture_opts->save_file) {
412       argv = sync_pipe_add_arg(argv, &argc, "-w");
413       argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
414     }
415
416 #ifdef _WIN32
417     /* init SECURITY_ATTRIBUTES */
418     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
419     sa.bInheritHandle = TRUE;
420     sa.lpSecurityDescriptor = NULL;
421
422     /* Create a pipe for the child process */
423     /* (increase this value if you have trouble while fast capture file switches) */
424     if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
425       /* Couldn't create the pipe between parent and child. */
426       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
427                         strerror(errno));
428       g_free( (gpointer) argv[0]);
429       g_free( (gpointer) argv);
430       return FALSE;
431     }
432
433     /* Create the signal pipe */
434     signal_pipe_name = g_strdup_printf(SIGNAL_PIPE_FORMAT, control_id);
435     signal_pipe = CreateNamedPipe(utf_8to16(signal_pipe_name),
436       PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 65535, 65535, 0, NULL);
437     g_free(signal_pipe_name);
438
439     if (signal_pipe == INVALID_HANDLE_VALUE) {
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",
442                         strerror(errno));
443       g_free( (gpointer) argv[0]);
444       g_free( (gpointer) argv);
445       return FALSE;
446     }
447
448     /* init STARTUPINFO */
449     memset(&si, 0, sizeof(si));
450     si.cb           = sizeof(si);
451 #ifdef DEBUG_CHILD
452     si.dwFlags = STARTF_USESHOWWINDOW;
453     si.wShowWindow  = SW_SHOW;
454 #else
455     si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
456     si.wShowWindow  = SW_HIDE;  /* this hides the console window */
457     si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
458     si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
459     si.hStdError = sync_pipe_write;
460     /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
461 #endif
462
463     /* convert args array into a single string */
464     /* XXX - could change sync_pipe_add_arg() instead */
465     /* there is a drawback here: the length is internally limited to 1024 bytes */
466     for(i=0; argv[i] != 0; i++) {
467         if(i != 0) g_string_append_c(args, ' ');    /* don't prepend a space before the path!!! */
468         quoted_arg = protect_arg(argv[i]);
469         g_string_append(args, quoted_arg);
470         g_free(quoted_arg);
471     }
472
473     /* call dumpcap */
474     if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
475                       CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
476       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
477                     "Couldn't run %s in child process: error %u",
478                     args->str, GetLastError());
479       CloseHandle(sync_pipe_read);
480       CloseHandle(sync_pipe_write);
481       g_free( (gpointer) argv[0]);
482       g_free( (gpointer) argv);
483       return FALSE;
484     }
485     capture_opts->fork_child = (int) pi.hProcess;
486     g_string_free(args, TRUE);
487
488     /* associate the operating system filehandle to a C run-time file handle */
489     /* (good file handle infos at: http://www.flounder.com/handles.htm) */
490     sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
491
492     /* associate the operating system filehandle to a C run-time file handle */
493     capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe, _O_BINARY);
494
495 #else /* _WIN32 */
496     if (pipe(sync_pipe) < 0) {
497       /* Couldn't create the pipe between parent and child. */
498       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
499                         strerror(errno));
500       g_free( (gpointer) argv[0]);
501       g_free(argv);
502       return FALSE;
503     }
504
505     if ((capture_opts->fork_child = fork()) == 0) {
506       /*
507        * Child process - run dumpcap with the right arguments to make
508        * it just capture with the specified capture parameters
509        */
510       eth_close(2);
511       dup(sync_pipe[PIPE_WRITE]);
512       eth_close(sync_pipe[PIPE_READ]);
513       execv(argv[0], (gpointer)argv);
514       g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
515                 argv[0], strerror(errno));
516       sync_pipe_errmsg_to_parent(1, errmsg, "");
517
518       /* Exit with "_exit()", so that we don't close the connection
519          to the X server (and cause stuff buffered up by our parent but
520          not yet sent to be sent, as that stuff should only be sent by
521          our parent). */
522       _exit(2);
523     }
524
525     sync_pipe_read_fd = sync_pipe[PIPE_READ];
526 #endif
527
528     g_free( (gpointer) argv[0]);  /* exename */
529
530     /* Parent process - read messages from the child process over the
531        sync pipe. */
532     g_free( (gpointer) argv);   /* free up arg array */
533
534     /* Close the write side of the pipe, so that only the child has it
535        open, and thus it completely closes, and thus returns to us
536        an EOF indication, if the child closes it (either deliberately
537        or by exiting abnormally). */
538 #ifdef _WIN32
539     CloseHandle(sync_pipe_write);
540 #else
541     eth_close(sync_pipe[PIPE_WRITE]);
542 #endif
543
544     if (capture_opts->fork_child == -1) {
545       /* We couldn't even create the child process. */
546       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
547                         "Couldn't create child process: %s", strerror(errno));
548       eth_close(sync_pipe_read_fd);
549 #ifdef _WIN32
550       eth_close(capture_opts->signal_pipe_write_fd);
551 #endif
552       return FALSE;
553     }
554
555     /* we might wait for a moment till child is ready, so update screen now */
556     main_window_update();
557
558     /* We were able to set up to read the capture file;
559        arrange that our callback be called whenever it's possible
560        to read from the sync pipe, so that it's called when
561        the child process wants to tell us something. */
562
563     /* we have a running capture, now wait for the real capture filename */
564     pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts,
565         &capture_opts->fork_child, sync_pipe_input_cb);
566
567     return TRUE;
568 }
569
570 /*
571  * Open dumpcap with the supplied arguments.  On success, msg points to
572  * a buffer containing the dumpcap output and returns 0.  read_fd and
573  * fork_child point to the pipe's file descriptor and child PID/handle,
574  * respectively.  On failure, msg points to the error message returned by
575  * dumpcap, and returns dumpcap's exit value.  In either case, msg must be
576  * freed with g_free().
577  */
578 /* XXX - This duplicates a lot of code in sync_pipe_start() */
579 #define PIPE_BUF_SIZE 5120
580 static int
581 sync_pipe_open_command(const char** argv, int *read_fd, int *fork_child, gchar **msg) {
582 #ifdef _WIN32
583     HANDLE sync_pipe_read;                  /* pipe used to send messages from child to parent */
584     HANDLE sync_pipe_write;                 /* pipe used to send messages from parent to child */
585     GString *args = g_string_sized_new(200);
586     gchar *quoted_arg;
587     SECURITY_ATTRIBUTES sa;
588     STARTUPINFO si;
589     PROCESS_INFORMATION pi;
590     int i;
591 #else
592     int sync_pipe[2];                       /* pipe used to send messages from child to parent */
593     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
594 #endif
595
596     *fork_child = -1;
597     *read_fd = -1;
598     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_run_command");
599
600     if (!msg) {
601         /* We can't return anything */
602 #ifdef _WIN32
603         g_string_free(args, TRUE);
604 #endif
605         return -1;
606     }
607
608 #ifdef _WIN32
609     /* init SECURITY_ATTRIBUTES */
610     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
611     sa.bInheritHandle = TRUE;
612     sa.lpSecurityDescriptor = NULL;
613
614     /* Create a pipe for the child process */
615     /* (inrease this value if you have trouble while fast capture file switches) */
616     if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
617         /* Couldn't create the pipe between parent and child. */
618         *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
619         g_free( (gpointer) argv[0]);
620         g_free( (gpointer) argv);
621         return CANT_RUN_DUMPCAP;
622     }
623
624     /* init STARTUPINFO */
625     memset(&si, 0, sizeof(si));
626     si.cb           = sizeof(si);
627 #ifdef DEBUG_CHILD
628     si.dwFlags = STARTF_USESHOWWINDOW;
629     si.wShowWindow  = SW_SHOW;
630 #else
631     si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
632     si.wShowWindow  = SW_HIDE;  /* this hides the console window */
633     si.hStdInput = NULL;
634     si.hStdOutput = sync_pipe_write;
635     si.hStdError = sync_pipe_write;
636     /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
637 #endif
638
639     /* convert args array into a single string */
640     /* XXX - could change sync_pipe_add_arg() instead */
641     /* there is a drawback here: the length is internally limited to 1024 bytes */
642     for(i=0; argv[i] != 0; i++) {
643         if(i != 0) g_string_append_c(args, ' ');    /* don't prepend a space before the path!!! */
644         quoted_arg = protect_arg(argv[i]);
645         g_string_append(args, quoted_arg);
646         g_free(quoted_arg);
647     }
648
649     /* call dumpcap */
650     if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
651                       CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
652         *msg = g_strdup_printf("Couldn't run %s in child process: error %u",
653                         args->str, GetLastError());
654         CloseHandle(sync_pipe_read);
655         CloseHandle(sync_pipe_write);
656         g_free( (gpointer) argv[0]);
657         g_free( (gpointer) argv);
658         return CANT_RUN_DUMPCAP;
659     }
660     *fork_child = (int) pi.hProcess;
661     g_string_free(args, TRUE);
662
663     /* associate the operating system filehandle to a C run-time file handle */
664     /* (good file handle infos at: http://www.flounder.com/handles.htm) */
665     *read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
666
667 #else /* _WIN32 */
668     if (pipe(sync_pipe) < 0) {
669         /* Couldn't create the pipe between parent and child. */
670         *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
671         g_free( (gpointer) argv[0]);
672         g_free(argv);
673         return CANT_RUN_DUMPCAP;
674     }
675
676     if ((*fork_child = fork()) == 0) {
677         /*
678          * Child process - run dumpcap with the right arguments to make
679          * it just capture with the specified capture parameters
680          */
681         eth_close(1);
682         dup(sync_pipe[PIPE_WRITE]);
683         eth_close(sync_pipe[PIPE_READ]);
684         execv(argv[0], (gpointer)argv);
685         *msg = g_strdup_printf("Couldn't run %s in child process: %s",
686                 argv[0], strerror(errno));
687         return CANT_RUN_DUMPCAP;
688     }
689
690     *read_fd = sync_pipe[PIPE_READ];
691 #endif
692
693     g_free( (gpointer) argv[0]);  /* exename */
694
695     /* Parent process - read messages from the child process over the
696        sync pipe. */
697     g_free( (gpointer) argv);   /* free up arg array */
698
699     /* Close the write side of the pipe, so that only the child has it
700        open, and thus it completely closes, and thus returns to us
701        an EOF indication, if the child closes it (either deliberately
702        or by exiting abnormally). */
703 #ifdef _WIN32
704     CloseHandle(sync_pipe_write);
705 #else
706     eth_close(sync_pipe[PIPE_WRITE]);
707 #endif
708
709     if (*fork_child == -1) {
710         /* We couldn't even create the child process. */
711         *msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
712         eth_close(*read_fd);
713         return CANT_RUN_DUMPCAP;
714     }
715
716     /* we might wait for a moment till child is ready, so update screen now */
717     main_window_update();
718     return 0;
719 }
720
721 static int
722 #ifdef _WIN32
723 sync_pipe_close_command(int *read_fd, int *fork_child, gchar **msg) {
724 #else
725 sync_pipe_close_command(int *read_fd, gchar **msg) {
726 #endif
727     int fork_child_status;
728
729     eth_close(*read_fd);
730
731     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_close_command: wait till child closed");
732
733 #ifdef _WIN32
734     /* XXX - Should we signal the child somehow? */
735     sync_pipe_kill(*fork_child);
736     if (_cwait(&fork_child_status, *fork_child, _WAIT_CHILD) == -1) {
737         *msg = g_strdup_printf("Child capture process stopped unexpectedly "
738             "(errno:%u)", errno);
739         return CANT_RUN_DUMPCAP;
740     }
741 #else
742     if (wait(&fork_child_status) != -1) {
743         if (WIFEXITED(fork_child_status)) {
744             /* The child exited. */
745             fork_child_status = WEXITSTATUS(fork_child_status);
746         } else {
747             if (WIFSTOPPED(fork_child_status)) {
748                 /* It stopped, rather than exiting.  "Should not happen." */
749                 *msg = g_strdup_printf("Child capture process stopped: %s",
750                     sync_pipe_signame(WSTOPSIG(fork_child_status)));
751             } else if (WIFSIGNALED(fork_child_status)) {
752                 /* It died with a signal. */
753                 *msg = g_strdup_printf("Child capture process died: %s%s",
754                     sync_pipe_signame(WTERMSIG(fork_child_status)),
755                     WCOREDUMP(fork_child_status) ? " - core dumped" : "");
756             } else {
757                 /* What?  It had to either have exited, or stopped, or died with
758                    a signal; what happened here? */
759                 *msg = g_strdup_printf("Child capture process died: wait status %#o",
760                     fork_child_status);
761             }
762             return CANT_RUN_DUMPCAP;
763         }
764     } else {
765       *msg = g_strdup_printf("Child capture process stopped unexpectedly "
766         "(errno:%u)", errno);
767       return CANT_RUN_DUMPCAP;
768     }
769 #endif
770     return 0;
771 }
772
773 /*
774  * Run dumpcap with the supplied arguments.  On success, msg points to
775  * a buffer containing the dumpcap output and returns 0.  On failure, msg
776  * points to the error message returned by dumpcap, and returns dumpcap's
777  * exit value.  In either case, msg must be freed with g_free().
778  */
779 /* XXX - This duplicates a lot of code in sync_pipe_start() */
780 #define PIPE_BUF_SIZE 5120
781 static int
782 sync_pipe_run_command(const char** argv, gchar **msg) {
783     int sync_pipe_read_fd, fork_child, ret;
784     gchar buf[PIPE_BUF_SIZE+1];
785     GString *msg_buf = NULL;
786     int count;
787
788     ret = sync_pipe_open_command(argv, &sync_pipe_read_fd, &fork_child, msg);
789
790     if (ret)
791         return ret;
792
793     /* We were able to set up to read dumpcap's output.  Do so and
794        return its exit value. */
795     msg_buf = g_string_new("");
796     while ((count = eth_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
797         buf[count] = '\0';
798         g_string_append(msg_buf, buf);
799     }
800
801 #ifdef _WIN32
802     ret = sync_pipe_close_command(&sync_pipe_read_fd, &fork_child, msg);
803 #else
804     ret = sync_pipe_close_command(&sync_pipe_read_fd, msg);
805 #endif
806
807     if (ret) {
808         g_string_free(msg_buf, TRUE);
809         return ret;
810     }
811
812     *msg = msg_buf->str;
813     g_string_free(msg_buf, FALSE);
814     return 0;
815 }
816
817 /*
818  * Get an interface list using dumpcap.  On success, msg points to
819  * a buffer containing the dumpcap output and returns 0.  On failure, msg
820  * points to the error message returned by dumpcap, and returns dumpcap's
821  * exit value.  In either case, msg must be freed with g_free().
822  */
823 int
824 sync_interface_list_open(gchar **msg) {
825     int argc;
826     const char **argv;
827
828     if (!msg) {
829         /* We can't return anything */
830         return -1;
831     }
832
833     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open");
834
835     argv = init_pipe_args(&argc);
836
837     if (!argv) {
838         *msg = g_strdup_printf("We don't know where to find dumpcap.");
839         return CANT_RUN_DUMPCAP;
840     }
841
842     /* Ask for the interface list */
843     argv = sync_pipe_add_arg(argv, &argc, "-D");
844     argv = sync_pipe_add_arg(argv, &argc, "-M");
845
846     /* dumpcap should be running in capture child mode (hidden feature) */
847 #ifndef DEBUG_CHILD
848     argv = sync_pipe_add_arg(argv, &argc, "-Z");
849     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
850 #endif
851
852     return sync_pipe_run_command(argv, msg);
853 }
854
855 /*
856  * Get an linktype list using dumpcap.  On success, msg points to
857  * a buffer containing the dumpcap output and returns 0.  On failure, msg
858  * points to the error message returned by dumpcap, and returns dumpcap's
859  * exit value.  In either case, msg must be freed with g_free().
860  */
861 int
862 sync_linktype_list_open(gchar *ifname, gchar **msg) {
863     int argc;
864     const char **argv;
865
866     if (!msg) {
867         /* We can't return anything */
868         return -1;
869     }
870
871     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_linktype_list_open");
872
873     argv = init_pipe_args(&argc);
874
875     if (!argv) {
876         *msg = g_strdup_printf("We don't know where to find dumpcap.");
877         return CANT_RUN_DUMPCAP;
878     }
879
880     /* Ask for the linktype list */
881     argv = sync_pipe_add_arg(argv, &argc, "-i");
882     argv = sync_pipe_add_arg(argv, &argc, ifname);
883     argv = sync_pipe_add_arg(argv, &argc, "-L");
884     argv = sync_pipe_add_arg(argv, &argc, "-M");
885
886     /* dumpcap should be running in capture child mode (hidden feature) */
887 #ifndef DEBUG_CHILD
888     argv = sync_pipe_add_arg(argv, &argc, "-Z");
889     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
890 #endif
891
892     return sync_pipe_run_command(argv, msg);
893 }
894
895 /*
896  * Start getting interface statistics using dumpcap.  On success, read_fd
897  * contains the file descriptor for the pipe's stdout, msg is unchanged,
898  * and zero is returned.  On failure, msg will point to an error message
899  * that must be g_free()d and a nonzero error value will be returned.
900  */
901 int
902 sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg) {
903     int argc;
904     const char **argv;
905
906     if (!msg) {
907         /* We can't return anything */
908         return -1;
909     }
910
911     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_linktype_list_open");
912
913     argv = init_pipe_args(&argc);
914
915     if (!argv) {
916         *msg = g_strdup_printf("We don't know where to find dumpcap.");
917         return CANT_RUN_DUMPCAP;
918     }
919
920     /* Ask for the linktype list */
921     argv = sync_pipe_add_arg(argv, &argc, "-S");
922     argv = sync_pipe_add_arg(argv, &argc, "-M");
923
924     /* dumpcap should be running in capture child mode (hidden feature) */
925 #ifndef DEBUG_CHILD
926     argv = sync_pipe_add_arg(argv, &argc, "-Z");
927     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
928 #endif
929
930     return sync_pipe_open_command(argv, read_fd, fork_child, msg);
931 }
932
933 /* Close down the stats process */
934 int
935 sync_interface_stats_close(int *read_fd, int *fork_child
936 #ifndef _WIN32
937 _U_
938 #endif
939 , gchar **msg) {
940 #ifdef _WIN32
941     return sync_pipe_close_command(read_fd, fork_child, msg);
942 #else
943     return sync_pipe_close_command(read_fd, msg);
944 #endif
945 }
946
947 /* read a number of bytes from a pipe */
948 /* (blocks until enough bytes read or an error occurs) */
949 static int
950 pipe_read_bytes(int pipe, char *bytes, int required) {
951     int newly;
952     int offset = 0;
953
954     while(required) {
955         newly = read(pipe, &bytes[offset], required);
956         if (newly == 0) {
957             /* EOF */
958             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
959                   "read from pipe %d: EOF (capture closed?)", pipe);
960             return offset;
961         }
962         if (newly < 0) {
963             /* error */
964             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
965                   "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
966             return newly;
967         }
968
969         required -= newly;
970         offset += newly;
971     }
972
973     return offset;
974 }
975
976 static gboolean pipe_data_available(int pipe) {
977 #ifdef _WIN32 /* PeekNamedPipe */
978     HANDLE hPipe = (HANDLE) _get_osfhandle(pipe);
979     DWORD bytes_avail;
980
981     if (hPipe == INVALID_HANDLE_VALUE)
982         return FALSE;
983
984     if (! PeekNamedPipe(hPipe, NULL, 0, NULL, &bytes_avail, NULL))
985         return FALSE;
986
987     if (bytes_avail > 0)
988         return TRUE;
989     return FALSE;
990 #else /* select */
991     fd_set rfds;
992     struct timeval timeout;
993
994     FD_ZERO(&rfds);
995     FD_SET(pipe, &rfds);
996     timeout.tv_sec = 0;
997     timeout.tv_usec = 0;
998
999     if (select(pipe+1, &rfds, NULL, NULL, &timeout) > 0)
1000         return TRUE;
1001
1002     return FALSE;
1003 #endif
1004 }
1005
1006 /* Read a line from a pipe, similar to fgets */
1007 int
1008 sync_pipe_gets_nonblock(int pipe, char *bytes, int max) {
1009     int newly;
1010     int offset = -1;
1011
1012     while(offset < max - 1) {
1013         offset++;
1014         if (! pipe_data_available(pipe))
1015             break;
1016         newly = read(pipe, &bytes[offset], 1);
1017         if (newly == 0) {
1018             /* EOF - not necessarily an error */
1019             break;
1020         } else if (newly < 0) {
1021             /* error */
1022             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
1023                   "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
1024             return newly;
1025         } else if (bytes[offset] == '\n') {
1026             break;
1027         }
1028     }
1029
1030     if (offset >= 0)
1031         bytes[offset] = '\0';
1032
1033     return offset;
1034 }
1035
1036
1037 /* convert header values (indicator and 4-byte length) */
1038 static void
1039 pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
1040
1041     g_assert(header_len == 4);
1042
1043     /* convert header values */
1044     *indicator = header[0];
1045     *block_len = header[1]<<16 | header[2]<<8 | header[3];
1046 }
1047
1048 /* read a message from the sending pipe in the standard format
1049    (1-byte message indicator, 3-byte message length (excluding length
1050    and indicator field), and the rest is the message) */
1051 static int
1052 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
1053     int required;
1054     int newly;
1055     guchar header[4];
1056
1057
1058     /* read header (indicator and 3-byte length) */
1059     newly = pipe_read_bytes(pipe, header, 4);
1060     if(newly != 4) {
1061         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
1062               "read %d failed to read header: %u", pipe, newly);
1063         return -1;
1064     }
1065
1066     /* convert header values */
1067     pipe_convert_header(header, 4, indicator, &required);
1068
1069     /* only indicator with no value? */
1070     if(required == 0) {
1071         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
1072               "read %d indicator: %c empty value", pipe, *indicator);
1073         return 4;
1074     }
1075
1076     /* does the data fit into the given buffer? */
1077     if(required > len) {
1078         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
1079               "read %d length error, required %d > len %d, indicator: %u",
1080               pipe, required, len, *indicator);
1081
1082         /* we have a problem here, try to read some more bytes from the pipe to debug where the problem really is */
1083         memcpy(msg, header, sizeof(header));
1084         newly = read(pipe, &msg[sizeof(header)], len-sizeof(header));
1085         g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
1086         return -1;
1087     }
1088     len = required;
1089
1090     /* read the actual block data */
1091     newly = pipe_read_bytes(pipe, msg, required);
1092     if(newly != required) {
1093         g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
1094         return -1;
1095     }
1096
1097     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
1098           "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator,
1099           len, msg);
1100     return newly + 4;
1101 }
1102
1103
1104 /* There's stuff to read from the sync pipe, meaning the child has sent
1105    us a message, or the sync pipe has closed, meaning the child has
1106    closed it (perhaps because it exited). */
1107 static gboolean
1108 sync_pipe_input_cb(gint source, gpointer user_data)
1109 {
1110   capture_options *capture_opts = (capture_options *)user_data;
1111   char buffer[SP_MAX_MSG_LEN+1];
1112   int  nread;
1113   char indicator;
1114   int  primary_len;
1115   char * primary_msg;
1116   int  secondary_len;
1117   char * secondary_msg;
1118
1119
1120   nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer);
1121   if(nread <= 0) {
1122     if (nread == 0)
1123       g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
1124             "sync_pipe_input_cb: child has closed sync_pipe");
1125     else
1126       g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
1127             "sync_pipe_input_cb: error reading from sync pipe");
1128
1129     /* The child has closed the sync pipe, meaning it's not going to be
1130        capturing any more packets.  Pick up its exit status, and
1131        complain if it did anything other than exit with status 0.
1132
1133        We don't have to worry about killing the child, if the sync pipe
1134        returned an error. Usually this error is caused as the child killed itself
1135        while going down. Even in the rare cases that this isn't the case,
1136        the child will get an error when writing to the broken pipe the next time,
1137        cleaning itself up then. */
1138     sync_pipe_wait_for_child(capture_opts);
1139
1140 #ifdef _WIN32
1141     eth_close(capture_opts->signal_pipe_write_fd);
1142 #endif
1143     capture_input_closed(capture_opts);
1144     return FALSE;
1145   }
1146
1147   /* we got a valid message block from the child, process it */
1148   switch(indicator) {
1149   case SP_FILE:
1150     if(!capture_input_new_file(capture_opts, buffer)) {
1151       g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
1152
1153       /* We weren't able to open the new capture file; user has been
1154          alerted. Close the sync pipe. */
1155       eth_close(source);
1156
1157       /* the child has send us a filename which we couldn't open.
1158          this probably means, the child is creating files faster than we can handle it.
1159          this should only be the case for very fast file switches
1160          we can't do much more than telling the child to stop
1161          (this is the "emergency brake" if user e.g. wants to switch files every second) */
1162       sync_pipe_stop(capture_opts);
1163     }
1164     break;
1165   case SP_PACKET_COUNT:
1166     nread = atoi(buffer);
1167     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
1168     capture_input_new_packets(capture_opts, nread);
1169     break;
1170   case SP_ERROR_MSG:
1171     /* convert primary message */
1172     pipe_convert_header(buffer, 4, &indicator, &primary_len);
1173     primary_msg = buffer+4;
1174     /* convert secondary message */
1175     pipe_convert_header(primary_msg + primary_len, 4, &indicator, &secondary_len);
1176     secondary_msg = primary_msg + primary_len + 4;
1177     /* message output */
1178     capture_input_error_message(capture_opts, primary_msg, secondary_msg);
1179     /* the capture child will close the sync_pipe, nothing to do for now */
1180     /* (an error message doesn't mean we have to stop capturing) */
1181     break;
1182   case SP_BAD_FILTER:
1183     capture_input_cfilter_error_message(capture_opts, buffer);
1184     /* the capture child will close the sync_pipe, nothing to do for now */
1185     break;
1186   case SP_DROPS:
1187     capture_input_drops(capture_opts, atoi(buffer));
1188     break;
1189   default:
1190     g_assert_not_reached();
1191   }
1192
1193   return TRUE;
1194 }
1195
1196
1197
1198 /* the child process is going down, wait until it's completely terminated */
1199 static void
1200 sync_pipe_wait_for_child(capture_options *capture_opts)
1201 {
1202   int  wstatus;
1203
1204
1205   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
1206   g_assert(capture_opts->fork_child != -1);
1207
1208 #ifdef _WIN32
1209   if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
1210     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1211                 "Child capture process stopped unexpectedly (errno:%u)", errno);
1212   }
1213 #else
1214   if (wait(&wstatus) != -1) {
1215     if (WIFEXITED(wstatus)) {
1216       /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
1217       /* the child will inform us about errors through the sync_pipe, which will popup */
1218       /* an error message, so don't popup another one */
1219
1220       /* If there are situations where the child won't send us such an error message, */
1221       /* this should be fixed in the child and not here! */
1222       if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
1223         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1224                       "Child capture process exited: exit status %d",
1225                       WEXITSTATUS(wstatus));
1226       }
1227     } else if (WIFSTOPPED(wstatus)) {
1228       /* It stopped, rather than exiting.  "Should not happen." */
1229       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1230                     "Child capture process stopped: %s",
1231                     sync_pipe_signame(WSTOPSIG(wstatus)));
1232     } else if (WIFSIGNALED(wstatus)) {
1233       /* It died with a signal. */
1234       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1235                     "Child capture process died: %s%s",
1236                     sync_pipe_signame(WTERMSIG(wstatus)),
1237                     WCOREDUMP(wstatus) ? " - core dumped" : "");
1238     } else {
1239       /* What?  It had to either have exited, or stopped, or died with
1240          a signal; what happened here? */
1241       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1242                     "Child capture process died: wait status %#o", wstatus);
1243     }
1244   }
1245 #endif
1246
1247   /* No more child process. */
1248   capture_opts->fork_child = -1;
1249
1250   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
1251 }
1252
1253
1254 #ifndef _WIN32
1255 /* convert signal to corresponding name */
1256 static const char *
1257 sync_pipe_signame(int sig)
1258 {
1259   const char *sigmsg;
1260   static char sigmsg_buf[6+1+3+1];
1261
1262   switch (sig) {
1263
1264   case SIGHUP:
1265     sigmsg = "Hangup";
1266     break;
1267
1268   case SIGINT:
1269     sigmsg = "Interrupted";
1270     break;
1271
1272   case SIGQUIT:
1273     sigmsg = "Quit";
1274     break;
1275
1276   case SIGILL:
1277     sigmsg = "Illegal instruction";
1278     break;
1279
1280   case SIGTRAP:
1281     sigmsg = "Trace trap";
1282     break;
1283
1284   case SIGABRT:
1285     sigmsg = "Abort";
1286     break;
1287
1288   case SIGFPE:
1289     sigmsg = "Arithmetic exception";
1290     break;
1291
1292   case SIGKILL:
1293     sigmsg = "Killed";
1294     break;
1295
1296   case SIGBUS:
1297     sigmsg = "Bus error";
1298     break;
1299
1300   case SIGSEGV:
1301     sigmsg = "Segmentation violation";
1302     break;
1303
1304   /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
1305      Linux is POSIX compliant.  These are not POSIX-defined signals ---
1306      ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
1307
1308         ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
1309         were omitted from POSIX.1 because their behavior is
1310         implementation dependent and could not be adequately catego-
1311         rized.  Conforming implementations may deliver these sig-
1312         nals, but must document the circumstances under which they
1313         are delivered and note any restrictions concerning their
1314         delivery.''
1315
1316      So we only check for SIGSYS on those systems that happen to
1317      implement them (a system can be POSIX-compliant and implement
1318      them, it's just that POSIX doesn't *require* a POSIX-compliant
1319      system to implement them).
1320    */
1321
1322 #ifdef SIGSYS
1323   case SIGSYS:
1324     sigmsg = "Bad system call";
1325     break;
1326 #endif
1327
1328   case SIGPIPE:
1329     sigmsg = "Broken pipe";
1330     break;
1331
1332   case SIGALRM:
1333     sigmsg = "Alarm clock";
1334     break;
1335
1336   case SIGTERM:
1337     sigmsg = "Terminated";
1338     break;
1339
1340   default:
1341         /* Returning a static buffer is ok in the context we use it here */
1342     g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
1343     sigmsg = sigmsg_buf;
1344     break;
1345   }
1346   return sigmsg;
1347 }
1348 #endif
1349
1350
1351 #ifdef _WIN32
1352 /* tell the child through the signal pipe that we want to quit the capture */
1353 static void
1354 signal_pipe_capquit_to_child(capture_options *capture_opts)
1355 {
1356     const char quit_msg[] = "QUIT";
1357     int ret;
1358
1359
1360     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
1361
1362     /* it doesn't matter *what* we send here, the first byte will stop the capture */
1363     /* simply sending a "QUIT" string */
1364     /*pipe_write_block(capture_opts->signal_pipe_write_fd, SP_QUIT, quit_msg);*/
1365     ret = write(capture_opts->signal_pipe_write_fd, quit_msg, sizeof quit_msg);
1366     if(ret == -1) {
1367         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
1368               "signal_pipe_capquit_to_child: %d header: error %s", capture_opts->signal_pipe_write_fd, strerror(errno));
1369     }
1370 }
1371 #endif
1372
1373
1374 /* user wants to stop the capture run */
1375 void
1376 sync_pipe_stop(capture_options *capture_opts)
1377 {
1378 #ifdef _WIN32
1379   int count;
1380   DWORD childstatus;
1381   gboolean terminate = TRUE;
1382 #endif
1383
1384   if (capture_opts->fork_child != -1) {
1385 #ifndef _WIN32
1386     /* send the SIGUSR1 signal to close the capture child gracefully. */
1387     kill(capture_opts->fork_child, SIGUSR1);
1388 #else
1389 #define STOP_SLEEP_TIME 500 /* ms */
1390 #define STOP_CHECK_TIME 50
1391     /* First, use the special signal pipe to try to close the capture child
1392      * gracefully.
1393      */
1394     signal_pipe_capquit_to_child(capture_opts);
1395
1396     /* Next, wait for the process to exit on its own */
1397     for (count = 0; count < STOP_SLEEP_TIME / STOP_CHECK_TIME; count++) {
1398       if (GetExitCodeProcess((HANDLE) capture_opts->fork_child, &childstatus) &&
1399               childstatus != STILL_ACTIVE) {
1400         terminate = FALSE;
1401         break;
1402       }
1403       Sleep(STOP_CHECK_TIME);
1404     }
1405
1406     /* Force the issue. */
1407     if (terminate) {
1408       g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
1409             "sync_pipe_stop: forcing child to exit");
1410       sync_pipe_kill(capture_opts->fork_child);
1411     }
1412 #endif
1413   }
1414 }
1415
1416
1417 /* Wireshark has to exit, force the capture child to close */
1418 void
1419 sync_pipe_kill(int fork_child)
1420 {
1421   if (fork_child != -1) {
1422 #ifndef _WIN32
1423       kill(fork_child, SIGTERM);        /* SIGTERM so it can clean up if necessary */
1424 #else
1425       /* Remark: This is not the preferred method of closing a process!
1426        * the clean way would be getting the process id of the child process,
1427        * then getting window handle hWnd of that process (using EnumChildWindows),
1428        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
1429        *
1430        * Unfortunately, I don't know how to get the process id from the
1431        * handle.  OpenProcess will get an handle (not a window handle)
1432        * from the process ID; it will not get a window handle from the
1433        * process ID.  (How could it?  A process can have more than one
1434        * window.  For that matter, a process might have *no* windows,
1435        * as a process running dumpcap, the normal child process program,
1436        * probably does.)
1437        *
1438        * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
1439        * running in the same console; that's not necessarily the case for
1440        * us, as we might not be running in a console.
1441        * And this also will require to have the process id.
1442        */
1443       TerminateProcess((HANDLE) (fork_child), 0);
1444 #endif
1445   }
1446 }
1447
1448 #endif /* HAVE_LIBPCAP */