2 * Base function for extcaps
4 * Copyright 2015, Dario Lombardo
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 #define WS_LOG_DOMAIN LOG_DOMAIN_EXTCAP
16 #include "extcap-base.h"
22 #include <wsutil/wslog.h>
24 #include <wsutil/ws_assert.h>
26 #include "ws_attributes.h"
29 EXTCAP_BASE_OPTIONS_ENUM
32 typedef struct _extcap_interface
39 char * dltdescription
;
42 typedef struct _extcap_option
{
47 static FILE *custom_log
= NULL
;
49 /* used to inform to extcap application that end of application is requested */
50 bool extcap_end_application
= false;
51 /* graceful shutdown callback, can be null */
52 void (*extcap_graceful_shutdown_cb
)(void) = NULL
;
54 static void extcap_init_log_file(const char *filename
);
56 /* Called from signals */
59 extcap_exit_from_loop(DWORD dwCtrlType _U_
)
61 static void extcap_exit_from_loop(int signo _U_
)
64 ws_debug("Exiting from main loop by signal");
65 extcap_end_application
= true;
66 if (extcap_graceful_shutdown_cb
!= NULL
) {
67 extcap_graceful_shutdown_cb();
74 void extcap_base_register_interface(extcap_parameters
* extcap
, const char * interface
, const char * ifdescription
, uint16_t dlt
, const char * dltdescription
)
76 extcap_base_register_interface_ext(extcap
, interface
, ifdescription
, dlt
, NULL
, dltdescription
);
79 void extcap_base_register_interface_ext(extcap_parameters
* extcap
,
80 const char * interface
, const char * ifdescription
,
81 uint16_t dlt
, const char * dltname
, const char * dltdescription
)
83 extcap_interface
* iface
;
85 if (interface
== NULL
)
88 iface
= g_new0(extcap_interface
, 1);
90 iface
->interface
= g_strdup(interface
);
91 iface
->description
= g_strdup(ifdescription
);
93 iface
->dltname
= g_strdup(dltname
);
94 iface
->dltdescription
= g_strdup(dltdescription
);
96 extcap
->interfaces
= g_list_append(extcap
->interfaces
, (void *) iface
);
99 bool extcap_base_register_graceful_shutdown_cb(extcap_parameters
* extcap _U_
, void (*callback
)(void))
102 struct sigaction sig_handler
= { .sa_handler
= extcap_exit_from_loop
};
105 extcap_end_application
= false;
106 extcap_graceful_shutdown_cb
= callback
;
108 if (!SetConsoleCtrlHandler(extcap_exit_from_loop
, true)) {
109 ws_warning("Can't set console handler");
113 /* Catch signals to be able to cleanup config later */
114 if (sigaction(SIGINT
, &sig_handler
, NULL
)) {
115 ws_warning("Can't set SIGINT signal handler");
118 if (sigaction(SIGTERM
, &sig_handler
, NULL
)) {
119 ws_warning("Can't set SIGTERM signal handler");
122 if (sigaction(SIGPIPE
, &sig_handler
, NULL
)) {
123 ws_warning("Can't set SIGPIPE signal handler");
131 void extcap_base_set_util_info(extcap_parameters
* extcap
, const char * exename
, const char * major
,
132 const char * minor
, const char * release
, const char * helppage
)
134 extcap
->exename
= g_path_get_basename(exename
);
140 extcap
->version
= ws_strdup_printf("%s%s%s%s%s",
145 release
? release
: "");
146 extcap
->helppage
= g_strdup(helppage
);
149 void extcap_base_set_compiled_with(extcap_parameters
* extcap
, const char *fmt
, ...)
154 extcap
->compiled_with
= ws_strdup_vprintf(fmt
, ap
);
158 void extcap_base_set_running_with(extcap_parameters
* extcap
, const char *fmt
, ...)
163 extcap
->running_with
= ws_strdup_vprintf(fmt
, ap
);
167 void extcap_log_init(const char *progname
)
169 ws_log_init(progname
, NULL
);
170 /* extcaps cannot write debug information to parent on stderr. */
171 ws_log_console_writer_set_use_stdout(true);
172 ws_noisy("Extcap log initialization finished");
175 uint8_t extcap_base_parse_options(extcap_parameters
* extcap
, int result
, char * optargument
)
178 enum ws_log_level level
;
181 case EXTCAP_OPT_LOG_LEVEL
:
182 level
= ws_log_set_level_str(optargument
);
183 if (level
== LOG_LEVEL_NONE
) {
184 /* Invalid log level string. */
187 extcap
->debug
= level
;
189 case EXTCAP_OPT_LOG_FILE
:
190 extcap_init_log_file(optargument
);
192 case EXTCAP_OPT_LIST_INTERFACES
:
193 extcap
->do_list_interfaces
= 1;
195 case EXTCAP_OPT_VERSION
:
196 extcap
->ws_version
= g_strdup(optargument
);
197 extcap
->do_version
= 1;
199 case EXTCAP_OPT_LIST_DLTS
:
200 extcap
->do_list_dlts
= 1;
202 case EXTCAP_OPT_INTERFACE
:
203 extcap
->interface
= g_strdup(optargument
);
205 case EXTCAP_OPT_CONFIG
:
206 extcap
->show_config
= 1;
208 case EXTCAP_OPT_CAPTURE
:
211 case EXTCAP_OPT_CAPTURE_FILTER
:
212 extcap
->capture_filter
= g_strdup(optargument
);
214 case EXTCAP_OPT_FIFO
:
215 extcap
->fifo
= g_strdup(optargument
);
224 static void extcap_iface_print(void * data
, void * userdata _U_
)
226 extcap_interface
* iface
= (extcap_interface
*)data
;
228 printf("interface {value=%s}", iface
->interface
);
229 if (iface
->description
!= NULL
)
230 printf ("{display=%s}\n", iface
->description
);
235 static int extcap_iface_compare(gconstpointer a
, gconstpointer b
)
237 const extcap_interface
* iface_a
= (const extcap_interface
*)a
;
239 return (g_strcmp0(iface_a
->interface
, (const char *) b
));
242 static void extcap_print_version(extcap_parameters
* extcap
)
244 printf("extcap {version=%s}", extcap
->version
!= NULL
? extcap
->version
: "unknown");
245 if (extcap
->helppage
!= NULL
)
246 printf("{help=%s}", extcap
->helppage
);
250 static int extcap_iface_listall(extcap_parameters
* extcap
, uint8_t list_ifs
)
253 if (g_list_length(extcap
->interfaces
) > 0) {
254 extcap_print_version(extcap
);
255 g_list_foreach(extcap
->interfaces
, extcap_iface_print
, extcap
);
257 } else if (extcap
->do_version
) {
258 extcap_print_version(extcap
);
260 GList
* element
= NULL
;
261 extcap_interface
* iface
= NULL
;
262 if ((element
= g_list_find_custom(extcap
->interfaces
, extcap
->interface
, extcap_iface_compare
)) == NULL
)
265 iface
= (extcap_interface
*) element
->data
;
266 printf("dlt {number=%u}{name=%s}", iface
->dlt
, iface
->dltname
!= NULL
? iface
->dltname
: iface
->interface
);
267 if (iface
->description
!= NULL
)
268 printf ("{display=%s}\n", iface
->dltdescription
);
276 uint8_t extcap_base_handle_interface(extcap_parameters
* extcap
)
278 /* A fifo must be provided for capture */
279 if (extcap
->capture
&& (extcap
->fifo
== NULL
|| strlen(extcap
->fifo
) <= 0)) {
281 ws_error("Extcap Error: No FIFO pipe provided");
285 if (extcap
->do_list_interfaces
) {
286 return extcap_iface_listall(extcap
, 1);
287 } else if (extcap
->do_version
|| extcap
->do_list_dlts
) {
288 return extcap_iface_listall(extcap
, 0);
294 static void extcap_iface_free(void * data
)
296 extcap_interface
* iface
= (extcap_interface
*)data
;
297 g_free(iface
->interface
);
298 g_free(iface
->description
);
299 g_free(iface
->dltname
);
300 g_free(iface
->dltdescription
);
304 static void extcap_help_option_free(void * option
)
306 extcap_option_t
* o
= (extcap_option_t
*)option
;
312 void extcap_base_cleanup(extcap_parameters
** extcap
)
314 g_list_free_full((*extcap
)->interfaces
, extcap_iface_free
);
315 g_free((*extcap
)->exename
);
316 g_free((*extcap
)->fifo
);
317 g_free((*extcap
)->interface
);
318 g_free((*extcap
)->version
);
319 g_free((*extcap
)->compiled_with
);
320 g_free((*extcap
)->running_with
);
321 g_free((*extcap
)->helppage
);
322 g_free((*extcap
)->help_header
);
323 g_free((*extcap
)->ws_version
);
324 g_list_free_full((*extcap
)->help_options
, extcap_help_option_free
);
329 static void extcap_print_option(void * option
, void * user_data _U_
)
331 extcap_option_t
* o
= (extcap_option_t
*)option
;
332 printf("\t%s: %s\n", o
->optname
, o
->optdesc
);
335 void extcap_version_print(extcap_parameters
* extcap
)
337 printf("%s version %s\n", extcap
->exename
, extcap
->version
);
338 if (extcap
->compiled_with
!= NULL
)
339 printf("Compiled with %s\n", extcap
->compiled_with
);
340 if (extcap
->running_with
!= NULL
)
341 printf("Running with %s\n", extcap
->running_with
);
344 void extcap_help_print(extcap_parameters
* extcap
)
346 printf("\nWireshark - %s v%s\n\n", extcap
->exename
, extcap
->version
);
348 printf("%s", extcap
->help_header
);
350 printf("Options:\n");
351 g_list_foreach(extcap
->help_options
, extcap_print_option
, NULL
);
355 void extcap_help_add_option(extcap_parameters
* extcap
, const char * help_option_name
, const char * help_option_desc
)
357 extcap_option_t
* o
= g_new0(extcap_option_t
, 1);
358 o
->optname
= g_strdup(help_option_name
);
359 o
->optdesc
= g_strdup(help_option_desc
);
361 extcap
->help_options
= g_list_append(extcap
->help_options
, o
);
364 void extcap_help_add_header(extcap_parameters
* extcap
, char * help_header
)
366 extcap
->help_header
= g_strdup(help_header
);
367 extcap_help_add_option(extcap
, "--extcap-interfaces", "list the extcap Interfaces");
368 extcap_help_add_option(extcap
, "--extcap-dlts", "list the DLTs");
369 extcap_help_add_option(extcap
, "--extcap-interface <iface>", "specify the extcap interface");
370 extcap_help_add_option(extcap
, "--extcap-config", "list the additional configuration for an interface");
371 extcap_help_add_option(extcap
, "--capture", "run the capture");
372 extcap_help_add_option(extcap
, "--extcap-capture-filter <filter>", "the capture filter");
373 extcap_help_add_option(extcap
, "--fifo <file>", "dump data to file or fifo");
374 extcap_help_add_option(extcap
, "--extcap-version", "print tool version");
375 extcap_help_add_option(extcap
, "--log-level", "Set the log level");
376 extcap_help_add_option(extcap
, "--log-file", "Set a log file to log messages in addition to the console");
379 static void extcap_init_log_file(const char* filename
)
381 if (!filename
|| strlen(filename
) == 0)
382 ws_error("Missing log file name");
383 custom_log
= fopen(filename
, "w");
385 ws_error("Can't open custom log file: %s (%s)", filename
, strerror(errno
));
386 ws_log_add_custom_file(custom_log
);
389 void extcap_config_debug(unsigned* count
)
391 printf("arg {number=%u}{call=--log-level}{display=Set the log level}"
392 "{type=selector}{tooltip=Set the log level}{required=false}"
393 "{group=Debug}\n", *count
);
394 printf("value {arg=%u}{value=message}{display=Message}{default=true}\n", *count
);
395 printf("value {arg=%u}{value=info}{display=Info}\n", *count
);
396 printf("value {arg=%u}{value=debug}{display=Debug}\n", *count
);
397 printf("value {arg=%u}{value=noisy}{display=Noisy}\n", *count
);
399 printf("arg {number=%u}{call=--log-file}{display=Use a file for logging}"
400 "{type=fileselect}{tooltip=Set a file where log messages are written}{required=false}"
401 "{group=Debug}\n", (*count
)++);
404 void extcap_cmdline_debug(char** ar
, const unsigned n
)
406 GString
* cmdline
= g_string_new("cmdline: ");
408 for (i
= 0; i
< n
; i
++)
409 g_string_append_printf(cmdline
, "%s ", ar
[i
]);
410 ws_debug("%s", cmdline
->str
);
411 g_string_free(cmdline
, true);
415 * Editor modelines - https://www.wireshark.org/tools/modelines.html
420 * indent-tabs-mode: nil
423 * vi: set shiftwidth=4 tabstop=8 expandtab:
424 * :indentSize=4:tabSize=8:noTabs=true: