Eliminate proto_tree_add_text from packet-spice.c
[metze/wireshark/wip.git] / extcap.c
1 /* extcap.h
2  *
3  * Routines for extcap external capture
4  * Copyright 2013, Mike Ryan <mikeryan@lacklustre.net>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include <config.h>
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #ifdef WIN32
32 #include <windows.h>
33 #include <process.h>
34 #include <time.h>
35 #else
36 /* Include for unlink */
37 #include <unistd.h>
38 #endif
39
40 #include <glib.h>
41 #include <log.h>
42
43 #include <wsutil/file_util.h>
44 #include <wsutil/filesystem.h>
45 #include <wsutil/tempfile.h>
46
47 #include "capture_opts.h"
48
49 #ifdef HAVE_EXTCAP
50
51 #include "extcap.h"
52 #include "extcap_parser.h"
53
54 #ifdef _WIN32
55 static HANDLE pipe_h = NULL;
56 #endif
57
58 /* internal container, for all the extcap interfaces that have been found.
59  * will be resetted by every call to extcap_interface_list() and is being
60  * used in extcap_get_if_* as well as extcaps_init_initerfaces to ensure,
61  * that only extcap interfaces are being given to underlying extcap programs
62  */
63 static GHashTable *ifaces = NULL;
64
65 /* Prefix for the pipe interfaces */
66 #define EXTCAP_PIPE_PREFIX "wireshark_extcap"
67
68 /* Callback definition for extcap_foreach */
69 typedef gboolean (*extcap_cb_t)(const gchar *extcap, gchar *output, void *data,
70         gchar **err_str);
71
72 /* #define ARG_DEBUG */
73 #if ARG_DEBUG
74 static void extcap_debug_arguments ( extcap_arg *arg_iter );
75 #endif
76
77 static gboolean
78 extcap_if_exists(const char *ifname)
79 {
80     if ( ifname != NULL )
81     {
82         if ( ifaces != NULL )
83         {
84             if ( g_hash_table_size(ifaces) > 0 )
85             {
86                 if ( g_hash_table_lookup(ifaces, (const gchar *)ifname) != NULL )
87                 {
88                     return TRUE;
89                 }
90             }
91         }
92     }
93     return FALSE;
94 }
95
96 static gboolean
97 extcap_if_exists_for_extcap(const char *ifname, const char *extcap)
98 {
99     gchar * entry = NULL;
100
101     if ( extcap_if_exists(ifname) )
102     {
103         if ( ( entry = (gchar *)g_hash_table_lookup(ifaces, (const gchar *)ifname) ) != NULL )
104         {
105             if ( strcmp(entry, extcap) == 0 )
106                 return TRUE;
107         }
108     }
109
110     return FALSE;
111 }
112
113 static gchar *
114 extcap_if_executable(const char *ifname)
115 {
116     if ( extcap_if_exists(ifname) )
117         return (gchar *)g_hash_table_lookup(ifaces, (const gchar *)ifname);
118
119     return (gchar *)NULL;
120 }
121
122 static void
123 extcap_if_cleanup(void)
124 {
125     if ( ifaces == NULL )
126         ifaces = g_hash_table_new(g_str_hash, g_str_equal);
127
128     g_hash_table_remove_all(ifaces);
129 }
130
131 static void
132 extcap_if_add(gchar *ifname, gchar *extcap)
133 {
134     if ( g_hash_table_lookup(ifaces, ifname) == NULL )
135         g_hash_table_insert(ifaces, ifname, extcap);
136 }
137
138 static void extcap_foreach(gint argc, gchar **args, extcap_cb_t cb,
139         void *cb_data, char **err_str, const char * ifname _U_) {
140     const char *dirname = get_extcap_dir();
141     GDir *dir;
142     const gchar *file;
143     gboolean keep_going;
144     gchar **argv;
145
146     keep_going = TRUE;
147
148     argv = (gchar **) g_malloc0(sizeof(gchar *) * (argc + 2));
149
150     if ((dir = g_dir_open(dirname, 0, NULL)) != NULL) {
151 #ifdef WIN32
152         dirname = g_strescape(dirname,NULL);
153 #endif
154         while (keep_going && (file = g_dir_read_name(dir)) != NULL ) {
155             GString *extcap_string = NULL;
156             gchar *extcap = NULL;
157             gchar *command_output = NULL;
158             gboolean status = FALSE;
159             gint i;
160             gint exit_status = 0;
161             GError *error = NULL;
162
163             /* full path to extcap binary */
164             extcap_string = g_string_new("");
165 #ifdef WIN32
166             g_string_printf(extcap_string, "%s\\\\%s",dirname,file);
167             extcap = g_string_free(extcap_string, FALSE);
168 #else
169             g_string_printf(extcap_string, "%s/%s", dirname, file);
170             extcap = g_string_free(extcap_string, FALSE);
171 #endif
172             if ( extcap_if_exists(ifname) && !extcap_if_exists_for_extcap(ifname, extcap ) )
173                 continue;
174
175             argv[0] = extcap;
176             for (i = 0; i < argc; ++i)
177                 argv[i+1] = args[i];
178             argv[argc+1] = NULL;
179
180             status = g_spawn_sync(dirname, argv, NULL,
181                 (GSpawnFlags) 0, NULL, NULL,
182                     &command_output, NULL, &exit_status, &error);
183
184             if (status && exit_status == 0)
185             keep_going = cb(extcap, command_output, cb_data, err_str);
186
187             g_free(extcap);
188             g_free(command_output);
189         }
190
191         g_dir_close(dir);
192     }
193
194     g_free(argv);
195 }
196
197 static gboolean dlt_cb(const gchar *extcap _U_, gchar *output, void *data,
198         char **err_str) {
199     extcap_token_sentence *tokens;
200     extcap_dlt *dlts, *dlt_iter, *next;
201     if_capabilities_t *caps;
202     GList *linktype_list = NULL;
203     data_link_info_t *data_link_info;
204
205     tokens = extcap_tokenize_sentences(output);
206     extcap_parse_dlts(tokens, &dlts);
207
208     extcap_free_tokenized_sentence_list(tokens);
209
210     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Extcap pipe %s ", extcap);
211
212     /*
213      * Allocate the interface capabilities structure.
214      */
215     caps = (if_capabilities_t *) g_malloc(sizeof *caps);
216     caps->can_set_rfmon = FALSE;
217
218     dlt_iter = dlts;
219     while (dlt_iter != NULL ) {
220         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
221                 "  DLT %d name=\"%s\" display=\"%s\" ", dlt_iter->number,
222                 dlt_iter->name, dlt_iter->display);
223
224         data_link_info = g_new(data_link_info_t, 1);
225         data_link_info->dlt = dlt_iter->number;
226         data_link_info->name = g_strdup(dlt_iter->name);
227         data_link_info->description = g_strdup(dlt_iter->display);
228         linktype_list = g_list_append(linktype_list, data_link_info);
229         dlt_iter = dlt_iter->next_dlt;
230     }
231
232     /* Check to see if we built a list */
233     if (linktype_list != NULL && data != NULL) {
234         caps->data_link_types = linktype_list;
235         *(if_capabilities_t **) data = caps;
236     } else {
237         if (err_str) {
238             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "  returned no DLTs");
239             *err_str = g_strdup("Extcap returned no DLTs");
240         }
241         g_free(caps);
242     }
243
244     dlt_iter = dlts;
245     while (dlt_iter != NULL ) {
246         next = dlt_iter->next_dlt;
247         extcap_free_dlt(dlt_iter);
248         dlt_iter = next;
249     }
250
251     return FALSE;
252 }
253
254 if_capabilities_t *
255 extcap_get_if_dlts(const gchar *ifname, char **err_str) {
256     gchar *argv[3];
257     gint i;
258     if_capabilities_t *caps = NULL;
259
260     if (ifname != NULL && err_str != NULL)
261         *err_str = NULL;
262
263     if ( extcap_if_exists(ifname) )
264     {
265         argv[0] = g_strdup(EXTCAP_ARGUMENT_LIST_DLTS);
266         argv[1] = g_strdup(EXTCAP_ARGUMENT_INTERFACE);
267         argv[2] = g_strdup(ifname);
268
269         if (err_str)
270             *err_str = NULL;
271         extcap_foreach(3, argv, dlt_cb, &caps, err_str, ifname);
272
273         for (i = 0; i < 3; ++i)
274             g_free(argv[i]);
275     }
276
277     return caps;
278 }
279
280 static gboolean interfaces_cb(const gchar *extcap, gchar *output, void *data,
281         char **err_str _U_) {
282     GList **il = (GList **) data;
283     extcap_token_sentence *tokens;
284     extcap_interface *interfaces, *int_iter; /*, *next; */
285     if_info_t *if_info;
286
287     tokens = extcap_tokenize_sentences(output);
288     extcap_parse_interfaces(tokens, &interfaces);
289
290     extcap_free_tokenized_sentence_list(tokens);
291
292     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Extcap pipe %s ", extcap);
293
294     int_iter = interfaces;
295     while (int_iter != NULL ) {
296         if ( extcap_if_exists(int_iter->call) )
297         {
298             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_WARNING, "Extcap interface \"%s\" is already provided by \"%s\" ",
299                     int_iter->call, (gchar *)extcap_if_executable(int_iter->call) );
300             int_iter = int_iter->next_interface;
301             continue;
302         }
303
304         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "  Interface [%s] \"%s\" ",
305                 int_iter->call, int_iter->display);
306
307         if_info = g_new0(if_info_t, 1);
308         if_info->name = g_strdup(int_iter->call);
309         if_info->friendly_name = g_strdup(int_iter->display);
310
311         if_info->type = IF_EXTCAP;
312
313         if_info->extcap = g_strdup(extcap);
314         *il = g_list_append(*il, if_info);
315
316         extcap_if_add(g_strdup(int_iter->call), g_strdup(extcap) );
317         int_iter = int_iter->next_interface;
318     }
319
320     return TRUE;
321 }
322
323 GList *
324 extcap_interface_list(char **err_str) {
325     gchar *argv;
326     /* gint i; */
327     GList *ret = NULL;
328
329     if (err_str != NULL)
330     *err_str = NULL;
331
332     extcap_if_cleanup();
333
334     argv = g_strdup(EXTCAP_ARGUMENT_LIST_INTERFACES);
335
336     if (err_str)
337     *err_str = NULL;
338     extcap_foreach(1, &argv, interfaces_cb, &ret, err_str, NULL);
339
340     g_free(argv);
341
342     return ret;
343 }
344
345 static void g_free_1(gpointer data, gpointer user_data _U_)
346 {
347     g_free(data);
348 }
349
350 static void extcap_free_if_configuration(GList *list)
351 {
352     GList *elem;
353
354     for (elem = g_list_first(list); elem; elem = elem->next)
355     {
356         GList *arg_list;
357         if (elem->data == NULL)
358         {
359             continue;
360         }
361
362         arg_list = g_list_first((GList *)elem->data);
363         g_list_foreach(arg_list, g_free_1, NULL);
364         g_list_free(arg_list);
365     }
366     g_list_free(list);
367 }
368
369 static gboolean search_cb(const gchar *extcap _U_, gchar *output, void *data,
370         char **err_str _U_) {
371     extcap_token_sentence *tokens = NULL;
372     GList *arguments = NULL;
373     GList **il = (GList **) data;
374
375     tokens = extcap_tokenize_sentences(output);
376     arguments = extcap_parse_args(tokens);
377
378     extcap_free_tokenized_sentence_list(tokens);
379
380 #if ARG_DEBUG
381     extcap_debug_arguments ( arguments );
382 #endif
383
384     *il = g_list_append(*il, arguments);
385
386     /* By returning false, extcap_foreach will break on first found */
387     return TRUE;
388 }
389
390 GList *
391 extcap_get_if_configuration(const char * ifname) {
392     gchar *argv[4];
393     GList *ret = NULL;
394     gchar **err_str = NULL;
395
396     if ( extcap_if_exists(ifname) )
397     {
398         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Extcap path %s",
399                 get_extcap_dir());
400
401         if (err_str != NULL)
402         *err_str = NULL;
403
404         argv[0] = g_strdup(EXTCAP_ARGUMENT_CONFIG);
405         argv[1] = g_strdup(EXTCAP_ARGUMENT_INTERFACE);
406         argv[2] = g_strdup(ifname);
407         argv[3] = NULL;
408
409         extcap_foreach(4, argv, search_cb, &ret, err_str, ifname);
410     }
411
412     return ret;
413 }
414
415 void extcap_cleanup(capture_options * capture_opts) {
416     interface_options interface_opts;
417     guint icnt = 0;
418
419     for (icnt = 0; icnt < capture_opts->ifaces->len; icnt++) {
420         interface_opts = g_array_index(capture_opts->ifaces, interface_options,
421                 icnt);
422
423         /* skip native interfaces */
424         if (interface_opts.if_type != IF_EXTCAP)
425         continue;
426
427         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
428                 "Extcap [%s] - Cleaning up fifo: %s; PID: %d", interface_opts.name,
429                 interface_opts.extcap_fifo, interface_opts.extcap_pid);
430 #ifdef WIN32
431         if (pipe_h)
432         {
433             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
434                 "Extcap [%s] - Closing pipe", interface_opts.name);
435             FlushFileBuffers(pipe_h);
436             DisconnectNamedPipe(pipe_h);
437             CloseHandle(pipe_h);
438         }
439 #else
440         if (interface_opts.extcap_fifo != NULL && file_exists(interface_opts.extcap_fifo))
441         {
442             /* the fifo will not be freed here, but with the other capture_opts in capture_sync */
443             ws_unlink(interface_opts.extcap_fifo);
444             interface_opts.extcap_fifo = NULL;
445         }
446 #endif
447         /* Maybe the client closed and removed fifo, but ws should check if
448          * pid should be closed */
449         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
450                 "Extcap [%s] - Closing spawned PID: %d", interface_opts.name,
451                 interface_opts.extcap_pid);
452
453         if (interface_opts.extcap_child_watch > 0)
454         {
455             g_source_remove(interface_opts.extcap_child_watch);
456             interface_opts.extcap_child_watch = 0;
457         }
458
459         if (interface_opts.extcap_pid != INVALID_EXTCAP_PID)
460         {
461 #ifdef WIN32
462             TerminateProcess(interface_opts.extcap_pid, 0);
463 #endif
464             g_spawn_close_pid(interface_opts.extcap_pid);
465             interface_opts.extcap_pid = INVALID_EXTCAP_PID;
466         }
467
468         /* Make sure modified interface_opts is saved in capture_opts. */
469         capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, icnt);
470         g_array_insert_val(capture_opts->ifaces, icnt, interface_opts);
471     }
472 }
473
474 static void
475 extcap_arg_cb(gpointer key, gpointer value, gpointer data) {
476     GPtrArray *args = (GPtrArray *)data;
477
478     if ( key != NULL )
479     {
480         g_ptr_array_add(args, g_strdup((const gchar*)key));
481
482         if ( value != NULL )
483             g_ptr_array_add(args, g_strdup((const gchar*)value));
484     }
485 }
486
487 static void extcap_child_watch_cb(GPid pid, gint status _U_, gpointer user_data)
488 {
489     guint i;
490     interface_options interface_opts;
491     capture_options *capture_opts = (capture_options *)user_data;
492
493     /* Close handle to child process. */
494     g_spawn_close_pid(pid);
495
496     /* Update extcap_pid in interface options structure. */
497     for (i = 0; i < capture_opts->ifaces->len; i++)
498     {
499         interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
500         if (interface_opts.extcap_pid == pid)
501         {
502             interface_opts.extcap_pid = INVALID_EXTCAP_PID;
503             interface_opts.extcap_child_watch = 0;
504             capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, i);
505             g_array_insert_val(capture_opts->ifaces, i, interface_opts);
506             break;
507         }
508     }
509 }
510
511 /* call mkfifo for each extcap,
512  * returns FALSE if there's an error creating a FIFO */
513 gboolean
514 extcaps_init_initerfaces(capture_options *capture_opts)
515 {
516     guint i;
517     interface_options interface_opts;
518
519     for (i = 0; i < capture_opts->ifaces->len; i++)
520     {
521         GPtrArray *args = NULL;
522         GPid pid = INVALID_EXTCAP_PID;
523         gchar **tmp;
524         int tmp_i;
525
526         interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
527
528         /* skip native interfaces */
529         if (interface_opts.if_type != IF_EXTCAP )
530             continue;
531
532         /* create pipe for fifo */
533         if ( ! extcap_create_pipe ( &interface_opts.extcap_fifo ) )
534             return FALSE;
535
536         /* Create extcap call */
537         args = g_ptr_array_new();
538 #define add_arg(X) g_ptr_array_add(args, g_strdup(X))
539
540         add_arg(interface_opts.extcap);
541         add_arg(EXTCAP_ARGUMENT_RUN_CAPTURE);
542         add_arg(EXTCAP_ARGUMENT_INTERFACE);
543         add_arg(interface_opts.name);
544         add_arg(EXTCAP_ARGUMENT_RUN_PIPE);
545         add_arg(interface_opts.extcap_fifo);
546         if (interface_opts.extcap_args == NULL)
547         {
548             /* User did not perform interface configuration.
549              *
550              * Check if there are any boolean flags that are set by default
551              * and hence their argument should be added.
552              */
553             GList *arglist;
554             GList *elem;
555
556             arglist = extcap_get_if_configuration(interface_opts.name);
557             for (elem = g_list_first(arglist); elem; elem = elem->next)
558             {
559                 GList * arg_list;
560                 extcap_arg *arg_iter;
561
562                 if (elem->data == NULL)
563                 {
564                     continue;
565                 }
566
567                 arg_list = g_list_first((GList *)elem->data);
568                 while (arg_list != NULL)
569                 {
570                     /* In case of boolflags only first element in arg_list is relevant. */
571                     arg_iter = (extcap_arg*) (arg_list->data);
572
573                     if  (arg_iter->arg_type == EXTCAP_ARG_BOOLFLAG)
574                     {
575                         if (arg_iter->default_complex != NULL
576                             && extcap_complex_get_bool(arg_iter->default_complex))
577                         {
578                             add_arg(arg_iter->call);
579                         }
580                     }
581
582                     arg_list = arg_list->next;
583                 }
584             }
585
586             extcap_free_if_configuration(arglist);
587         }
588         else
589         {
590             g_hash_table_foreach(interface_opts.extcap_args, extcap_arg_cb, args);
591         }
592         add_arg(NULL);
593 #undef add_arg
594
595         /* Dump commandline parameters sent to extcap. */
596         for (tmp = (gchar **)args->pdata, tmp_i = 0; *tmp && **tmp; ++tmp_i, ++tmp)
597         {
598             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "argv[%d]: %s", tmp_i, *tmp);
599         }
600
601         /* Wireshark for windows crashes here sometimes *
602          * Access violation reading location 0x...      */
603         g_spawn_async(NULL, (gchar **)args->pdata, NULL,
604                     (GSpawnFlags) G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
605                     &pid,NULL);
606
607         g_ptr_array_foreach(args, (GFunc)g_free, NULL);
608         g_ptr_array_free(args, TRUE);
609         interface_opts.extcap_pid = pid;
610         interface_opts.extcap_child_watch =
611             g_child_watch_add(pid, extcap_child_watch_cb, (gpointer)capture_opts);
612         capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, i);
613         g_array_insert_val(capture_opts->ifaces, i, interface_opts);
614
615 #ifdef WIN32
616         /* On Windows, wait for extcap to connect to named pipe.
617          * Some extcaps will present UAC screen to user.
618          * 30 second timeout should be reasonable timeout for extcap to
619          * connect to named pipe (including user interaction).
620          * Wait on multiple object in case of extcap termination
621          * without opening pipe.
622          *
623          * Minimum supported version of Windows: XP / Server 2003.
624          */
625         if (pid != INVALID_EXTCAP_PID)
626         {
627             DWORD dw;
628             HANDLE handles[2];
629             OVERLAPPED ov;
630             ov.Pointer = 0;
631             ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
632
633             ConnectNamedPipe(pipe_h, &ov);
634             handles[0] = ov.hEvent;
635             handles[1] = pid;
636
637             if (GetLastError() == ERROR_PIPE_CONNECTED)
638             {
639                 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap connected to pipe");
640             }
641             else
642             {
643                 dw = WaitForMultipleObjects(2, handles, FALSE, 30000);
644                 if (dw == WAIT_OBJECT_0)
645                 {
646                     /* ConnectNamedPipe finished. */
647                     DWORD code;
648
649                     code = GetLastError();
650                     if (code == ERROR_IO_PENDING)
651                     {
652                         DWORD dummy;
653                         if (!GetOverlappedResult(ov.hEvent, &ov, &dummy, TRUE))
654                         {
655                             code = GetLastError();
656                         }
657                         else
658                         {
659                             code = ERROR_SUCCESS;
660                         }
661                     }
662
663                     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe code: %d", code);
664                 }
665                 else if (dw == (WAIT_OBJECT_0 + 1))
666                 {
667                     /* extcap process terminated. */
668                     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe!");
669                 }
670                 else if (dw == WAIT_TIMEOUT)
671                 {
672                     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds!");
673                 }
674                 else
675                 {
676                     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForMultipleObjects returned 0x%08X. Error %d", dw, GetLastError());
677                 }
678             }
679
680             CloseHandle(ov.hEvent);
681         }
682 #endif
683     }
684
685     return TRUE;
686 }
687
688 #ifdef WIN32
689 /* called by capture_sync to get the CreatNamedPipe handle*/
690 HANDLE
691 extcap_get_win32_handle()
692 {
693     return pipe_h;
694 }
695 #endif
696
697 gboolean extcap_create_pipe(char ** fifo)
698 {
699 #ifdef WIN32
700     gchar timestr[ 14+1 ];
701     time_t current_time;
702
703     gchar *pipename = NULL;
704
705     SECURITY_ATTRIBUTES security;
706     /* create pipename */
707     current_time = time(NULL);
708     strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", localtime(&current_time));
709     pipename = g_strconcat ( "\\\\.\\pipe\\", EXTCAP_PIPE_PREFIX, "_", timestr, NULL );
710
711     /* Security struct to enable Inheritable HANDLE */
712     memset(&security, 0, sizeof(SECURITY_ATTRIBUTES));
713     security.nLength = sizeof(SECURITY_ATTRIBUTES);
714     security.bInheritHandle = TRUE;
715     security.lpSecurityDescriptor = NULL;
716
717     /* create a namedPipe*/
718     pipe_h = CreateNamedPipe(
719                 utf_8to16(pipename),
720                 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
721                 PIPE_TYPE_MESSAGE| PIPE_READMODE_MESSAGE | PIPE_WAIT,
722                 5, 65536, 65536,
723                 300,
724                 &security);
725
726     if (pipe_h == INVALID_HANDLE_VALUE)
727     {
728         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,"\nError creating pipe => (%d)", GetLastError());
729         return FALSE;
730     }
731     else
732     {
733         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,"\nWireshark Created pipe =>(%s)",pipename);
734         *fifo = g_strdup(pipename);
735     }
736 #else
737     gchar *temp_name = NULL;
738     int fd = 0;
739
740     if ( ( fd = create_tempfile ( &temp_name, EXTCAP_PIPE_PREFIX ) ) == 0 )
741         return FALSE;
742
743     ws_close(fd);
744
745     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
746             "Extcap - Creating fifo: %s", temp_name);
747
748     if ( file_exists(temp_name) )
749         ws_unlink(temp_name);
750
751     if (mkfifo(temp_name, 0600) == 0)
752         *fifo = g_strdup(temp_name);
753 #endif
754
755     return TRUE;
756 }
757
758 #if ARG_DEBUG
759 void extcap_debug_arguments ( extcap_arg *arg_iter )
760 {
761     extcap_value *v = NULL;
762     GList *walker = NULL;
763
764     printf("debug - parser dump\n");
765     while (arg_iter != NULL) {
766         printf("ARG %d call=%s display=\"%s\" type=", arg_iter->arg_num, arg_iter->call, arg_iter->display);
767
768         switch (arg_iter->arg_type) {
769             case EXTCAP_ARG_INTEGER:
770             printf("int\n");
771             break;
772             case EXTCAP_ARG_UNSIGNED:
773             printf("unsigned\n");
774             break;
775             case EXTCAP_ARG_LONG:
776             printf("long\n");
777             break;
778             case EXTCAP_ARG_DOUBLE:
779             printf("double\n");
780             break;
781             case EXTCAP_ARG_BOOLEAN:
782             printf("boolean\n");
783             break;
784             case EXTCAP_ARG_MENU:
785             printf("menu\n");
786             break;
787             case EXTCAP_ARG_RADIO:
788             printf("radio\n");
789             break;
790             case EXTCAP_ARG_SELECTOR:
791             printf("selctor\n");
792             break;
793             case EXTCAP_ARG_STRING:
794             printf ( "string\n" );
795             break;
796             case EXTCAP_ARG_MULTICHECK:
797             printf ( "unknown\n" );
798             break;
799             case EXTCAP_ARG_UNKNOWN:
800             printf ( "unknown\n" );
801             break;
802         }
803
804         if (arg_iter->range_start != NULL && arg_iter->range_end != NULL) {
805             printf("\tRange: ");
806             extcap_printf_complex(arg_iter->range_start);
807             printf(" - ");
808             extcap_printf_complex(arg_iter->range_end);
809             printf("\n");
810         }
811
812         for ( walker = g_list_first ( arg_iter->value_list ); walker; walker = walker->next )
813         {
814             v = (extcap_value *)walker->data;
815             if (v->is_default == TRUE)
816             printf("*");
817             printf("\tcall=\"%p\" display=\"%p\"\n", v->call, v->display);
818             printf("\tcall=\"%s\" display=\"%s\"\n", v->call, v->display);
819         }
820
821         arg_iter = arg_iter->next_arg;
822     }
823 }
824 #endif
825 #endif
826
827 /*
828  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
829  *
830  * Local variables:
831  * c-basic-offset: 4
832  * tab-width: 8
833  * indent-tabs-mode: nil
834  * End:
835  *
836  * vi: set shiftwidth=4 tabstop=8 expandtab:
837  * :indentSize=4:tabSize=8:noTabs=true:
838  */