Bug Summary

File:builds/wireshark/wireshark/extcap/extcap-base.c
Warning:line 288, column 9
Potential leak of memory pointed to by 'buffer'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name extcap-base.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-08-15-100306-3660-1 -x c /builds/wireshark/wireshark/extcap/extcap-base.c
1/* extcap-base.c
2 * Base function for extcaps
3 *
4 * Copyright 2015, Dario Lombardo
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13#include "config.h"
14#define WS_LOG_DOMAIN"Extcap" LOG_DOMAIN_EXTCAP"Extcap"
15
16#include "extcap-base.h"
17
18#include <stdlib.h>
19#include <stdint.h>
20#include <string.h>
21#include <errno(*__errno_location ()).h>
22
23#include <wsutil/wslog.h>
24#include <wsutil/ws_assert.h>
25#include <wsutil/file_util.h>
26
27#ifdef _WIN32
28#include <wsutil/unicode-utils.h>
29#include <wsutil/win32-utils.h>
30#endif
31
32#include <capture/sync_pipe.h>
33
34#include "ws_attributes.h"
35
36enum extcap_options {
37 EXTCAP_BASE_OPTIONS_ENUMEXTCAP_OPT_LIST_INTERFACES, EXTCAP_OPT_VERSION, EXTCAP_OPT_LIST_DLTS
, EXTCAP_OPT_INTERFACE, EXTCAP_OPT_CONFIG, EXTCAP_OPT_CONFIG_OPTION_NAME
, EXTCAP_OPT_CONFIG_OPTION_VALUE, EXTCAP_OPT_CLEANUP_POSTKILL
, EXTCAP_OPT_CAPTURE, EXTCAP_OPT_CAPTURE_FILTER, EXTCAP_OPT_FIFO
, EXTCAP_OPT_CONTROL_OUT, EXTCAP_OPT_CONTROL_IN, EXTCAP_OPT_LOG_LEVEL
, EXTCAP_OPT_LOG_FILE
38};
39
40typedef struct _extcap_interface
41{
42 char * interface;
43 char * description;
44
45 uint16_t dlt;
46 char * dltname;
47 char * dltdescription;
48} extcap_interface;
49
50typedef struct _extcap_option {
51 char * optname;
52 char * optdesc;
53} extcap_option_t;
54
55static FILE *custom_log;
56
57/* used to inform to extcap application that end of application is requested */
58bool_Bool extcap_end_application;
59/* graceful shutdown callback, can be null */
60static void (*extcap_graceful_shutdown_cb)(void);
61/* toolbar control callback, can be null */
62static extcap_toolbar_control_cb_t extcap_toolbar_control_cb;
63
64static void extcap_init_log_file(const char *filename);
65
66/* Called from signals */
67#ifdef _WIN32
68static BOOL WINAPI
69extcap_exit_from_loop(DWORD dwCtrlType _U___attribute__((unused)))
70#else
71static void extcap_exit_from_loop(int signo _U___attribute__((unused)))
72#endif /* _WIN32 */
73{
74 ws_debug("Exiting from main loop by signal")do { if (1) { ws_log_full("Extcap", LOG_LEVEL_DEBUG, "extcap/extcap-base.c"
, 74, __func__, "Exiting from main loop by signal"); } } while
(0)
;
75 extcap_end_application = true1;
76 if (extcap_graceful_shutdown_cb != NULL((void*)0)) {
77 extcap_graceful_shutdown_cb();
78 }
79#ifdef _WIN32
80 return true1;
81#endif /* _WIN32 */
82}
83
84void extcap_base_register_interface(extcap_parameters * extcap, const char * interface, const char * ifdescription, uint16_t dlt, const char * dltdescription )
85{
86 extcap_base_register_interface_ext(extcap, interface, ifdescription, dlt, NULL((void*)0), dltdescription );
87}
88
89void extcap_base_register_interface_ext(extcap_parameters * extcap,
90 const char * interface, const char * ifdescription,
91 uint16_t dlt, const char * dltname, const char * dltdescription )
92{
93 extcap_interface * iface;
94
95 if (interface == NULL((void*)0))
96 return;
97
98 iface = g_new0(extcap_interface, 1)((extcap_interface *) g_malloc0_n ((1), sizeof (extcap_interface
)))
;
99
100 iface->interface = g_strdup(interface)g_strdup_inline (interface);
101 iface->description = g_strdup(ifdescription)g_strdup_inline (ifdescription);
102 iface->dlt = dlt;
103 iface->dltname = g_strdup(dltname)g_strdup_inline (dltname);
104 iface->dltdescription = g_strdup(dltdescription)g_strdup_inline (dltdescription);
105
106 extcap->interfaces = g_list_append(extcap->interfaces, (void *) iface);
107}
108
109bool_Bool extcap_base_register_graceful_shutdown_cb(extcap_parameters * extcap _U___attribute__((unused)), void (*callback)(void))
110{
111#ifndef _WIN32
112 struct sigaction sig_handler = { .sa_handler__sigaction_handler.sa_handler = extcap_exit_from_loop };
113#endif
114
115 extcap_end_application = false0;
116 extcap_graceful_shutdown_cb = callback;
117#ifdef _WIN32
118 /* This signal can be triggered if extcap is ran manually from a command prompt,
119 * but cannot be triggered by wireshark. On Windows, wireshark will therefore terminate
120 * the program when the user clicks "stop". Use postkill_cb to try and cleanup afterwards
121 * if needed.
122 */
123 if (!SetConsoleCtrlHandler(extcap_exit_from_loop, true1)) {
124 ws_warning("Can't set console handler")do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 124, __func__, "Can't set console handler"); } } while (0)
;
125 return false0;
126 }
127#else
128 /* Catch signals to be able to cleanup config later */
129 if (sigaction(SIGINT2, &sig_handler, NULL((void*)0))) {
130 ws_warning("Can't set SIGINT signal handler")do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 130, __func__, "Can't set SIGINT signal handler"); } } while
(0)
;
131 return false0;
132 }
133 if (sigaction(SIGTERM15, &sig_handler, NULL((void*)0))) {
134 ws_warning("Can't set SIGTERM signal handler")do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 134, __func__, "Can't set SIGTERM signal handler"); } } while
(0)
;
135 return false0;
136 }
137 if (sigaction(SIGPIPE13, &sig_handler, NULL((void*)0))) {
138 ws_warning("Can't set SIGPIPE signal handler")do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 138, __func__, "Can't set SIGPIPE signal handler"); } } while
(0)
;
139 return false0;
140 }
141#endif /* _WIN32 */
142
143 return true1;
144}
145
146bool_Bool extcap_base_register_cleanup_postkill_cb(extcap_parameters* extcap, void (*callback)(void))
147{
148 extcap->cleanup_postkill_cb = callback;
149 return true1;
150}
151
152bool_Bool extcap_base_register_toolbar_control_cb(extcap_parameters * extcap _U___attribute__((unused)), extcap_toolbar_control_cb_t callback)
153{
154 extcap_toolbar_control_cb = callback;
155 return true1;
156}
157
158void extcap_base_set_util_info(extcap_parameters * extcap, const char * exename, const char * major,
159 const char * minor, const char * release, const char * helppage)
160{
161 extcap->exename = g_path_get_basename(exename);
162
163 ws_assert(major)do { if ((1) && !(major)) ws_log_fatal_full("Extcap",
LOG_LEVEL_ERROR, "extcap/extcap-base.c", 163, __func__, "assertion failed: %s"
, "major"); } while (0)
;
164 if (!minor)
165 ws_assert(!release)do { if ((1) && !(!release)) ws_log_fatal_full("Extcap"
, LOG_LEVEL_ERROR, "extcap/extcap-base.c", 165, __func__, "assertion failed: %s"
, "!release"); } while (0)
;
166
167 extcap->version = ws_strdup_printf("%s%s%s%s%s",wmem_strdup_printf(((void*)0), "%s%s%s%s%s", major, minor ? "."
: "", minor ? minor : "", release ? "." : "", release ? release
: "")
168 major,wmem_strdup_printf(((void*)0), "%s%s%s%s%s", major, minor ? "."
: "", minor ? minor : "", release ? "." : "", release ? release
: "")
169 minor ? "." : "",wmem_strdup_printf(((void*)0), "%s%s%s%s%s", major, minor ? "."
: "", minor ? minor : "", release ? "." : "", release ? release
: "")
170 minor ? minor : "",wmem_strdup_printf(((void*)0), "%s%s%s%s%s", major, minor ? "."
: "", minor ? minor : "", release ? "." : "", release ? release
: "")
171 release ? "." : "",wmem_strdup_printf(((void*)0), "%s%s%s%s%s", major, minor ? "."
: "", minor ? minor : "", release ? "." : "", release ? release
: "")
172 release ? release : "")wmem_strdup_printf(((void*)0), "%s%s%s%s%s", major, minor ? "."
: "", minor ? minor : "", release ? "." : "", release ? release
: "")
;
173 extcap->helppage = g_strdup(helppage)g_strdup_inline (helppage);
174}
175
176void extcap_base_set_compiled_with(extcap_parameters * extcap, const char *fmt, ...)
177{
178 va_list ap;
179
180 va_start(ap, fmt)__builtin_va_start(ap, fmt);
181 extcap->compiled_with = ws_strdup_vprintf(fmt, ap)wmem_strdup_vprintf(((void*)0), fmt, ap);
182 va_end(ap)__builtin_va_end(ap);
183}
184
185void extcap_base_set_running_with(extcap_parameters * extcap, const char *fmt, ...)
186{
187 va_list ap;
188
189 va_start(ap, fmt)__builtin_va_start(ap, fmt);
190 extcap->running_with = ws_strdup_vprintf(fmt, ap)wmem_strdup_vprintf(((void*)0), fmt, ap);
191 va_end(ap)__builtin_va_end(ap);
192}
193
194static void
195extcap_log_writer(const char *domain, enum ws_log_level level,
196 const char *file, long line, const char *func,
197 const char *fatal_msg _U___attribute__((unused)), ws_log_manifest_t *mft,
198 const char *user_format, va_list user_ap,
199 void *user_data)
200{
201 extcap_parameters *extcap_conf = (extcap_parameters*)user_data;
202
203 if (extcap_conf && extcap_conf->control_out && extcap_conf->control_out_fd != -1) {
204 /* Format the log message as what the sync pipe expects:
205 * The numeric level, followed by a colon, and then the
206 * string matching the standard log string. */
207 GString *msg = g_string_new(NULL((void*)0));
208 g_string_append_printf(msg, "%u:", level);
209 if (file != NULL((void*)0)) {
210 g_string_append_printf(msg, "%s", file);
211 if (line >= 0) {
212 g_string_append_printf(msg, ":%ld", line);
213 }
214 g_string_append(msg, " -- ")(__builtin_constant_p (" -- ") ? __extension__ ({ const char *
const __val = (" -- "); g_string_append_len_inline (msg, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (msg, " -- "
, (gssize) -1))
;
215 }
216 if (func != NULL((void*)0)) {
217 g_string_append_printf(msg, "%s(): ", func);
218 }
219 g_string_append_vprintf(msg, user_format, user_ap);
220
221 /* If it's possible to write more than PIPE_BUF, we should acquire
222 * a mutex just in case here. */
223 sync_pipe_write_string_msg(extcap_conf->control_out_fd, SP_LOG_MSG'L', msg->str);
224 g_string_free(msg, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(msg), ((!(0)))) : g_string_free_and_steal (msg)) : (g_string_free
) ((msg), ((!(0)))))
;
225 } else {
226 ws_log_console_writer(domain, level, file, line, func, mft, user_format, user_ap);
227 }
228}
229
230void extcap_log_init(extcap_parameters *extcap_conf)
231{
232 ws_log_init(NULL((void*)0), "Extcap Debug Console");
233 ws_log_set_writer_with_data(extcap_log_writer, extcap_conf, NULL((void*)0));
234 ws_noisy("Extcap log initialization finished")do { if (1) { ws_log_full("Extcap", LOG_LEVEL_NOISY, "extcap/extcap-base.c"
, 234, __func__, "Extcap log initialization finished"); } } while
(0)
;
235}
236
237static int
238open_control_in(const char *pipename)
239{
240 int fd = -1;
241#ifndef _WIN32
242 fd = ws_openopen(pipename, O_RDONLY00, 0000 /* no creation so don't matter */);
243 if (fd == -1) {
244 ws_warning("couldn't open %s (%i)", g_strerror(errno), errno)do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 244, __func__, "couldn't open %s (%i)", g_strerror((*__errno_location
())), (*__errno_location ())); } } while (0)
;
245 }
246#else
247 if (!win32_is_pipe_name(pipename)) {
248 return -1;
249 }
250 /* Wait for the pipe to appear */
251 HANDLE hPipe;
252 while (1) {
253 hPipe = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL((void*)0),
254 OPEN_EXISTING, 0, NULL((void*)0));
255
256 if (hPipe != INVALID_HANDLE_VALUE) {
257 fd = _open_osfhandle((intptr_t)hPipe, O_RDONLY00 | O_BINARY0);
258 break;
259 }
260
261 if (GetLastError() != ERROR_PIPE_BUSY) {
262 ws_warning("Error on control in pipe open: %s",do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 263, __func__, "Error on control in pipe open: %s", win32strerror
(GetLastError())); } } while (0)
263 win32strerror(GetLastError()))do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 263, __func__, "Error on control in pipe open: %s", win32strerror
(GetLastError())); } } while (0)
;
264 break;
265 }
266
267 if (!WaitNamedPipe(utf_8to16(pipename), 30 * 1000)) {
268 ws_warning("Control in pipe open timed out: %s",do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 269, __func__, "Control in pipe open timed out: %s", win32strerror
(GetLastError())); } } while (0)
269 win32strerror(GetLastError()))do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 269, __func__, "Control in pipe open timed out: %s", win32strerror
(GetLastError())); } } while (0)
;
270 break;
271 }
272 }
273#endif
274 return fd;
275}
276
277void *
278control_in_reader_thread(void *user_data) {
279 char *pipename = (char*)user_data;
280 ssize_t bytes_read;
281 char indicator;
282 char *buffer = g_malloc(SP_MAX_MSG_LEN(512 * 1000));
1
Memory is allocated
283 char *primary_msg;
284 GIOChannel *control_io;
285
286 int fd = open_control_in(pipename);
287 if (fd == -1) {
2
Taking true branch
288 ws_warning("Couldn't open control in pipe/FIFO %s", pipename)do { if (1) { ws_log_full("Extcap", LOG_LEVEL_WARNING, "extcap/extcap-base.c"
, 288, __func__, "Couldn't open control in pipe/FIFO %s", pipename
); } } while (0)
;
3
Potential leak of memory pointed to by 'buffer'
289 g_free(pipename)(__builtin_object_size ((pipename), 0) != ((size_t) - 1)) ? g_free_sized
(pipename, __builtin_object_size ((pipename), 0)) : (g_free)
(pipename)
;
290 return NULL((void*)0);
291 }
292 g_free(pipename)(__builtin_object_size ((pipename), 0) != ((size_t) - 1)) ? g_free_sized
(pipename, __builtin_object_size ((pipename), 0)) : (g_free)
(pipename)
;
293#ifdef _WIN32
294 control_io = g_io_channel_win32_new_fd(fd);
295#else
296 control_io = g_io_channel_unix_new(fd);
297#endif
298 g_io_channel_set_encoding(control_io, NULL((void*)0), NULL((void*)0));
299 g_io_channel_set_buffered(control_io, false0);
300 g_io_channel_set_close_on_unref(control_io, true1);
301
302 while ((bytes_read = sync_pipe_read_block(control_io, &indicator, SP_MAX_MSG_LEN(512 * 1000),
303 buffer, &primary_msg)) >= 4) {
304 // bytes_read includes the header and should always be at least 4 on
305 // synchronous reads
306
307 ws_debug("Got a %c message with length %zu", indicator, (size_t)bytes_read)do { if (1) { ws_log_full("Extcap", LOG_LEVEL_DEBUG, "extcap/extcap-base.c"
, 307, __func__, "Got a %c message with length %zu", indicator
, (size_t)bytes_read); } } while (0)
;
308 switch (indicator) {
309 // Add other callbacks?
310 case SP_QUIT'Q':
311 extcap_end_application = true1;
312 if (extcap_graceful_shutdown_cb) {
313 extcap_graceful_shutdown_cb();
314 } else {
315 // XXX - Are there extcaps that gracefully shutdown when
316 // extcap_end_application is set to true but do not register
317 // a graceful shutdown callback?
318 //_Exit(0);
319 }
320 break;
321 case SP_TOOLBAR_CTRL'T':
322 if (extcap_toolbar_control_cb && bytes_read >= 6) {
323 extcap_toolbar_control_cb(buffer[0], buffer[1], g_bytes_new(&buffer[2], bytes_read - 6));
324 }
325 default:
326 continue;
327 }
328 }
329
330 ws_debug("control in thread exiting")do { if (1) { ws_log_full("Extcap", LOG_LEVEL_DEBUG, "extcap/extcap-base.c"
, 330, __func__, "control in thread exiting"); } } while (0)
;
331 g_io_channel_unref(control_io);
332 g_free(buffer)(__builtin_object_size ((buffer), 0) != ((size_t) - 1)) ? g_free_sized
(buffer, __builtin_object_size ((buffer), 0)) : (g_free) (buffer
)
;
333 return NULL((void*)0);
334}
335
336uint8_t extcap_base_parse_options(extcap_parameters * extcap, int result, char * optargument)
337{
338 uint8_t ret = 1;
339 enum ws_log_level level;
340
341 switch (result) {
342 case EXTCAP_OPT_LOG_LEVEL:
343 level = ws_log_set_level_str(optargument);
344 if (level == LOG_LEVEL_NONE) {
345 /* Invalid log level string. */
346 ret = 0;
347 }
348 extcap->debug = level;
349 break;
350 case EXTCAP_OPT_LOG_FILE:
351 extcap_init_log_file(optargument);
352 break;
353 case EXTCAP_OPT_LIST_INTERFACES:
354 extcap->do_list_interfaces = 1;
355 break;
356 case EXTCAP_OPT_CLEANUP_POSTKILL:
357 extcap->do_cleanup_postkill = 1;
358 break;
359 case EXTCAP_OPT_VERSION:
360 extcap->ws_version = g_strdup(optargument)g_strdup_inline (optargument);
361 extcap->do_version = 1;
362 break;
363 case EXTCAP_OPT_LIST_DLTS:
364 extcap->do_list_dlts = 1;
365 break;
366 case EXTCAP_OPT_INTERFACE:
367 extcap->interface = g_strdup(optargument)g_strdup_inline (optargument);
368 break;
369 case EXTCAP_OPT_CONFIG:
370 extcap->show_config = 1;
371 break;
372 case EXTCAP_OPT_CONFIG_OPTION_NAME:
373 extcap->show_config_option = 1;
374 extcap->config_option_name = g_strdup(optargument)g_strdup_inline (optargument);
375 break;
376 case EXTCAP_OPT_CONFIG_OPTION_VALUE:
377 extcap->show_config_option = 1;
378 extcap->config_option_value = g_strdup(optargument)g_strdup_inline (optargument);
379 break;
380 case EXTCAP_OPT_CAPTURE:
381 extcap->capture = 1;
382 break;
383 case EXTCAP_OPT_CAPTURE_FILTER:
384 extcap->capture_filter = g_strdup(optargument)g_strdup_inline (optargument);
385 break;
386 case EXTCAP_OPT_FIFO:
387 extcap->fifo = g_strdup(optargument)g_strdup_inline (optargument);
388 break;
389 case EXTCAP_OPT_CONTROL_OUT:
390 extcap->control_out_fd = ws_openopen(optargument, O_WRONLY01, 0000 /* no creation so don't matter */);
391 if (extcap->control_out_fd != -1) {
392 extcap->control_out = g_strdup(optargument)g_strdup_inline (optargument);
393 }
394 break;
395 case EXTCAP_OPT_CONTROL_IN:
396 if (extcap->control_in_tid == NULL((void*)0)) {
397 extcap->control_in_tid = g_thread_new("Control in reader", control_in_reader_thread, g_strdup(optargument)g_strdup_inline (optargument));
398 }
399 break;
400 default:
401 ret = 0;
402 }
403
404 return ret;
405}
406
407static void extcap_iface_print(void * data, void * userdata _U___attribute__((unused)))
408{
409 extcap_interface * iface = (extcap_interface *)data;
410
411 printf("interface {value=%s}", iface->interface);
412 if (iface->description != NULL((void*)0))
413 printf ("{display=%s}\n", iface->description);
414 else
415 printf ("\n");
416}
417
418static int extcap_iface_compare(const void * a, const void * b)
419{
420 const extcap_interface * iface_a = (const extcap_interface *)a;
421
422 return (g_strcmp0(iface_a->interface, (const char *) b));
423}
424
425static void extcap_print_version(extcap_parameters * extcap)
426{
427 printf("extcap {version=%s}", extcap->version != NULL((void*)0) ? extcap->version : "unknown");
428 if (extcap->helppage != NULL((void*)0))
429 printf("{help=%s}", extcap->helppage);
430 printf("\n");
431}
432
433static int extcap_iface_listall(extcap_parameters * extcap, uint8_t list_ifs)
434{
435 if (list_ifs) {
436 if (g_list_length(extcap->interfaces) > 0) {
437 extcap_print_version(extcap);
438 g_list_foreach(extcap->interfaces, extcap_iface_print, extcap);
439 }
440 } else if (extcap->do_version) {
441 extcap_print_version(extcap);
442 } else {
443 GList * element = NULL((void*)0);
444 extcap_interface * iface = NULL((void*)0);
445 if ((element = g_list_find_custom(extcap->interfaces, extcap->interface, extcap_iface_compare)) == NULL((void*)0))
446 return 0;
447
448 iface = (extcap_interface *) element->data;
449 printf("dlt {number=%u}{name=%s}", iface->dlt, iface->dltname != NULL((void*)0) ? iface->dltname : iface->interface);
450 if (iface->description != NULL((void*)0))
451 printf ("{display=%s}\n", iface->dltdescription);
452 else
453 printf ("\n");
454 }
455
456 return 1;
457}
458
459uint8_t extcap_base_handle_interface(extcap_parameters * extcap)
460{
461 /* A fifo must be provided for capture */
462 if (extcap->capture && (extcap->fifo == NULL((void*)0) || strlen(extcap->fifo) == 0)) {
463 extcap->capture = 0;
464 ws_error("Extcap Error: No FIFO pipe provided")ws_log_fatal_full("Extcap", LOG_LEVEL_ERROR, "extcap/extcap-base.c"
, 464, __func__, "Extcap Error: No FIFO pipe provided")
;
465 return 0;
466 }
467
468 if (extcap->do_cleanup_postkill) {
469 if (extcap->cleanup_postkill_cb != NULL((void*)0))
470 extcap->cleanup_postkill_cb();
471 return 1;
472 } else if (extcap->do_list_interfaces) {
473 return extcap_iface_listall(extcap, 1);
474 } else if (extcap->do_version || extcap->do_list_dlts) {
475 return extcap_iface_listall(extcap, 0);
476 }
477
478 return 0;
479}
480
481static void extcap_iface_free(void * data)
482{
483 extcap_interface * iface = (extcap_interface *)data;
484 g_free(iface->interface)(__builtin_object_size ((iface->interface), 0) != ((size_t
) - 1)) ? g_free_sized (iface->interface, __builtin_object_size
((iface->interface), 0)) : (g_free) (iface->interface)
;
485 g_free(iface->description)(__builtin_object_size ((iface->description), 0) != ((size_t
) - 1)) ? g_free_sized (iface->description, __builtin_object_size
((iface->description), 0)) : (g_free) (iface->description
)
;
486 g_free(iface->dltname)(__builtin_object_size ((iface->dltname), 0) != ((size_t) -
1)) ? g_free_sized (iface->dltname, __builtin_object_size
((iface->dltname), 0)) : (g_free) (iface->dltname)
;
487 g_free(iface->dltdescription)(__builtin_object_size ((iface->dltdescription), 0) != ((size_t
) - 1)) ? g_free_sized (iface->dltdescription, __builtin_object_size
((iface->dltdescription), 0)) : (g_free) (iface->dltdescription
)
;
488 g_free(iface)(__builtin_object_size ((iface), 0) != ((size_t) - 1)) ? g_free_sized
(iface, __builtin_object_size ((iface), 0)) : (g_free) (iface
)
;
489}
490
491static void extcap_help_option_free(void * option)
492{
493 extcap_option_t* o = (extcap_option_t*)option;
494 g_free(o->optname)(__builtin_object_size ((o->optname), 0) != ((size_t) - 1)
) ? g_free_sized (o->optname, __builtin_object_size ((o->
optname), 0)) : (g_free) (o->optname)
;
495 g_free(o->optdesc)(__builtin_object_size ((o->optdesc), 0) != ((size_t) - 1)
) ? g_free_sized (o->optdesc, __builtin_object_size ((o->
optdesc), 0)) : (g_free) (o->optdesc)
;
496 g_free(o)(__builtin_object_size ((o), 0) != ((size_t) - 1)) ? g_free_sized
(o, __builtin_object_size ((o), 0)) : (g_free) (o)
;
497}
498
499void extcap_base_cleanup(extcap_parameters ** extcap)
500{
501 g_list_free_full((*extcap)->interfaces, extcap_iface_free);
502 g_free((*extcap)->exename)(__builtin_object_size (((*extcap)->exename), 0) != ((size_t
) - 1)) ? g_free_sized ((*extcap)->exename, __builtin_object_size
(((*extcap)->exename), 0)) : (g_free) ((*extcap)->exename
)
;
503 g_free((*extcap)->fifo)(__builtin_object_size (((*extcap)->fifo), 0) != ((size_t)
- 1)) ? g_free_sized ((*extcap)->fifo, __builtin_object_size
(((*extcap)->fifo), 0)) : (g_free) ((*extcap)->fifo)
;
504 g_free((*extcap)->control_in)(__builtin_object_size (((*extcap)->control_in), 0) != ((size_t
) - 1)) ? g_free_sized ((*extcap)->control_in, __builtin_object_size
(((*extcap)->control_in), 0)) : (g_free) ((*extcap)->control_in
)
;
505 g_free((*extcap)->control_out)(__builtin_object_size (((*extcap)->control_out), 0) != ((
size_t) - 1)) ? g_free_sized ((*extcap)->control_out, __builtin_object_size
(((*extcap)->control_out), 0)) : (g_free) ((*extcap)->
control_out)
;
506 g_free((*extcap)->interface)(__builtin_object_size (((*extcap)->interface), 0) != ((size_t
) - 1)) ? g_free_sized ((*extcap)->interface, __builtin_object_size
(((*extcap)->interface), 0)) : (g_free) ((*extcap)->interface
)
;
507 g_free((*extcap)->capture_filter)(__builtin_object_size (((*extcap)->capture_filter), 0) !=
((size_t) - 1)) ? g_free_sized ((*extcap)->capture_filter
, __builtin_object_size (((*extcap)->capture_filter), 0)) :
(g_free) ((*extcap)->capture_filter)
;
508 g_free((*extcap)->version)(__builtin_object_size (((*extcap)->version), 0) != ((size_t
) - 1)) ? g_free_sized ((*extcap)->version, __builtin_object_size
(((*extcap)->version), 0)) : (g_free) ((*extcap)->version
)
;
509 g_free((*extcap)->compiled_with)(__builtin_object_size (((*extcap)->compiled_with), 0) != (
(size_t) - 1)) ? g_free_sized ((*extcap)->compiled_with, __builtin_object_size
(((*extcap)->compiled_with), 0)) : (g_free) ((*extcap)->
compiled_with)
;
510 g_free((*extcap)->running_with)(__builtin_object_size (((*extcap)->running_with), 0) != (
(size_t) - 1)) ? g_free_sized ((*extcap)->running_with, __builtin_object_size
(((*extcap)->running_with), 0)) : (g_free) ((*extcap)->
running_with)
;
511 g_free((*extcap)->helppage)(__builtin_object_size (((*extcap)->helppage), 0) != ((size_t
) - 1)) ? g_free_sized ((*extcap)->helppage, __builtin_object_size
(((*extcap)->helppage), 0)) : (g_free) ((*extcap)->helppage
)
;
512 g_free((*extcap)->help_header)(__builtin_object_size (((*extcap)->help_header), 0) != ((
size_t) - 1)) ? g_free_sized ((*extcap)->help_header, __builtin_object_size
(((*extcap)->help_header), 0)) : (g_free) ((*extcap)->
help_header)
;
513 g_free((*extcap)->ws_version)(__builtin_object_size (((*extcap)->ws_version), 0) != ((size_t
) - 1)) ? g_free_sized ((*extcap)->ws_version, __builtin_object_size
(((*extcap)->ws_version), 0)) : (g_free) ((*extcap)->ws_version
)
;
514 g_list_free_full((*extcap)->help_options, extcap_help_option_free);
515 g_free(*extcap)(__builtin_object_size ((*extcap), 0) != ((size_t) - 1)) ? g_free_sized
(*extcap, __builtin_object_size ((*extcap), 0)) : (g_free) (
*extcap)
;
516 *extcap = NULL((void*)0);
517}
518
519static void extcap_print_option(void * option, void * user_data _U___attribute__((unused)))
520{
521 extcap_option_t* o = (extcap_option_t*)option;
522 printf("\t%s: %s\n", o->optname, o->optdesc);
523}
524
525void extcap_version_print(extcap_parameters * extcap)
526{
527 printf("%s version %s\n", extcap->exename, extcap->version);
528 if (extcap->compiled_with != NULL((void*)0))
529 printf("Compiled with %s\n", extcap->compiled_with);
530 if (extcap->running_with != NULL((void*)0))
531 printf("Running with %s\n", extcap->running_with);
532}
533
534void extcap_help_print(extcap_parameters * extcap)
535{
536 printf("\nWireshark - %s v%s\n\n", extcap->exename, extcap->version);
537 printf("Usage:\n");
538 printf("%s", extcap->help_header);
539 printf("\n");
540 printf("Options:\n");
541 g_list_foreach(extcap->help_options, extcap_print_option, NULL((void*)0));
542 printf("\n");
543}
544
545void extcap_help_add_option(extcap_parameters * extcap, const char * help_option_name, const char * help_option_desc)
546{
547 extcap_option_t* o = g_new0(extcap_option_t, 1)((extcap_option_t *) g_malloc0_n ((1), sizeof (extcap_option_t
)))
;
548 o->optname = g_strdup(help_option_name)g_strdup_inline (help_option_name);
549 o->optdesc = g_strdup(help_option_desc)g_strdup_inline (help_option_desc);
550
551 extcap->help_options = g_list_append(extcap->help_options, o);
552}
553
554void extcap_help_add_header(extcap_parameters * extcap, char * help_header)
555{
556 extcap->help_header = g_strdup(help_header)g_strdup_inline (help_header);
557 extcap_help_add_option(extcap, "--extcap-interfaces", "list the extcap Interfaces");
558 extcap_help_add_option(extcap, "--extcap-dlts", "list the DLTs");
559 extcap_help_add_option(extcap, "--extcap-interface <iface>", "specify the extcap interface");
560 extcap_help_add_option(extcap, "--extcap-config", "list the additional configuration for an interface");
561 extcap_help_add_option(extcap, "--capture", "run the capture");
562 extcap_help_add_option(extcap, "--extcap-capture-filter <filter>", "the capture filter");
563 extcap_help_add_option(extcap, "--fifo <file>", "dump data to file or fifo");
564 extcap_help_add_option(extcap, "--extcap-control-in <file>", "FIFO used to receive control messages");
565 extcap_help_add_option(extcap, "--extcap-control-out <file>", "FIFO used to send control messages");
566 extcap_help_add_option(extcap, "--extcap-version", "print tool version");
567 extcap_help_add_option(extcap, "--log-level", "Set the log level");
568 extcap_help_add_option(extcap, "--log-file", "Set a log file to log messages in addition to the console");
569 if (extcap->cleanup_postkill_cb != NULL((void*)0))
570 {
571 extcap_help_add_option(extcap, "--extcap-cleanup-postkill", "Perform a post-mortem cleanup if the process was killed.");
572 }
573}
574
575static void extcap_init_log_file(const char* filename)
576{
577 if (!filename || strlen(filename) == 0)
578 ws_error("Missing log file name")ws_log_fatal_full("Extcap", LOG_LEVEL_ERROR, "extcap/extcap-base.c"
, 578, __func__, "Missing log file name")
;
579 custom_log = fopen(filename, "w");
580 if (!custom_log)
581 ws_error("Can't open custom log file: %s (%s)", filename, strerror(errno))ws_log_fatal_full("Extcap", LOG_LEVEL_ERROR, "extcap/extcap-base.c"
, 581, __func__, "Can't open custom log file: %s (%s)", filename
, strerror((*__errno_location ())))
;
582 ws_log_add_custom_file(custom_log);
583}
584
585void extcap_config_debug(unsigned* count)
586{
587 printf("arg {number=%u}{call=--log-level}{display=Set the log level}"
588 "{type=selector}{tooltip=Set the log level}{required=false}"
589 "{group=Debug}\n", *count);
590 printf("value {arg=%u}{value=message}{display=Message}{default=true}\n", *count);
591 printf("value {arg=%u}{value=info}{display=Info}\n", *count);
592 printf("value {arg=%u}{value=debug}{display=Debug}\n", *count);
593 printf("value {arg=%u}{value=noisy}{display=Noisy}\n", *count);
594 (*count)++;
595 printf("arg {number=%u}{call=--log-file}{display=Use a file for logging}"
596 "{type=fileselect}{tooltip=Set a file where log messages are written}{required=false}"
597 "{group=Debug}\n", (*count)++);
598}
599
600void extcap_cmdline_debug(char** ar, const unsigned n)
601{
602 GString* cmdline = g_string_new("cmdline: ");
603 unsigned i;
604 for (i = 0; i < n; i++)
605 g_string_append_printf(cmdline, "%s ", ar[i]);
606 ws_debug("%s", cmdline->str)do { if (1) { ws_log_full("Extcap", LOG_LEVEL_DEBUG, "extcap/extcap-base.c"
, 606, __func__, "%s", cmdline->str); } } while (0)
;
607 g_string_free(cmdline, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(cmdline), ((!(0)))) : g_string_free_and_steal (cmdline)) : (
g_string_free) ((cmdline), ((!(0)))))
;
608}
609
610/*
611 * Report errors and warnings through ws_warning().
612 *
613 * Unfortunately, ws_warning() may be a macro, so we do it by calling
614 * ws_logv() with the appropriate arguments.
615 */
616void
617extcap_log_cmdarg_err(const char *msg_format, va_list ap)
618{
619 ws_logv(LOG_DOMAIN_CAPCHILD"Capchild", LOG_LEVEL_WARNING, msg_format, ap);
620}
621
622/*
623 * Editor modelines - https://www.wireshark.org/tools/modelines.html
624 *
625 * Local variables:
626 * c-basic-offset: 4
627 * tab-width: 8
628 * indent-tabs-mode: nil
629 * End:
630 *
631 * vi: set shiftwidth=4 tabstop=8 expandtab:
632 * :indentSize=4:tabSize=8:noTabs=true:
633 */