| File: | builds/wireshark/wireshark/extcap/extcap-base.c |
| Warning: | line 288, column 9 Potential leak of memory pointed to by 'buffer' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | ||||
| 36 | enum 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 | ||||
| 40 | typedef 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 | ||||
| 50 | typedef struct _extcap_option { | |||
| 51 | char * optname; | |||
| 52 | char * optdesc; | |||
| 53 | } extcap_option_t; | |||
| 54 | ||||
| 55 | static FILE *custom_log; | |||
| 56 | ||||
| 57 | /* used to inform to extcap application that end of application is requested */ | |||
| 58 | bool_Bool extcap_end_application; | |||
| 59 | /* graceful shutdown callback, can be null */ | |||
| 60 | static void (*extcap_graceful_shutdown_cb)(void); | |||
| 61 | /* toolbar control callback, can be null */ | |||
| 62 | static extcap_toolbar_control_cb_t extcap_toolbar_control_cb; | |||
| 63 | ||||
| 64 | static void extcap_init_log_file(const char *filename); | |||
| 65 | ||||
| 66 | /* Called from signals */ | |||
| 67 | #ifdef _WIN32 | |||
| 68 | static BOOL WINAPI | |||
| 69 | extcap_exit_from_loop(DWORD dwCtrlType _U___attribute__((unused))) | |||
| 70 | #else | |||
| 71 | static 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 | ||||
| 84 | void 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 | ||||
| 89 | void 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 | ||||
| 109 | bool_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 | ||||
| 146 | bool_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 | ||||
| 152 | bool_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 | ||||
| 158 | void 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 | ||||
| 176 | void 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 | ||||
| 185 | void 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 | ||||
| 194 | static void | |||
| 195 | extcap_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 | ||||
| 230 | void 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 | ||||
| 237 | static int | |||
| 238 | open_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 | ||||
| 277 | void * | |||
| 278 | control_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)); | |||
| ||||
| 283 | char *primary_msg; | |||
| 284 | GIOChannel *control_io; | |||
| 285 | ||||
| 286 | int fd = open_control_in(pipename); | |||
| 287 | if (fd == -1) { | |||
| 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); | |||
| ||||
| 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 | ||||
| 336 | uint8_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 | ||||
| 407 | static 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 | ||||
| 418 | static 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 | ||||
| 425 | static 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 | ||||
| 433 | static 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 | ||||
| 459 | uint8_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 | ||||
| 481 | static 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 | ||||
| 491 | static 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 | ||||
| 499 | void 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 | ||||
| 519 | static 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 | ||||
| 525 | void 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 | ||||
| 534 | void 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 | ||||
| 545 | void 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 | ||||
| 554 | void 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 | ||||
| 575 | static 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 | ||||
| 585 | void 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 | ||||
| 600 | void 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 | */ | |||
| 616 | void | |||
| 617 | extcap_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 | */ |