/src/wireshark/epan/dissectors/packet-ieee802a.c
Line | Count | Source |
1 | | /* packet-ieee802a.c |
2 | | * Routines for IEEE 802a |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * SPDX-License-Identifier: GPL-2.0-or-later |
9 | | */ |
10 | | |
11 | | #include "config.h" |
12 | | |
13 | | #include <epan/packet.h> |
14 | | #include <epan/addr_resolv.h> |
15 | | #include <epan/etypes.h> |
16 | | |
17 | | #include "packet-ieee802a.h" |
18 | | |
19 | | void proto_register_ieee802a(void); |
20 | | void proto_reg_handoff_ieee802a(void); |
21 | | |
22 | | static dissector_handle_t ieee802a_handle; |
23 | | |
24 | | static int proto_ieee802a; |
25 | | static int hf_ieee802a_oui; |
26 | | static int hf_ieee802a_pid; |
27 | | |
28 | | static int ett_ieee802a; |
29 | | |
30 | | /* |
31 | | * Hash table for translating OUIs to a dissector table/field info pair; |
32 | | * the dissector table maps PID values to dissectors, and the field |
33 | | * corresponds to the PID for that OUI. |
34 | | */ |
35 | | typedef struct { |
36 | | dissector_table_t table; |
37 | | hf_register_info *field_info; |
38 | | } oui_info_t; |
39 | | |
40 | | static GHashTable *oui_info_table; |
41 | | |
42 | | /* |
43 | | * Add an entry for a new OUI. |
44 | | */ |
45 | | void |
46 | | ieee802a_add_oui(uint32_t oui, const char *table_name, const char *table_ui_name, |
47 | | hf_register_info *hf_item, const int proto) |
48 | 15 | { |
49 | 15 | oui_info_t *new_info; |
50 | | |
51 | 15 | new_info = g_new(oui_info_t, 1); |
52 | 15 | new_info->table = register_dissector_table(table_name, |
53 | 15 | table_ui_name, proto, FT_UINT16, BASE_HEX); |
54 | 15 | new_info->field_info = hf_item; |
55 | | |
56 | | /* |
57 | | * Create the hash table for OUI information, if it doesn't |
58 | | * already exist. |
59 | | */ |
60 | 15 | if (oui_info_table == NULL) { |
61 | 15 | oui_info_table = g_hash_table_new_full(g_direct_hash, |
62 | 15 | g_direct_equal, NULL, g_free); |
63 | 15 | } |
64 | 15 | g_hash_table_insert(oui_info_table, GUINT_TO_POINTER(oui), new_info); |
65 | 15 | } |
66 | | |
67 | | static int |
68 | | dissect_ieee802a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
69 | 0 | { |
70 | 0 | proto_tree *ieee802a_tree; |
71 | 0 | proto_item *ti; |
72 | 0 | tvbuff_t *next_tvb; |
73 | 0 | const char *manuf; |
74 | 0 | uint32_t oui32; |
75 | 0 | uint16_t pid; |
76 | 0 | oui_info_t *oui_info; |
77 | 0 | dissector_table_t subdissector_table; |
78 | 0 | int hf; |
79 | |
|
80 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE802a"); |
81 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
82 | |
|
83 | 0 | ti = proto_tree_add_item(tree, proto_ieee802a, tvb, 0, 5, ENC_NA); |
84 | 0 | ieee802a_tree = proto_item_add_subtree(ti, ett_ieee802a); |
85 | |
|
86 | 0 | proto_tree_add_item_ret_uint(ieee802a_tree, hf_ieee802a_oui, tvb, 0, 3, ENC_BIG_ENDIAN, &oui32); |
87 | 0 | manuf = uint_get_manuf_name_if_known(oui32); |
88 | 0 | pid = tvb_get_ntohs(tvb, 3); |
89 | |
|
90 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "OUI %s (%s), PID 0x%04X", |
91 | 0 | tvb_bytes_to_str_punct(pinfo->pool, tvb, 0, 3, ':'), |
92 | 0 | manuf ? manuf : "Unknown", pid); |
93 | | |
94 | | /* |
95 | | * Do we have information for this OUI? |
96 | | */ |
97 | 0 | if (oui_info_table != NULL && |
98 | 0 | (oui_info = (oui_info_t *)g_hash_table_lookup(oui_info_table, |
99 | 0 | GUINT_TO_POINTER(oui32))) != NULL) { |
100 | | /* |
101 | | * Yes - use it. |
102 | | */ |
103 | 0 | hf = *oui_info->field_info->p_id; |
104 | 0 | subdissector_table = oui_info->table; |
105 | 0 | } else { |
106 | | /* |
107 | | * No, use hf_ieee802a_pid for the PID and just dissect |
108 | | * the payload as data. |
109 | | */ |
110 | 0 | hf = hf_ieee802a_pid; |
111 | 0 | subdissector_table = NULL; |
112 | 0 | } |
113 | |
|
114 | 0 | proto_tree_add_uint(ieee802a_tree, hf, tvb, 3, 2, pid); |
115 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 5); |
116 | 0 | if ((subdissector_table == NULL) || |
117 | | /* do lookup with the subdissector table */ |
118 | 0 | (!dissector_try_uint(subdissector_table, pid, next_tvb, pinfo, tree))) { |
119 | 0 | call_data_dissector(next_tvb, pinfo, tree); |
120 | 0 | } |
121 | 0 | return tvb_captured_length(tvb); |
122 | 0 | } |
123 | | |
124 | | static void |
125 | | ieee802a_shutdown(void) |
126 | 0 | { |
127 | 0 | g_hash_table_destroy(oui_info_table); |
128 | 0 | } |
129 | | |
130 | | void |
131 | | proto_register_ieee802a(void) |
132 | 15 | { |
133 | 15 | static hf_register_info hf[] = { |
134 | 15 | { &hf_ieee802a_oui, |
135 | 15 | { "Organization Code", "ieee802a.oui", FT_UINT24, BASE_OUI, |
136 | 15 | NULL, 0x0, NULL, HFILL }}, |
137 | | |
138 | 15 | { &hf_ieee802a_pid, |
139 | 15 | { "Protocol ID", "ieee802a.pid", FT_UINT16, BASE_HEX, |
140 | 15 | NULL, 0x0, NULL, HFILL }} |
141 | 15 | }; |
142 | 15 | static int *ett[] = { |
143 | 15 | &ett_ieee802a, |
144 | 15 | }; |
145 | | |
146 | 15 | proto_ieee802a = proto_register_protocol("IEEE802a OUI Extended Ethertype", "IEEE802a", "ieee802a"); |
147 | 15 | proto_register_field_array(proto_ieee802a, hf, array_length(hf)); |
148 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
149 | 15 | register_shutdown_routine(ieee802a_shutdown); |
150 | | |
151 | 15 | ieee802a_handle = register_dissector("ieee802a", dissect_ieee802a, proto_ieee802a); |
152 | 15 | } |
153 | | |
154 | | static void |
155 | | register_hf(void *key _U_, void *value, void *user_data _U_) |
156 | 15 | { |
157 | 15 | oui_info_t *info = (oui_info_t *)value; |
158 | | |
159 | 15 | proto_register_field_array(proto_ieee802a, info->field_info, 1); |
160 | 15 | } |
161 | | |
162 | | void |
163 | | proto_reg_handoff_ieee802a(void) |
164 | 15 | { |
165 | 15 | dissector_add_uint("ethertype", ETHERTYPE_IEEE802_OUI_EXTENDED, |
166 | 15 | ieee802a_handle); |
167 | | |
168 | | /* |
169 | | * Register all the fields for PIDs for various OUIs. |
170 | | */ |
171 | 15 | if (oui_info_table != NULL) |
172 | 15 | g_hash_table_foreach(oui_info_table, register_hf, NULL); |
173 | 15 | } |
174 | | |
175 | | /* |
176 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
177 | | * |
178 | | * Local variables: |
179 | | * c-basic-offset: 8 |
180 | | * tab-width: 8 |
181 | | * indent-tabs-mode: t |
182 | | * End: |
183 | | * |
184 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
185 | | * :indentSize=8:tabSize=8:noTabs=false: |
186 | | */ |