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