nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* decode_as_utils.c
2 *
3 * Routines to modify dissector tables on the fly.
4 *
5 * By David Hampton <dhampton@mac.com>
6 * Copyright 2001 David Hampton
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #include "config.h"
23  
24 #include <stdlib.h>
25  
26 #include <errno.h>
27  
28 #include "epan/decode_as.h"
29 #include "epan/packet.h"
30 #include "epan/prefs.h"
31 #include "epan/prefs-int.h"
32  
33 #include "epan/dissectors/packet-dcerpc.h"
34  
35 #include "ui/decode_as_utils.h"
36 #include "ui/simple_dialog.h"
37  
38 #include "wsutil/file_util.h"
39 #include "wsutil/filesystem.h"
40 #include "wsutil/cmdarg_err.h"
41 #include "ws_version_info.h"
42  
43 /* XXX - We might want to switch this to a UAT */
44  
45 /*
46 * A list of dissectors that need to be reset.
47 */
48 static GSList *dissector_reset_list = NULL;
49  
50 /*
51 * Data structure used as user data when iterating dissector handles
52 */
53 typedef struct lookup_entry {
54 gchar* dissector_short_name;
55 dissector_handle_t handle;
56 } lookup_entry_t;
57  
58 /*
59 * Data structure for tracking which dissector need to be reset. This
60 * structure is necessary as a hash table entry cannot be removed
61 * while a g_hash_table_foreach walk is in progress.
62 */
63 typedef struct dissector_delete_item {
64 /* The name of the dissector table */
65 gchar *ddi_table_name;
66 /* The type of the selector in that dissector table */
67 ftenum_t ddi_selector_type;
68 /* The selector in the dissector table */
69 union {
70 guint sel_uint;
71 char *sel_string;
72 } ddi_selector;
73 } dissector_delete_item_t;
74  
75 /*
76 * A callback function to changed a dissector_handle if matched
77 * This is used when iterating a dissector table
78 */
79 static void
80 change_dissector_if_matched(gpointer item, gpointer user_data)
81 {
82 dissector_handle_t handle = (dissector_handle_t)item;
83 lookup_entry_t * lookup = (lookup_entry_t *)user_data;
84 const gchar *proto_short_name = dissector_handle_get_short_name(handle);
85 if (proto_short_name && strcmp(lookup->dissector_short_name, proto_short_name) == 0) {
86 lookup->handle = handle;
87 }
88 }
89  
90 /*
91 * A callback function to parse each "decode as" entry in the file and apply the change
92 */
93 static prefs_set_pref_e
94 read_set_decode_as_entries(gchar *key, const gchar *value,
95 void *user_data _U_,
96 gboolean return_range_errors _U_)
97 {
98 gchar *values[4] = {NULL, NULL, NULL, NULL};
99 gchar delimiter[4] = {',', ',', ',','\0'};
100 gchar *pch;
101 guint i, j;
102 dissector_table_t sub_dissectors;
103 prefs_set_pref_e retval = PREFS_SET_OK;
104 gboolean is_valid = FALSE;
105  
106 if (strcmp(key, DECODE_AS_ENTRY) == 0) {
107 /* Parse csv into table, selector, initial, current */
108 for (i = 0; i < 4; i++) {
109 pch = strchr(value, delimiter[i]);
110 if (pch == NULL) {
111 for (j = 0; j < i; j++) {
112 g_free(values[j]);
113 }
114 return PREFS_SET_SYNTAX_ERR;
115 }
116 values[i] = g_strndup(value, pch - value);
117 value = pch + 1;
118 }
119 sub_dissectors = find_dissector_table(values[0]);
120 if (sub_dissectors != NULL) {
121 lookup_entry_t lookup;
122 ftenum_t selector_type;
123  
124 lookup.dissector_short_name = values[3];
125 lookup.handle = NULL;
126 selector_type = dissector_table_get_type(sub_dissectors);
127  
128 g_slist_foreach(dissector_table_get_dissector_handles(sub_dissectors),
129 change_dissector_if_matched, &lookup);
130 if (lookup.handle != NULL || g_ascii_strcasecmp(values[3], DECODE_AS_NONE) == 0) {
131 is_valid = TRUE;
132 }
133  
134 if (is_valid) {
135 if (IS_FT_STRING(selector_type)) {
136 dissector_change_string(values[0], values[1], lookup.handle);
137 } else {
138 char *p;
139 long long_value;
140  
141 long_value = strtol(values[1], &p, 0);
142 if (p == values[0] || *p != '\0' || long_value < 0 ||
143 (unsigned long)long_value > UINT_MAX) {
144 retval = PREFS_SET_SYNTAX_ERR;
145 is_valid = FALSE;
146 } else
147 dissector_change_uint(values[0], (guint)long_value, lookup.handle);
148 }
149 }
150 if (is_valid) {
151 decode_build_reset_list(values[0], selector_type, values[1], NULL, NULL);
152 }
153 } else {
154 retval = PREFS_SET_SYNTAX_ERR;
155 }
156  
157 } else {
158 retval = PREFS_SET_NO_SUCH_PREF;
159 }
160  
161 for (i = 0; i < 4; i++) {
162 g_free(values[i]);
163 }
164 return retval;
165 }
166  
167 void
168 load_decode_as_entries(void)
169 {
170 char *daf_path;
171 FILE *daf;
172  
173 if (dissector_reset_list) {
174 decode_clear_all();
175 }
176  
177 daf_path = get_persconffile_path(DECODE_AS_ENTRIES_FILE_NAME, TRUE);
178 if ((daf = ws_fopen(daf_path, "r")) != NULL) {
179 read_prefs_file(daf_path, daf, read_set_decode_as_entries, NULL);
180 fclose(daf);
181 }
182 g_free(daf_path);
183 }
184  
185 void
186 decode_build_reset_list (const gchar *table_name, ftenum_t selector_type,
187 gpointer key, gpointer value _U_,
188 gpointer user_data _U_)
189 {
190 dissector_delete_item_t *item;
191  
192 item = g_new(dissector_delete_item_t,1);
193 item->ddi_table_name = g_strdup(table_name);
194 item->ddi_selector_type = selector_type;
195 switch (selector_type) {
196  
197 case FT_UINT8:
198 case FT_UINT16:
199 case FT_UINT24:
200 case FT_UINT32:
201 item->ddi_selector.sel_uint = GPOINTER_TO_UINT(key);
202 break;
203  
204 case FT_STRING:
205 case FT_STRINGZ:
206 case FT_UINT_STRING:
207 case FT_STRINGZPAD:
208 item->ddi_selector.sel_string = g_strdup((char *)key);
209 break;
210  
211 default:
212 g_assert_not_reached();
213 }
214 dissector_reset_list = g_slist_prepend(dissector_reset_list, item);
215 }
216  
217 /* clear all settings */
218 void
219 decode_clear_all(void)
220 {
221 dissector_delete_item_t *item;
222 GSList *tmp;
223  
224 dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
225  
226 for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
227 item = (dissector_delete_item_t *)tmp->data;
228 switch (item->ddi_selector_type) {
229  
230 case FT_UINT8:
231 case FT_UINT16:
232 case FT_UINT24:
233 case FT_UINT32:
234 dissector_reset_uint(item->ddi_table_name,
235 item->ddi_selector.sel_uint);
236 break;
237  
238 case FT_STRING:
239 case FT_STRINGZ:
240 case FT_UINT_STRING:
241 case FT_STRINGZPAD:
242 dissector_reset_string(item->ddi_table_name,
243 item->ddi_selector.sel_string);
244 g_free(item->ddi_selector.sel_string);
245 break;
246  
247 default:
248 g_assert_not_reached();
249 }
250 g_free(item->ddi_table_name);
251 g_free(item);
252 }
253 g_slist_free(dissector_reset_list);
254 dissector_reset_list = NULL;
255  
256 decode_dcerpc_reset_all();
257 }
258  
259 static void
260 decode_as_write_entry (const gchar *table_name, ftenum_t selector_type,
261 gpointer key, gpointer value, gpointer user_data)
262 {
263 FILE *da_file = (FILE *)user_data;
264 dissector_handle_t current, initial;
265 const gchar *current_proto_name, *initial_proto_name;
266  
267 current = dtbl_entry_get_handle((dtbl_entry_t *)value);
268 if (current == NULL)
269 current_proto_name = DECODE_AS_NONE;
270 else
271 current_proto_name = dissector_handle_get_short_name(current);
272 initial = dtbl_entry_get_initial_handle((dtbl_entry_t *)value);
273 if (initial == NULL)
274 initial_proto_name = DECODE_AS_NONE;
275 else
276 initial_proto_name = dissector_handle_get_short_name(initial);
277  
278 switch (selector_type) {
279  
280 case FT_UINT8:
281 case FT_UINT16:
282 case FT_UINT24:
283 case FT_UINT32:
284 /*
285 * XXX - write these in decimal, regardless of the base of
286 * the dissector table's selector, as older versions of
287 * Wireshark used atoi() when reading this file, and
288 * failed to handle hex or octal numbers.
289 *
290 * That will be fixed in future 1.10 and 1.12 releases,
291 * but pre-1.10 releases are at end-of-life and won't
292 * be fixed.
293 */
294 fprintf (da_file,
295 DECODE_AS_ENTRY ": %s,%u,%s,%s\n",
296 table_name, GPOINTER_TO_UINT(key), initial_proto_name,
297 current_proto_name);
298 break;
299  
300 case FT_STRING:
301 case FT_STRINGZ:
302 case FT_UINT_STRING:
303 case FT_STRINGZPAD:
304 fprintf (da_file,
305 DECODE_AS_ENTRY ": %s,%s,%s,%s\n",
306 table_name, (gchar *)key, initial_proto_name,
307 current_proto_name);
308 break;
309  
310 default:
311 g_assert_not_reached();
312 break;
313 }
314 }
315  
316 int
317 save_decode_as_entries(gchar** err)
318 {
319 char *pf_dir_path;
320 char *daf_path;
321 FILE *da_file;
322  
323 if (create_persconffile_dir(&pf_dir_path) == -1) {
324 *err = g_strdup_printf("Can't create directory\n\"%s\"\nfor recent file: %s.",
325 pf_dir_path, g_strerror(errno));
326 g_free(pf_dir_path);
327 return -1;
328 }
329  
330 daf_path = get_persconffile_path(DECODE_AS_ENTRIES_FILE_NAME, TRUE);
331 if ((da_file = ws_fopen(daf_path, "w")) == NULL) {
332 *err = g_strdup_printf("Can't open decode_as_entries file\n\"%s\": %s.",
333 daf_path, g_strerror(errno));
334 g_free(daf_path);
335 return -1;
336 }
337  
338 fputs("# \"Decode As\" entries file for Wireshark " VERSION ".\n"
339 "#\n"
340 "# This file is regenerated each time \"Decode As\" preferences\n"
341 "# are saved within Wireshark. Making manual changes should be safe,\n"
342 "# however.\n", da_file);
343  
344 dissector_all_tables_foreach_changed(decode_as_write_entry, da_file);
345 fclose(da_file);
346 return 0;
347 }
348  
349 static const char* prev_display_dissector_name = NULL;
350  
351 /*
352 * For a dissector table, print on the stream described by output,
353 * its short name (which is what's used in the "-d" option) and its
354 * descriptive name.
355 */
356 static void
357 display_dissector_table_names(const char *table_name, const char *ui_name,
358 gpointer output)
359 {
360 if ((prev_display_dissector_name == NULL) ||
361 (strcmp(prev_display_dissector_name, table_name) != 0)) {
362 fprintf((FILE *)output, "\t%s (%s)\n", table_name, ui_name);
363 prev_display_dissector_name = table_name;
364 }
365 }
366  
367 /*
368 * For a dissector handle, print on the stream described by output,
369 * the filter name (which is what's used in the "-d" option) and the full
370 * name for the protocol that corresponds to this handle.
371 */
372 static void
373 display_dissector_names(const gchar *table _U_, gpointer handle, gpointer output)
374 {
375 int proto_id;
376 const gchar *proto_filter_name;
377 const gchar *proto_ui_name;
378  
379 proto_id = dissector_handle_get_protocol_index((dissector_handle_t)handle);
380  
381 if (proto_id != -1) {
382 proto_filter_name = proto_get_protocol_filter_name(proto_id);
383 proto_ui_name = proto_get_protocol_name(proto_id);
384 g_assert(proto_filter_name != NULL);
385 g_assert(proto_ui_name != NULL);
386  
387 if ((prev_display_dissector_name == NULL) ||
388 (strcmp(prev_display_dissector_name, proto_filter_name) != 0)) {
389 fprintf((FILE *)output, "\t%s (%s)\n",
390 proto_filter_name,
391 proto_ui_name);
392 prev_display_dissector_name = proto_filter_name;
393 }
394 }
395 }
396  
397 /*
398 * Allow dissector key names to be sorted alphabetically
399 */
400  
401 static gint
402 compare_dissector_key_name(gconstpointer dissector_a, gconstpointer dissector_b)
403 {
404 return strcmp((const char*)dissector_a, (const char*)dissector_b);
405 }
406  
407 /*
408 * Print all layer type names supported.
409 * We send the output to the stream described by the handle output.
410 */
411 static void
412 fprint_all_layer_types(FILE *output)
413  
414 {
415 prev_display_dissector_name = NULL;
416 dissector_all_tables_foreach_table(display_dissector_table_names, (gpointer)output, (GCompareFunc)compare_dissector_key_name);
417 }
418  
419 /*
420 * Print all protocol names supported for a specific layer type.
421 * table_name contains the layer type name in which the search is performed.
422 * We send the output to the stream described by the handle output.
423 */
424 static void
425 fprint_all_protocols_for_layer_types(FILE *output, gchar *table_name)
426  
427 {
428 prev_display_dissector_name = NULL;
429 dissector_table_foreach_handle(table_name,
430 display_dissector_names,
431 (gpointer)output);
432 }
433  
434 /*
435 * The protocol_name_search structure is used by find_protocol_name_func()
436 * to pass parameters and store results
437 */
438 struct protocol_name_search{
439 gchar *searched_name; /* Protocol filter name we are looking for */
440 dissector_handle_t matched_handle; /* Handle for a dissector whose protocol has the specified filter name */
441 guint nb_match; /* How many dissectors matched searched_name */
442 };
443 typedef struct protocol_name_search *protocol_name_search_t;
444  
445 /*
446 * This function parses all dissectors associated with a table to find the
447 * one whose protocol has the specified filter name. It is called
448 * as a reference function in a call to dissector_table_foreach_handle.
449 * The name we are looking for, as well as the results, are stored in the
450 * protocol_name_search struct pointed to by user_data.
451 * If called using dissector_table_foreach_handle, we actually parse the
452 * whole list of dissectors.
453 */
454 static void
455 find_protocol_name_func(const gchar *table _U_, gpointer handle, gpointer user_data)
456  
457 {
458 int proto_id;
459 const gchar *protocol_filter_name;
460 protocol_name_search_t search_info;
461  
462 g_assert(handle);
463  
464 search_info = (protocol_name_search_t)user_data;
465  
466 proto_id = dissector_handle_get_protocol_index((dissector_handle_t)handle);
467 if (proto_id != -1) {
468 protocol_filter_name = proto_get_protocol_filter_name(proto_id);
469 g_assert(protocol_filter_name != NULL);
470 if (strcmp(protocol_filter_name, search_info->searched_name) == 0) {
471 /* Found a match */
472 if (search_info->nb_match == 0) {
473 /* Record this handle only if this is the first match */
474 search_info->matched_handle = (dissector_handle_t)handle; /* Record the handle for this matching dissector */
475 }
476 search_info->nb_match++;
477 }
478 }
479 }
480  
481 /*
482 * The function below parses the command-line parameters for the decode as
483 * feature (a string pointer by cl_param).
484 * It checks the format of the command-line, searches for a matching table
485 * and dissector. If a table/dissector match is not found, we display a
486 * summary of the available tables/dissectors (on stderr) and return FALSE.
487 * If everything is fine, we get the "Decode as" preference activated,
488 * then we return TRUE.
489 */
490 gboolean decode_as_command_option(const gchar *cl_param)
491 {
492 gchar *table_name;
493 guint32 selector, selector2;
494 gchar *decoded_param;
495 gchar *remaining_param;
496 gchar *selector_str;
497 gchar *dissector_str;
498 dissector_handle_t dissector_matching;
499 dissector_table_t table_matching;
500 ftenum_t dissector_table_selector_type;
501 struct protocol_name_search user_protocol_name;
502 guint64 i;
503 char op;
504  
505 /* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
506  
507 g_assert(cl_param);
508 decoded_param = g_strdup(cl_param);
509 g_assert(decoded_param);
510  
511  
512 /* The lines below will parse this string (modifying it) to extract all
513 necessary information. Note that decoded_param is still needed since
514 strings are not copied - we just save pointers. */
515  
516 /* This section extracts a layer type (table_name) from decoded_param */
517 table_name = decoded_param; /* Layer type string starts from beginning */
518  
519 remaining_param = strchr(table_name, '=');
520 if (remaining_param == NULL) {
521 cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, DECODE_AS_ARG_TEMPLATE);
522 /* If the argument does not follow the template, carry on anyway to check
523 if the table name is at least correct. If remaining_param is NULL,
524 we'll exit anyway further down */
525 }
526 else {
527 *remaining_param = '\0'; /* Terminate the layer type string (table_name) where '=' was detected */
528 }
529  
530 /* Remove leading and trailing spaces from the table name */
531 while (table_name[0] == ' ')
532 table_name++;
533 while (table_name[strlen(table_name) - 1] == ' ')
534 table_name[strlen(table_name) - 1] = '\0'; /* Note: if empty string, while loop will eventually exit */
535  
536 /* The following part searches a table matching with the layer type specified */
537 table_matching = NULL;
538  
539 /* Look for the requested table */
540 if (!(*(table_name))) { /* Is the table name empty, if so, don't even search for anything, display a message */
541 cmdarg_err("No layer type specified"); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
542 }
543 else {
544 table_matching = find_dissector_table(table_name);
545 if (!table_matching) {
546 cmdarg_err("Unknown layer type -- %s", table_name); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
547 }
548 }
549  
550 if (!table_matching) {
551 /* Display a list of supported layer types to help the user, if the
552 specified layer type was not found */
553 cmdarg_err("Valid layer types are:");
554 fprint_all_layer_types(stderr);
555 }
556 if (remaining_param == NULL || !table_matching) {
557 /* Exit if the layer type was not found, or if no '=' separator was found
558 (see above) */
559 g_free(decoded_param);
560 return FALSE;
561 }
562  
563 if (*(remaining_param + 1) != '=') { /* Check for "==" and not only '=' */
564 cmdarg_err("WARNING: -d requires \"==\" instead of \"=\". Option will be treated as \"%s==%s\"", table_name, remaining_param + 1);
565 }
566 else {
567 remaining_param++; /* Move to the second '=' */
568 *remaining_param = '\0'; /* Remove the second '=' */
569 }
570 remaining_param++; /* Position after the layer type string */
571  
572 /* This section extracts a selector value (selector_str) from decoded_param */
573  
574 selector_str = remaining_param; /* Next part starts with the selector number */
575  
576 remaining_param = strchr(selector_str, ',');
577 if (remaining_param == NULL) {
578 cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, DECODE_AS_ARG_TEMPLATE);
579 /* If the argument does not follow the template, carry on anyway to check
580 if the selector value is at least correct. If remaining_param is NULL,
581 we'll exit anyway further down */
582 }
583 else {
584 *remaining_param = '\0'; /* Terminate the selector number string (selector_str) where ',' was detected */
585 }
586  
587 dissector_table_selector_type = get_dissector_table_selector_type(table_name);
588  
589 switch (dissector_table_selector_type) {
590  
591 case FT_UINT8:
592 case FT_UINT16:
593 case FT_UINT24:
594 case FT_UINT32:
595 /* The selector for this table is an unsigned number. Parse it as such.
596 There's no need to remove leading and trailing spaces from the
597 selector number string, because sscanf will do that for us. */
598 switch (sscanf(selector_str, "%u%c%u", &selector, &op, &selector2)) {
599 case 1:
600 op = '\0';
601 break;
602 case 3:
603 if (op != ':' && op != '-') {
604 cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
605 g_free(decoded_param);
606 return FALSE;
607 }
608 if (op == ':') {
609 if ((selector2 == 0) || ((guint64)selector + selector2 - 1) > G_MAXUINT32) {
610 cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
611 g_free(decoded_param);
612 return FALSE;
613 }
614 }
615 else if (selector2 < selector) {
616 /* We could swap them for the user, but maybe it's better to call
617 * this out as an error in case it's not what was intended? */
618 cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
619 g_free(decoded_param);
620 return FALSE;
621 }
622 break;
623 default:
624 cmdarg_err("Invalid selector number \"%s\"", selector_str);
625 g_free(decoded_param);
626 return FALSE;
627 }
628 break;
629  
630 case FT_STRING:
631 case FT_STRINGZ:
632 case FT_UINT_STRING:
633 case FT_STRINGZPAD:
634 /* The selector for this table is a string. */
635 break;
636  
637 default:
638 /* There are currently no dissector tables with any types other
639 than the ones listed above. */
640 g_assert_not_reached();
641 }
642  
643 if (remaining_param == NULL) {
644 /* Exit if no ',' separator was found (see above) */
645 cmdarg_err("Valid protocols for layer type \"%s\" are:", table_name);
646 fprint_all_protocols_for_layer_types(stderr, table_name);
647 g_free(decoded_param);
648 return FALSE;
649 }
650  
651 remaining_param++; /* Position after the selector number string */
652  
653 /* This section extracts a protocol filter name (dissector_str) from decoded_param */
654  
655 dissector_str = remaining_param; /* All the rest of the string is the dissector (decode as protocol) name */
656  
657 /* Remove leading and trailing spaces from the dissector name */
658 while (dissector_str[0] == ' ')
659 dissector_str++;
660 while (dissector_str[strlen(dissector_str) - 1] == ' ')
661 dissector_str[strlen(dissector_str) - 1] = '\0'; /* Note: if empty string, while loop will eventually exit */
662  
663 dissector_matching = NULL;
664  
665 /* We now have a pointer to the handle for the requested table inside the variable table_matching */
666 if (!(*dissector_str)) { /* Is the dissector name empty, if so, don't even search for a matching dissector and display all dissectors found for the selected table */
667 cmdarg_err("No protocol name specified"); /* Note, we don't exit here, but dissector_matching will remain NULL, so we exit below */
668 }
669 else {
670 user_protocol_name.nb_match = 0;
671 user_protocol_name.searched_name = dissector_str;
672 user_protocol_name.matched_handle = NULL;
673  
674 dissector_table_foreach_handle(table_name, find_protocol_name_func, &user_protocol_name); /* Go and perform the search for this dissector in the this table's dissectors' names and shortnames */
675  
676 if (user_protocol_name.nb_match != 0) {
677 dissector_matching = user_protocol_name.matched_handle;
678 if (user_protocol_name.nb_match > 1) {
679 cmdarg_err("WARNING: Protocol \"%s\" matched %u dissectors, first one will be used", dissector_str, user_protocol_name.nb_match);
680 }
681 }
682 else {
683 /* OK, check whether the problem is that there isn't any such
684 protocol, or that there is but it's not specified as a protocol
685 that's valid for that dissector table.
686 Note, we don't exit here, but dissector_matching will remain NULL,
687 so we exit below */
688 if (proto_get_id_by_filter_name(dissector_str) == -1) {
689 /* No such protocol */
690 cmdarg_err("Unknown protocol -- \"%s\"", dissector_str);
691 }
692 else {
693 cmdarg_err("Protocol \"%s\" isn't valid for layer type \"%s\"",
694 dissector_str, table_name);
695 }
696 }
697 }
698  
699 if (!dissector_matching) {
700 cmdarg_err("Valid protocols for layer type \"%s\" are:", table_name);
701 fprint_all_protocols_for_layer_types(stderr, table_name);
702 g_free(decoded_param);
703 return FALSE;
704 }
705  
706 /* This is the end of the code that parses the command-line options.
707 All information is now stored in the variables:
708 table_name
709 selector
710 dissector_matching
711 The above variables that are strings are still pointing to areas within
712 decoded_parm. decoded_parm thus still needs to be kept allocated in
713 until we stop needing these variables
714 decoded_param will be deallocated at each exit point of this function */
715  
716  
717 /* We now have a pointer to the handle for the requested dissector
718 (requested protocol) inside the variable dissector_matching */
719 switch (dissector_table_selector_type) {
720  
721 case FT_UINT8:
722 case FT_UINT16:
723 case FT_UINT24:
724 case FT_UINT32:
725 /* The selector for this table is an unsigned number. */
726 if (op == '\0') {
727 dissector_change_uint(table_name, selector, dissector_matching);
728 }
729 else if (op == ':') {
730 for (i = selector; i < (guint64)selector + selector2; i++) {
731 dissector_change_uint(table_name, (guint32)i, dissector_matching);
732 }
733 }
734 else { /* op == '-' */
735 for (i = selector; i <= selector2; i++) {
736 dissector_change_uint(table_name, (guint32)i, dissector_matching);
737 }
738 }
739 break;
740  
741 case FT_STRING:
742 case FT_STRINGZ:
743 case FT_UINT_STRING:
744 case FT_STRINGZPAD:
745 /* The selector for this table is a string. */
746 dissector_change_string(table_name, selector_str, dissector_matching);
747 break;
748  
749 default:
750 /* There are currently no dissector tables with any types other
751 than the ones listed above. */
752 g_assert_not_reached();
753 }
754 g_free(decoded_param); /* "Decode As" rule has been successfully added */
755 return TRUE;
756 }
757  
758 /*
759 * Editor modelines
760 *
761 * Local Variables:
762 * c-basic-offset: 4
763 * tab-width: 8
764 * indent-tabs-mode: nil
765 * End:
766 *
767 * ex: set shiftwidth=4 tabstop=8 expandtab:
768 * :indentSize=4:tabSize=8:noTabs=true:
769 */