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
15 #include "extcap-base.h"
16
17 #include <stdlib.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <wsutil/wslog.h>
22
23 #include <wsutil/ws_assert.h>
24
25 #include "ws_attributes.h"
26
27 enum extcap_options {
28 EXTCAP_BASE_OPTIONS_ENUM
29 };
30
31 typedef struct _extcap_interface
32 {
33 char * interface;
34 char * description;
35
36 uint16_t dlt;
37 char * dltname;
38 char * dltdescription;
39 } extcap_interface;
40
41 typedef struct _extcap_option {
42 char * optname;
43 char * optdesc;
44 } extcap_option_t;
45
46 static FILE *custom_log = NULL;
47
extcap_base_register_interface(extcap_parameters * extcap,const char * interface,const char * ifdescription,uint16_t dlt,const char * dltdescription)48 void extcap_base_register_interface(extcap_parameters * extcap, const char * interface, const char * ifdescription, uint16_t dlt, const char * dltdescription )
49 {
50 extcap_base_register_interface_ext(extcap, interface, ifdescription, dlt, NULL, dltdescription );
51 }
52
extcap_base_register_interface_ext(extcap_parameters * extcap,const char * interface,const char * ifdescription,uint16_t dlt,const char * dltname,const char * dltdescription)53 void extcap_base_register_interface_ext(extcap_parameters * extcap,
54 const char * interface, const char * ifdescription,
55 uint16_t dlt, const char * dltname, const char * dltdescription )
56 {
57 extcap_interface * iface;
58
59 if (interface == NULL)
60 return;
61
62 iface = g_new0(extcap_interface, 1);
63
64 iface->interface = g_strdup(interface);
65 iface->description = g_strdup(ifdescription);
66 iface->dlt = dlt;
67 iface->dltname = g_strdup(dltname);
68 iface->dltdescription = g_strdup(dltdescription);
69
70 extcap->interfaces = g_list_append(extcap->interfaces, (gpointer) iface);
71 }
72
extcap_base_set_util_info(extcap_parameters * extcap,const char * exename,const char * major,const char * minor,const char * release,const char * helppage)73 void extcap_base_set_util_info(extcap_parameters * extcap, const char * exename, const char * major,
74 const char * minor, const char * release, const char * helppage)
75 {
76 extcap->exename = g_path_get_basename(exename);
77
78 ws_assert(major);
79 if (!minor)
80 ws_assert(!release);
81
82 extcap->version = g_strdup_printf("%s%s%s%s%s",
83 major,
84 minor ? "." : "",
85 minor ? minor : "",
86 release ? "." : "",
87 release ? release : "");
88 extcap->helppage = g_strdup(helppage);
89 }
90
extcap_base_set_compiled_with(extcap_parameters * extcap,const char * fmt,...)91 void extcap_base_set_compiled_with(extcap_parameters * extcap, const char *fmt, ...)
92 {
93 va_list ap;
94
95 va_start(ap, fmt);
96 extcap->compiled_with = g_strdup_vprintf(fmt, ap);
97 va_end(ap);
98 }
99
extcap_base_set_running_with(extcap_parameters * extcap,const char * fmt,...)100 void extcap_base_set_running_with(extcap_parameters * extcap, const char *fmt, ...)
101 {
102 va_list ap;
103
104 va_start(ap, fmt);
105 extcap->running_with = g_strdup_vprintf(fmt, ap);
106 va_end(ap);
107 }
108
extcap_custom_log(const char * domain,enum ws_log_level level,ws_log_time_t timestamp,const char * file,int line,const char * func,const char * user_format,va_list user_ap,void * user_data _U_)109 static void extcap_custom_log(const char *domain, enum ws_log_level level,
110 ws_log_time_t timestamp,
111 const char *file, int line, const char *func,
112 const char *user_format, va_list user_ap,
113 void *user_data _U_)
114 {
115 if (level <= LOG_LEVEL_DEBUG) {
116 if (!custom_log)
117 return;
118 ws_log_file_writer(custom_log, domain, level, timestamp, file, line, func, user_format, user_ap);
119 } else {
120 ws_log_console_writer(domain, level, timestamp, file, line, func, user_format, user_ap);
121 }
122 }
123
extcap_log_init(const char * progname)124 void extcap_log_init(const char *progname)
125 {
126 ws_log_init_with_writer(progname, extcap_custom_log, NULL);
127 }
128
extcap_base_parse_options(extcap_parameters * extcap,int result,char * optargument)129 uint8_t extcap_base_parse_options(extcap_parameters * extcap, int result, char * optargument)
130 {
131 uint8_t ret = 1;
132
133 switch (result) {
134 case EXTCAP_OPT_DEBUG:
135 extcap->debug = TRUE;
136 ws_log_set_level(LOG_LEVEL_DEBUG);
137 break;
138 case EXTCAP_OPT_DEBUG_FILE:
139 extcap_init_custom_log(optargument);
140 break;
141 case EXTCAP_OPT_LIST_INTERFACES:
142 extcap->do_list_interfaces = 1;
143 break;
144 case EXTCAP_OPT_VERSION:
145 extcap->ws_version = g_strdup(optargument);
146 extcap->do_version = 1;
147 break;
148 case EXTCAP_OPT_LIST_DLTS:
149 extcap->do_list_dlts = 1;
150 break;
151 case EXTCAP_OPT_INTERFACE:
152 extcap->interface = g_strdup(optargument);
153 break;
154 case EXTCAP_OPT_CONFIG:
155 extcap->show_config = 1;
156 break;
157 case EXTCAP_OPT_CAPTURE:
158 extcap->capture = 1;
159 break;
160 case EXTCAP_OPT_CAPTURE_FILTER:
161 extcap->capture_filter = g_strdup(optargument);
162 break;
163 case EXTCAP_OPT_FIFO:
164 extcap->fifo = g_strdup(optargument);
165 break;
166 default:
167 ret = 0;
168 }
169
170 return ret;
171 }
172
extcap_iface_print(gpointer data,gpointer userdata _U_)173 static void extcap_iface_print(gpointer data, gpointer userdata _U_)
174 {
175 extcap_interface * iface = (extcap_interface *)data;
176
177 printf("interface {value=%s}", iface->interface);
178 if (iface->description != NULL)
179 printf ("{display=%s}\n", iface->description);
180 else
181 printf ("\n");
182 }
183
extcap_iface_compare(gconstpointer a,gconstpointer b)184 static gint extcap_iface_compare(gconstpointer a, gconstpointer b)
185 {
186 const extcap_interface * iface_a = (const extcap_interface *)a;
187
188 return (g_strcmp0(iface_a->interface, (const char *) b));
189 }
190
extcap_print_version(extcap_parameters * extcap)191 static void extcap_print_version(extcap_parameters * extcap)
192 {
193 printf("extcap {version=%s}", extcap->version != NULL ? extcap->version : "unknown");
194 if (extcap->helppage != NULL)
195 printf("{help=%s}", extcap->helppage);
196 printf("\n");
197 }
198
extcap_iface_listall(extcap_parameters * extcap,uint8_t list_ifs)199 static gint extcap_iface_listall(extcap_parameters * extcap, uint8_t list_ifs)
200 {
201 if (list_ifs) {
202 if (g_list_length(extcap->interfaces) > 0) {
203 extcap_print_version(extcap);
204 g_list_foreach(extcap->interfaces, extcap_iface_print, extcap);
205 }
206 } else if (extcap->do_version) {
207 extcap_print_version(extcap);
208 } else {
209 GList * element = NULL;
210 extcap_interface * iface = NULL;
211 if ((element = g_list_find_custom(extcap->interfaces, extcap->interface, extcap_iface_compare)) == NULL)
212 return 0;
213
214 iface = (extcap_interface *) element->data;
215 printf("dlt {number=%u}{name=%s}", iface->dlt, iface->dltname != NULL ? iface->dltname : iface->interface);
216 if (iface->description != NULL)
217 printf ("{display=%s}\n", iface->dltdescription);
218 else
219 printf ("\n");
220 }
221
222 return 1;
223 }
224
extcap_base_handle_interface(extcap_parameters * extcap)225 uint8_t extcap_base_handle_interface(extcap_parameters * extcap)
226 {
227 /* A fifo must be provided for capture */
228 if (extcap->capture && (extcap->fifo == NULL || strlen(extcap->fifo) <= 0)) {
229 extcap->capture = 0;
230 ws_error("Extcap Error: No FIFO pipe provided");
231 return 0;
232 }
233
234 if (extcap->do_list_interfaces) {
235 return extcap_iface_listall(extcap, 1);
236 } else if (extcap->do_version || extcap->do_list_dlts) {
237 return extcap_iface_listall(extcap, 0);
238 }
239
240 return 0;
241 }
242
extcap_iface_free(gpointer data)243 static void extcap_iface_free(gpointer data)
244 {
245 extcap_interface * iface = (extcap_interface *)data;
246 g_free(iface->interface);
247 g_free(iface->description);
248 g_free(iface->dltname);
249 g_free(iface->dltdescription);
250 g_free(iface);
251 }
252
extcap_help_option_free(gpointer option)253 static void extcap_help_option_free(gpointer option)
254 {
255 extcap_option_t* o = (extcap_option_t*)option;
256 g_free(o->optname);
257 g_free(o->optdesc);
258 g_free(o);
259 }
260
extcap_base_cleanup(extcap_parameters ** extcap)261 void extcap_base_cleanup(extcap_parameters ** extcap)
262 {
263 g_list_free_full((*extcap)->interfaces, extcap_iface_free);
264 g_free((*extcap)->exename);
265 g_free((*extcap)->fifo);
266 g_free((*extcap)->interface);
267 g_free((*extcap)->version);
268 g_free((*extcap)->compiled_with);
269 g_free((*extcap)->running_with);
270 g_free((*extcap)->helppage);
271 g_free((*extcap)->help_header);
272 g_free((*extcap)->ws_version);
273 g_list_free_full((*extcap)->help_options, extcap_help_option_free);
274 g_free(*extcap);
275 *extcap = NULL;
276 }
277
extcap_print_option(gpointer option,gpointer user_data _U_)278 static void extcap_print_option(gpointer option, gpointer user_data _U_)
279 {
280 extcap_option_t* o = (extcap_option_t*)option;
281 printf("\t%s: %s\n", o->optname, o->optdesc);
282 }
283
extcap_version_print(extcap_parameters * extcap)284 void extcap_version_print(extcap_parameters * extcap)
285 {
286 printf("%s version %s\n", extcap->exename, extcap->version);
287 if (extcap->compiled_with != NULL)
288 printf("Compiled with %s\n", extcap->compiled_with);
289 if (extcap->running_with != NULL)
290 printf("Running with %s\n", extcap->running_with);
291 }
292
extcap_help_print(extcap_parameters * extcap)293 void extcap_help_print(extcap_parameters * extcap)
294 {
295 printf("\nWireshark - %s v%s\n\n", extcap->exename, extcap->version);
296 printf("Usage:\n");
297 printf("%s", extcap->help_header);
298 printf("\n");
299 printf("Options:\n");
300 g_list_foreach(extcap->help_options, extcap_print_option, NULL);
301 printf("\n");
302 }
303
extcap_help_add_option(extcap_parameters * extcap,const char * help_option_name,const char * help_option_desc)304 void extcap_help_add_option(extcap_parameters * extcap, const char * help_option_name, const char * help_option_desc)
305 {
306 extcap_option_t* o = g_new0(extcap_option_t, 1);
307 o->optname = g_strdup(help_option_name);
308 o->optdesc = g_strdup(help_option_desc);
309
310 extcap->help_options = g_list_append(extcap->help_options, o);
311 }
312
extcap_help_add_header(extcap_parameters * extcap,char * help_header)313 void extcap_help_add_header(extcap_parameters * extcap, char * help_header)
314 {
315 extcap->help_header = g_strdup(help_header);
316 extcap_help_add_option(extcap, "--extcap-interfaces", "list the extcap Interfaces");
317 extcap_help_add_option(extcap, "--extcap-dlts", "list the DLTs");
318 extcap_help_add_option(extcap, "--extcap-interface <iface>", "specify the extcap interface");
319 extcap_help_add_option(extcap, "--extcap-config", "list the additional configuration for an interface");
320 extcap_help_add_option(extcap, "--capture", "run the capture");
321 extcap_help_add_option(extcap, "--extcap-capture-filter <filter>", "the capture filter");
322 extcap_help_add_option(extcap, "--fifo <file>", "dump data to file or fifo");
323 extcap_help_add_option(extcap, "--extcap-version", "print tool version");
324 extcap_help_add_option(extcap, "--debug", "print additional messages");
325 extcap_help_add_option(extcap, "--debug-file", "print debug messages to file");
326 }
327
extcap_init_custom_log(const char * filename)328 void extcap_init_custom_log(const char* filename)
329 {
330 if (!filename || strlen(filename) == 0)
331 return;
332 custom_log = fopen(filename, "w");
333 if (!custom_log)
334 ws_error("Can't open custom log file: %s (%s)", filename, strerror(errno));
335 }
336
extcap_config_debug(unsigned * count)337 void extcap_config_debug(unsigned* count)
338 {
339 printf("arg {number=%u}{call=--debug}{display=Run in debug mode}"
340 "{type=boolflag}{default=false}{tooltip=Print debug messages}{required=false}"
341 "{group=Debug}\n", (*count)++);
342 printf("arg {number=%u}{call=--debug-file}{display=Use a file for debug}"
343 "{type=string}{tooltip=Set a file where the debug messages are written}{required=false}"
344 "{group=Debug}\n", (*count)++);
345 }
346
extcap_cmdline_debug(char ** ar,const unsigned n)347 void extcap_cmdline_debug(char** ar, const unsigned n)
348 {
349 GString* cmdline = g_string_new("cmdline: ");
350 unsigned i;
351 for (i = 0; i < n; i++)
352 g_string_append_printf(cmdline, "%s ", ar[i]);
353 ws_debug("%s", cmdline->str);
354 g_string_free(cmdline, TRUE);
355 }
356
357 /*
358 * Editor modelines - https://www.wireshark.org/tools/modelines.html
359 *
360 * Local variables:
361 * c-basic-offset: 4
362 * tab-width: 8
363 * indent-tabs-mode: nil
364 * End:
365 *
366 * vi: set shiftwidth=4 tabstop=8 expandtab:
367 * :indentSize=4:tabSize=8:noTabs=true:
368 */
369