3 * Routines for extcap external capture
4 * Copyright 2013, Mike Ryan <mikeryan@lacklustre.net>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 #define WS_LOG_DOMAIN LOG_DOMAIN_EXTCAP
20 #include "ui/iface_toolbar.h"
21 #include "wsutil/strtoi.h"
24 #include "extcap_parser.h"
25 #include "ws_attributes.h"
27 void extcap_printf_complex(extcap_complex
*comp
) {
28 char *ret
= extcap_get_complex_as_string(comp
);
33 char *extcap_get_complex_as_string(extcap_complex
*comp
) {
34 return (comp
? g_strdup(comp
->_val
) : NULL
);
37 extcap_complex
*extcap_parse_complex(extcap_arg_type complex_type
,
40 extcap_complex
*rc
= g_new0(extcap_complex
, 1);
42 rc
->_val
= g_strdup(data
);
43 rc
->complex_type
= complex_type
;
48 bool extcap_compare_is_default(extcap_arg
*element
, extcap_complex
*test
) {
49 if (element
== NULL
|| element
->default_complex
== NULL
|| test
== NULL
)
52 if (g_strcmp0(element
->default_complex
->_val
, test
->_val
) == 0)
58 void extcap_free_complex(extcap_complex
*comp
) {
64 int extcap_complex_get_int(extcap_complex
*comp
) {
65 if (comp
== NULL
|| comp
->_val
== NULL
|| comp
->complex_type
!= EXTCAP_ARG_INTEGER
)
68 return (int) g_ascii_strtoll(comp
->_val
, NULL
, 10);
71 unsigned extcap_complex_get_uint(extcap_complex
*comp
) {
72 if (comp
== NULL
|| comp
->_val
== NULL
|| comp
->complex_type
!= EXTCAP_ARG_UNSIGNED
)
74 return (unsigned) g_ascii_strtoull(comp
->_val
, NULL
, 10);
77 int64_t extcap_complex_get_long(extcap_complex
*comp
) {
78 if (comp
== NULL
|| comp
->_val
== NULL
|| comp
->complex_type
!= EXTCAP_ARG_LONG
)
80 return g_ascii_strtoll(comp
->_val
, NULL
, 10);
83 double extcap_complex_get_double(extcap_complex
*comp
) {
84 if (comp
== NULL
|| comp
->_val
== NULL
|| comp
->complex_type
!= EXTCAP_ARG_DOUBLE
)
86 return g_strtod(comp
->_val
, NULL
);
89 static bool matches_regex(const char *pattern
, const char *subject
) {
90 if (!g_utf8_validate(subject
, -1, NULL
))
92 return g_regex_match_simple(pattern
, subject
, (GRegexCompileFlags
) (G_REGEX_CASELESS
), (GRegexMatchFlags
)0);
95 bool extcap_complex_get_bool(extcap_complex
*comp
) {
96 if (comp
== NULL
|| comp
->_val
== NULL
)
99 if (comp
->complex_type
!= EXTCAP_ARG_BOOLEAN
&& comp
->complex_type
!= EXTCAP_ARG_BOOLFLAG
)
102 return matches_regex(EXTCAP_BOOLEAN_REGEX
, comp
->_val
);
105 char *extcap_complex_get_string(extcap_complex
*comp
) {
106 /* Not checking for argument type, to use this method as fallback if only strings are needed */
107 return comp
!= NULL
? comp
->_val
: NULL
;
110 static extcap_token_sentence
*extcap_tokenize_sentence(const char *s
) {
111 GRegex
*regex
= NULL
;
112 GMatchInfo
*match_info
= NULL
;
113 GError
*error
= NULL
;
114 char *param_value
= NULL
;
115 unsigned param_type
= EXTCAP_PARAM_UNKNOWN
;
117 if (!g_utf8_validate(s
, -1, NULL
))
120 extcap_token_sentence
*rs
= g_new0(extcap_token_sentence
, 1);
124 /* Regex for catching just the allowed values for sentences */
125 if ((regex
= g_regex_new("^[\\t| ]*(arg|value|interface|extcap|dlt|control)(?=[\\t| ]+\\{)",
126 (GRegexCompileFlags
) (G_REGEX_CASELESS
),
127 (GRegexMatchFlags
) 0, NULL
)) != NULL
) {
128 g_regex_match(regex
, s
, (GRegexMatchFlags
) 0, &match_info
);
130 if (g_match_info_matches(match_info
))
131 rs
->sentence
= g_match_info_fetch(match_info
, 0);
133 g_match_info_free(match_info
);
134 g_regex_unref(regex
);
136 /* No valid sentence found, exiting here */
137 if (rs
->sentence
== NULL
) {
142 rs
->param_list
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
, g_free
);
144 /* Capture the argument and the value of the list. This will ensure,
145 * that regex patterns given to {validation=} are parsed correctly,
146 * as long as }{ does not occur within the pattern */
147 regex
= g_regex_new("\\{([a-zA-Z_-]*?)\\=(.*?)\\}(?=\\{|$|\\s)",
148 (GRegexCompileFlags
) (G_REGEX_CASELESS
),
149 (GRegexMatchFlags
) 0, NULL
);
151 g_regex_match_full(regex
, s
, -1, 0, (GRegexMatchFlags
) 0, &match_info
, &error
);
152 while (g_match_info_matches(match_info
)) {
153 char *arg
= g_match_info_fetch(match_info
, 1);
158 param_value
= g_match_info_fetch(match_info
, 2);
160 if (g_ascii_strcasecmp(arg
, "number") == 0) {
161 param_type
= EXTCAP_PARAM_ARGNUM
;
162 } else if (g_ascii_strcasecmp(arg
, "call") == 0) {
163 param_type
= EXTCAP_PARAM_CALL
;
164 } else if (g_ascii_strcasecmp(arg
, "display") == 0) {
165 param_type
= EXTCAP_PARAM_DISPLAY
;
166 } else if (g_ascii_strcasecmp(arg
, "type") == 0) {
167 param_type
= EXTCAP_PARAM_TYPE
;
168 } else if (g_ascii_strcasecmp(arg
, "arg") == 0) {
169 param_type
= EXTCAP_PARAM_ARG
;
170 } else if (g_ascii_strcasecmp(arg
, "default") == 0) {
171 param_type
= EXTCAP_PARAM_DEFAULT
;
172 } else if (g_ascii_strcasecmp(arg
, "value") == 0) {
173 param_type
= EXTCAP_PARAM_VALUE
;
174 } else if (g_ascii_strcasecmp(arg
, "range") == 0) {
175 param_type
= EXTCAP_PARAM_RANGE
;
176 } else if (g_ascii_strcasecmp(arg
, "tooltip") == 0) {
177 param_type
= EXTCAP_PARAM_TOOLTIP
;
178 } else if (g_ascii_strcasecmp(arg
, "placeholder") == 0) {
179 param_type
= EXTCAP_PARAM_PLACEHOLDER
;
180 } else if (g_ascii_strcasecmp(arg
, "mustexist") == 0) {
181 param_type
= EXTCAP_PARAM_FILE_MUSTEXIST
;
182 } else if (g_ascii_strcasecmp(arg
, "fileext") == 0) {
183 param_type
= EXTCAP_PARAM_FILE_EXTENSION
;
184 } else if (g_ascii_strcasecmp(arg
, "group") == 0) {
185 param_type
= EXTCAP_PARAM_GROUP
;
186 } else if (g_ascii_strcasecmp(arg
, "name") == 0) {
187 param_type
= EXTCAP_PARAM_NAME
;
188 } else if (g_ascii_strcasecmp(arg
, "enabled") == 0) {
189 param_type
= EXTCAP_PARAM_ENABLED
;
190 } else if (g_ascii_strcasecmp(arg
, "parent") == 0) {
191 param_type
= EXTCAP_PARAM_PARENT
;
192 } else if (g_ascii_strcasecmp(arg
, "reload") == 0) {
193 param_type
= EXTCAP_PARAM_RELOAD
;
194 } else if (g_ascii_strcasecmp(arg
, "required") == 0) {
195 param_type
= EXTCAP_PARAM_REQUIRED
;
196 } else if (g_ascii_strcasecmp(arg
, "save") == 0) {
197 param_type
= EXTCAP_PARAM_SAVE
;
198 } else if (g_ascii_strcasecmp(arg
, "validation") == 0) {
199 param_type
= EXTCAP_PARAM_VALIDATION
;
200 } else if (g_ascii_strcasecmp(arg
, "version") == 0) {
201 param_type
= EXTCAP_PARAM_VERSION
;
202 } else if (g_ascii_strcasecmp(arg
, "help") == 0) {
203 param_type
= EXTCAP_PARAM_HELP
;
204 } else if (g_ascii_strcasecmp(arg
, "control") == 0) {
205 param_type
= EXTCAP_PARAM_CONTROL
;
206 } else if (g_ascii_strcasecmp(arg
, "role") == 0) {
207 param_type
= EXTCAP_PARAM_ROLE
;
209 param_type
= EXTCAP_PARAM_UNKNOWN
;
212 g_hash_table_insert(rs
->param_list
, ENUM_KEY(param_type
), param_value
);
214 g_match_info_next(match_info
, &error
);
217 g_match_info_free(match_info
);
218 g_regex_unref(regex
);
224 static GList
*extcap_tokenize_sentences(const char *s
) {
226 GList
*sentences
= NULL
;
227 extcap_token_sentence
*item
= NULL
;
228 char **list
, **list_iter
;
230 list_iter
= list
= g_strsplit(s
, "\n", 0);
231 while (*list_iter
!= NULL
) {
232 item
= extcap_tokenize_sentence(*list_iter
);
234 sentences
= g_list_append(sentences
, item
);
243 static void extcap_free_value(extcap_value
*v
) {
254 static void extcap_free_valuelist(void *data
, void *user_data _U_
) {
255 extcap_free_value((extcap_value
*) data
);
258 void extcap_free_arg(extcap_arg
*a
) {
266 g_free(a
->placeholder
);
267 g_free(a
->fileextension
);
270 g_free(a
->device_name
);
272 if (a
->range_start
!= NULL
)
273 extcap_free_complex(a
->range_start
);
275 if (a
->range_end
!= NULL
)
276 extcap_free_complex(a
->range_end
);
278 if (a
->default_complex
!= NULL
)
279 extcap_free_complex(a
->default_complex
);
281 g_list_foreach(a
->values
, (GFunc
) extcap_free_valuelist
, NULL
);
282 g_list_free(a
->values
);
286 static void extcap_free_toolbar_value(iface_toolbar_value
*value
)
293 g_free(value
->value
);
294 g_free(value
->display
);
298 void extcap_free_toolbar_control(iface_toolbar_control
*control
)
305 g_free(control
->display
);
306 g_free(control
->validation
);
307 g_free(control
->tooltip
);
308 g_free(control
->placeholder
);
309 if (control
->ctrl_type
== INTERFACE_TYPE_STRING
) {
310 g_free(control
->default_value
.string
);
312 g_list_free_full(control
->values
, (GDestroyNotify
)extcap_free_toolbar_value
);
316 void extcap_free_arg_list(GList
*a
) {
317 g_list_free_full(a
, (GDestroyNotify
)extcap_free_arg
);
320 static int glist_find_numbered_arg(const void *listelem
, const void *needle
) {
321 if (((const extcap_arg
*) listelem
)->arg_num
== *((const int *) needle
))
326 static int glist_find_numbered_control(const void *listelem
, const void *needle
) {
327 if (((const iface_toolbar_control
*) listelem
)->num
== *((const int *) needle
))
332 static void extcap_free_tokenized_sentence(void *s
, void *user_data _U_
) {
333 extcap_token_sentence
*t
= (extcap_token_sentence
*)s
;
339 g_hash_table_destroy(t
->param_list
);
343 static void extcap_free_tokenized_sentences(GList
*sentences
) {
344 if (sentences
== NULL
)
347 g_list_foreach(sentences
, extcap_free_tokenized_sentence
, NULL
);
348 g_list_free(sentences
);
351 static extcap_value
*extcap_parse_value_sentence(extcap_token_sentence
*s
) {
352 extcap_value
*value
= NULL
;
353 char *param_value
= NULL
;
360 if (g_ascii_strcasecmp(s
->sentence
, "value") == 0) {
362 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_ARG
)))
364 printf("no arg in VALUE sentence\n");
368 if (sscanf(param_value
, "%d", &tint
) != 1) {
369 printf("invalid arg in VALUE sentence\n");
373 value
= g_new0(extcap_value
, 1);
374 value
->arg_num
= tint
;
376 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_VALUE
)))
378 /* printf("no value in VALUE sentence\n"); */
379 extcap_free_value(value
);
382 value
->call
= g_strdup(param_value
);
384 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DISPLAY
)))
386 /* printf("no display in VALUE sentence\n"); */
387 extcap_free_value(value
);
390 value
->display
= g_strdup(param_value
);
392 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_PARENT
)))
394 value
->parent
= g_strdup(param_value
);
397 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DEFAULT
)))
399 /* printf("found default value\n"); */
400 value
->is_default
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
403 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_ENABLED
)))
405 value
->enabled
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
412 static extcap_arg
*extcap_parse_arg_sentence(GList
*args
, extcap_token_sentence
*s
) {
413 char *param_value
= NULL
;
415 extcap_arg
*target_arg
= NULL
;
416 extcap_value
*value
= NULL
;
419 extcap_sentence_type sent
= EXTCAP_SENTENCE_UNKNOWN
;
424 if (g_ascii_strcasecmp(s
->sentence
, "arg") == 0) {
425 sent
= EXTCAP_SENTENCE_ARG
;
426 /* printf("ARG sentence\n"); */
427 } else if (g_ascii_strcasecmp(s
->sentence
, "value") == 0) {
428 sent
= EXTCAP_SENTENCE_VALUE
;
429 /* printf("VALUE sentence\n"); */
432 if (sent
== EXTCAP_SENTENCE_ARG
) {
433 target_arg
= g_new0(extcap_arg
, 1);
434 target_arg
->arg_type
= EXTCAP_ARG_UNKNOWN
;
435 target_arg
->save
= true;
438 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_ARGNUM
))) == NULL
) {
439 extcap_free_arg(target_arg
);
443 if (sscanf(param_value
, "%d", &(target_arg
->arg_num
)) != 1) {
444 extcap_free_arg(target_arg
);
448 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_CALL
))) == NULL
) {
449 extcap_free_arg(target_arg
);
452 target_arg
->call
= g_strdup(param_value
);
454 /* No value only parameters allowed */
455 if (strlen(target_arg
->call
) == 0) {
456 extcap_free_arg(target_arg
);
460 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DISPLAY
))) == NULL
) {
461 extcap_free_arg(target_arg
);
464 target_arg
->display
= g_strdup(param_value
);
466 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_TOOLTIP
)))
468 target_arg
->tooltip
= g_strdup(param_value
);
471 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_PLACEHOLDER
)))
473 target_arg
->placeholder
= g_strdup(param_value
);
476 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_FILE_MUSTEXIST
)))
478 target_arg
->fileexists
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
481 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_FILE_EXTENSION
)))
483 target_arg
->fileextension
= g_strdup(param_value
);
486 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_VALIDATION
)))
488 target_arg
->regexp
= g_strdup(param_value
);
491 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_GROUP
)))
493 target_arg
->group
= g_strdup(param_value
);
496 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_REQUIRED
)))
498 target_arg
->is_required
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
501 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_TYPE
)))
503 /* printf("no type in ARG sentence\n"); */
504 extcap_free_arg(target_arg
);
508 if (g_ascii_strcasecmp(param_value
, "integer") == 0) {
509 target_arg
->arg_type
= EXTCAP_ARG_INTEGER
;
510 } else if (g_ascii_strcasecmp(param_value
, "unsigned") == 0) {
511 target_arg
->arg_type
= EXTCAP_ARG_UNSIGNED
;
512 } else if (g_ascii_strcasecmp(param_value
, "long") == 0) {
513 target_arg
->arg_type
= EXTCAP_ARG_LONG
;
514 } else if (g_ascii_strcasecmp(param_value
, "double") == 0) {
515 target_arg
->arg_type
= EXTCAP_ARG_DOUBLE
;
516 } else if (g_ascii_strcasecmp(param_value
, "boolean") == 0) {
517 target_arg
->arg_type
= EXTCAP_ARG_BOOLEAN
;
518 } else if (g_ascii_strcasecmp(param_value
, "boolflag") == 0) {
519 target_arg
->arg_type
= EXTCAP_ARG_BOOLFLAG
;
520 } else if (g_ascii_strcasecmp(param_value
, "selector") == 0) {
521 target_arg
->arg_type
= EXTCAP_ARG_SELECTOR
;
522 } else if (g_ascii_strcasecmp(param_value
, "editselector") == 0) {
523 target_arg
->arg_type
= EXTCAP_ARG_EDIT_SELECTOR
;
524 } else if (g_ascii_strcasecmp(param_value
, "radio") == 0) {
525 target_arg
->arg_type
= EXTCAP_ARG_RADIO
;
526 } else if (g_ascii_strcasecmp(param_value
, "string") == 0) {
527 target_arg
->arg_type
= EXTCAP_ARG_STRING
;
528 } else if (g_ascii_strcasecmp(param_value
, "password") == 0) {
529 /* Password is never saved because is mapped to PREF_PASSWORD later */
530 target_arg
->arg_type
= EXTCAP_ARG_PASSWORD
;
531 } else if (g_ascii_strcasecmp(param_value
, "fileselect") == 0) {
532 target_arg
->arg_type
= EXTCAP_ARG_FILESELECT
;
533 } else if (g_ascii_strcasecmp(param_value
, "multicheck") == 0) {
534 target_arg
->arg_type
= EXTCAP_ARG_MULTICHECK
;
535 } else if (g_ascii_strcasecmp(param_value
, "timestamp") == 0) {
536 target_arg
->arg_type
= EXTCAP_ARG_TIMESTAMP
;
538 printf("invalid type %s in ARG sentence\n", param_value
);
539 extcap_free_arg(target_arg
);
543 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_SAVE
)))
545 target_arg
->save
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
548 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_RELOAD
)))
550 target_arg
->reload
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
553 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_RANGE
)))
555 char *cp
= g_strstr_len(param_value
, -1, ",");
558 printf("invalid range, expected value,value got %s\n",
560 extcap_free_arg(target_arg
);
564 if ((target_arg
->range_start
= extcap_parse_complex(
565 target_arg
->arg_type
, param_value
)) == NULL
) {
566 printf("invalid range, expected value,value got %s\n",
568 extcap_free_arg(target_arg
);
572 if ((target_arg
->range_end
= extcap_parse_complex(
573 target_arg
->arg_type
, cp
+ 1)) == NULL
) {
574 printf("invalid range, expected value,value got %s\n",
576 extcap_free_arg(target_arg
);
581 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DEFAULT
)))
583 if (target_arg
->arg_type
!= EXTCAP_ARG_MULTICHECK
&& target_arg
->arg_type
!= EXTCAP_ARG_SELECTOR
)
585 if ((target_arg
->default_complex
= extcap_parse_complex(
586 target_arg
->arg_type
, param_value
)) == NULL
) {
587 printf("invalid default, couldn't parse %s\n", param_value
);
592 } else if (sent
== EXTCAP_SENTENCE_VALUE
) {
593 value
= extcap_parse_value_sentence(s
);
597 if ((entry
= g_list_find_custom(args
, &value
->arg_num
, glist_find_numbered_arg
))
599 printf("couldn't find arg %d in list for VALUE sentence\n", value
->arg_num
);
603 ((extcap_arg
*) entry
->data
)->values
= g_list_append(
604 ((extcap_arg
*) entry
->data
)->values
, value
);
612 GList
*extcap_parse_args(char *output
) {
613 GList
*result
= NULL
;
614 GList
*walker
= NULL
;
617 walker
= extcap_tokenize_sentences(output
);
621 extcap_arg
*ra
= NULL
;
622 extcap_token_sentence
*sentence
= (extcap_token_sentence
*)walker
->data
;
624 if ((ra
= extcap_parse_arg_sentence(result
, sentence
)) != NULL
)
625 result
= g_list_append(result
, (void *) ra
);
627 walker
= g_list_next(walker
);
630 extcap_free_tokenized_sentences(temp
);
635 GList
*extcap_parse_values(char *output
) {
636 GList
*result
= NULL
;
637 GList
*walker
= NULL
;
640 walker
= extcap_tokenize_sentences(output
);
644 extcap_value
*ra
= NULL
;
645 extcap_token_sentence
*sentence
= (extcap_token_sentence
*)walker
->data
;
647 if ((ra
= extcap_parse_value_sentence(sentence
)) != NULL
)
648 result
= g_list_append(result
, (void *) ra
);
650 walker
= g_list_next(walker
);
653 extcap_free_tokenized_sentences(temp
);
658 static extcap_interface
*extcap_parse_interface_sentence(extcap_token_sentence
*s
) {
659 extcap_sentence_type sent
= EXTCAP_SENTENCE_UNKNOWN
;
660 char *param_value
= NULL
;
661 extcap_interface
*ri
= NULL
;
666 if (g_ascii_strcasecmp(s
->sentence
, "interface") == 0) {
667 sent
= EXTCAP_SENTENCE_INTERFACE
;
668 } else if (g_ascii_strcasecmp(s
->sentence
, "extcap") == 0) {
669 sent
= EXTCAP_SENTENCE_EXTCAP
;
672 if (sent
== EXTCAP_SENTENCE_UNKNOWN
)
675 ri
= g_new0(extcap_interface
, 1);
679 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_VALUE
)))
680 == NULL
&& sent
== EXTCAP_SENTENCE_INTERFACE
) {
681 printf("No value in INTERFACE sentence\n");
685 ri
->call
= g_strdup(param_value
);
687 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DISPLAY
)))
688 == NULL
&& sent
== EXTCAP_SENTENCE_INTERFACE
) {
689 printf("No display in INTERFACE sentence\n");
694 ri
->display
= g_strdup(param_value
);
696 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_VERSION
)))
698 ri
->version
= g_strdup(param_value
);
701 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_HELP
)))
703 ri
->help
= g_strdup(param_value
);
709 static iface_toolbar_control
*extcap_parse_control_sentence(GList
*control_items
, extcap_token_sentence
*s
)
711 extcap_sentence_type sent
= EXTCAP_SENTENCE_UNKNOWN
;
712 char *param_value
= NULL
;
713 iface_toolbar_control
*control
= NULL
;
714 iface_toolbar_value
*value
= NULL
;
721 if (g_ascii_strcasecmp(s
->sentence
, "control") == 0) {
722 sent
= EXTCAP_SENTENCE_CONTROL
;
723 } else if (g_ascii_strcasecmp(s
->sentence
, "value") == 0) {
724 sent
= EXTCAP_SENTENCE_VALUE
;
727 if (sent
== EXTCAP_SENTENCE_UNKNOWN
)
730 if (sent
== EXTCAP_SENTENCE_CONTROL
) {
731 control
= g_new0(iface_toolbar_control
, 1);
732 control
->ctrl_type
= INTERFACE_TYPE_UNKNOWN
;
734 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_ARGNUM
));
735 if (param_value
== NULL
) {
736 extcap_free_toolbar_control(control
);
740 if (!ws_strtou32(param_value
, NULL
, &num
)) {
741 extcap_free_toolbar_control(control
);
744 control
->num
= (int)num
;
746 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DISPLAY
));
747 if (param_value
== NULL
) {
748 extcap_free_toolbar_control(control
);
751 control
->display
= g_strdup(param_value
);
753 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_VALIDATION
)))
755 control
->validation
= g_strdup(param_value
);
758 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_REQUIRED
)))
760 control
->is_required
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
763 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_TOOLTIP
));
764 control
->tooltip
= g_strdup(param_value
);
766 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_PLACEHOLDER
));
767 control
->placeholder
= g_strdup(param_value
);
769 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_TYPE
));
770 if (param_value
== NULL
) {
771 extcap_free_toolbar_control(control
);
775 extcap_arg_type arg_type
= EXTCAP_ARG_UNKNOWN
;
776 if (g_ascii_strcasecmp(param_value
, "boolean") == 0) {
777 control
->ctrl_type
= INTERFACE_TYPE_BOOLEAN
;
778 arg_type
= EXTCAP_ARG_BOOLEAN
;
779 } else if (g_ascii_strcasecmp(param_value
, "button") == 0) {
780 control
->ctrl_type
= INTERFACE_TYPE_BUTTON
;
781 } else if (g_ascii_strcasecmp(param_value
, "selector") == 0) {
782 control
->ctrl_type
= INTERFACE_TYPE_SELECTOR
;
783 } else if (g_ascii_strcasecmp(param_value
, "string") == 0) {
784 control
->ctrl_type
= INTERFACE_TYPE_STRING
;
785 arg_type
= EXTCAP_ARG_STRING
;
787 printf("invalid type %s in CONTROL sentence\n", param_value
);
788 extcap_free_toolbar_control(control
);
792 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_ROLE
));
793 if (param_value
!= NULL
) {
794 if (g_ascii_strcasecmp(param_value
, "control") == 0) {
795 control
->ctrl_role
= INTERFACE_ROLE_CONTROL
;
796 } else if (g_ascii_strcasecmp(param_value
, "help") == 0) {
797 control
->ctrl_role
= INTERFACE_ROLE_HELP
;
798 } else if (g_ascii_strcasecmp(param_value
, "logger") == 0) {
799 control
->ctrl_role
= INTERFACE_ROLE_LOGGER
;
800 } else if (g_ascii_strcasecmp(param_value
, "restore") == 0) {
801 control
->ctrl_role
= INTERFACE_ROLE_RESTORE
;
803 printf("invalid role %s in CONTROL sentence\n", param_value
);
804 control
->ctrl_role
= INTERFACE_ROLE_UNKNOWN
;
808 control
->ctrl_role
= INTERFACE_ROLE_CONTROL
;
811 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DEFAULT
));
812 if (param_value
!= NULL
) {
813 if (arg_type
!= EXTCAP_ARG_UNKNOWN
) {
814 extcap_complex
*complex = extcap_parse_complex(arg_type
, param_value
);
815 if (complex != NULL
) {
816 if (arg_type
== EXTCAP_ARG_BOOLEAN
) {
817 control
->default_value
.boolean
= extcap_complex_get_bool(complex);
818 } else if (arg_type
== EXTCAP_ARG_STRING
) {
819 control
->default_value
.string
= g_strdup(complex->_val
);
821 extcap_free_complex(complex);
823 printf("invalid default, couldn't parse %s\n", param_value
);
828 } else if (sent
== EXTCAP_SENTENCE_VALUE
) {
829 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_CONTROL
));
830 if (param_value
== NULL
) {
831 printf("no control in VALUE sentence\n");
835 if (!ws_strtou32(param_value
, NULL
, &num
)) {
836 extcap_free_toolbar_control(control
);
840 entry
= g_list_find_custom(control_items
, &num
, glist_find_numbered_control
);
842 printf("couldn't find control %u in list for VALUE sentence\n", num
);
846 value
= g_new0(iface_toolbar_value
, 1);
847 value
->num
= (int)num
;
849 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_VALUE
));
850 if (param_value
== NULL
) {
851 extcap_free_toolbar_value(value
);
854 value
->value
= g_strdup(param_value
);
856 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DISPLAY
));
857 if (param_value
== NULL
) {
858 extcap_free_toolbar_value(value
);
861 value
->display
= g_strdup(param_value
);
863 param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DEFAULT
));
864 if (param_value
!= NULL
) {
865 value
->is_default
= matches_regex(EXTCAP_BOOLEAN_REGEX
, param_value
);
868 control
= (iface_toolbar_control
*)entry
->data
;
869 control
->values
= g_list_append(control
->values
, value
);
877 GList
*extcap_parse_interfaces(char *output
, GList
**control_items
) {
879 GList
*result
= NULL
;
880 GList
*tokens
= NULL
;
881 GList
*walker
= extcap_tokenize_sentences(output
);
885 extcap_interface
*ri
= NULL
;
886 iface_toolbar_control
*ti
= NULL
;
887 extcap_token_sentence
*if_sentence
= (extcap_token_sentence
*) walker
->data
;
890 if ((g_ascii_strcasecmp(if_sentence
->sentence
, "interface") == 0) ||
891 (g_ascii_strcasecmp(if_sentence
->sentence
, "extcap") == 0))
893 if ((ri
= extcap_parse_interface_sentence(if_sentence
))) {
894 result
= g_list_append(result
, ri
);
896 } else if (control_items
&&
897 ((g_ascii_strcasecmp(if_sentence
->sentence
, "control") == 0) ||
898 (g_ascii_strcasecmp(if_sentence
->sentence
, "value") == 0)))
900 if ((ti
= extcap_parse_control_sentence(*control_items
, if_sentence
))) {
901 *control_items
= g_list_append(*control_items
, ti
);
906 walker
= g_list_next(walker
);
909 extcap_free_tokenized_sentences(tokens
);
914 /* Parse a tokenized set of sentences and validate, looking for DLT definitions */
915 static extcap_dlt
*extcap_parse_dlt_sentence(extcap_token_sentence
*s
) {
916 char *param_value
= NULL
;
917 extcap_sentence_type sent
= EXTCAP_SENTENCE_UNKNOWN
;
918 extcap_dlt
*result
= NULL
;
923 if (g_ascii_strcasecmp(s
->sentence
, "dlt") == 0) {
924 sent
= EXTCAP_SENTENCE_DLT
;
927 if (sent
== EXTCAP_SENTENCE_UNKNOWN
)
930 result
= g_new0(extcap_dlt
, 1);
934 result
->display
= NULL
;
936 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_ARGNUM
)))
938 printf("No number in DLT sentence\n");
942 if (sscanf(param_value
, "%d", &(result
->number
)) != 1) {
943 printf("Invalid number in DLT sentence\n");
948 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_NAME
)))
950 printf("No name in DLT sentence\n");
954 result
->name
= g_strdup(param_value
);
956 if ((param_value
= (char *)g_hash_table_lookup(s
->param_list
, ENUM_KEY(EXTCAP_PARAM_DISPLAY
)))
958 printf("No display in DLT sentence\n");
959 g_free(result
->name
);
963 result
->display
= g_strdup(param_value
);
968 GList
*extcap_parse_dlts(char *output
) {
970 GList
*walker
= NULL
;
972 GList
*result
= NULL
;
974 walker
= extcap_tokenize_sentences(output
);
979 extcap_dlt
*data
= NULL
;
981 if ((data
= extcap_parse_dlt_sentence((extcap_token_sentence
*)walker
->data
)) != NULL
)
982 result
= g_list_append(result
, data
);
984 walker
= g_list_next(walker
);
987 extcap_free_tokenized_sentences(temp
);
993 * Editor modelines - https://www.wireshark.org/tools/modelines.html
998 * indent-tabs-mode: nil
1001 * vi: set shiftwidth=4 tabstop=8 expandtab:
1002 * :indentSize=4:tabSize=8:noTabs=true: