/src/wireshark/epan/dissectors/packet-cl3.c
Line | Count | Source |
1 | | /* packet-cl3.c |
2 | | * Routines for CableLabs Layer-3 Protocol Dissection |
3 | | * Copyright 2019 Jon Dennis <j.dennis[at]cablelabs.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | * |
11 | | * Dissector for IEEE-Registered CableLabs EtherType 0xB4E3 |
12 | | * |
13 | | * IEEE EtherType List |
14 | | * http://standards-oui.ieee.org/ethertype/eth.txt |
15 | | * |
16 | | * CableLabs Specifications Can Be Found At: |
17 | | * https://www.cablelabs.com/specs |
18 | | * Note: As of writing this, the spec is in the process of being published. |
19 | | * Initially, this will be published under the Dual Channel Wi-Fi spec, |
20 | | * but may split off into its own spec in the future. |
21 | | * Eventually a direct link to the spec should be put here. |
22 | | */ |
23 | | |
24 | | #include "config.h" |
25 | | #include <epan/packet.h> |
26 | | #include <epan/expert.h> |
27 | | |
28 | | #include <epan/etypes.h> |
29 | | |
30 | | #include <wsutil/str_util.h> |
31 | | |
32 | | |
33 | | void proto_register_cl3(void); |
34 | | void proto_reg_handoff_cl3(void); |
35 | | |
36 | | static dissector_handle_t cl3_handle; |
37 | | |
38 | | /* persistent handles for this dissector */ |
39 | | static int proto_cl3; |
40 | | static dissector_table_t cl3_command_table; |
41 | | static int ett_cl3; |
42 | | static int hf_cl3_version; |
43 | | static int hf_cl3_headerlen; |
44 | | static int hf_cl3_subproto; |
45 | | static int hf_cl3_payload; |
46 | | static expert_field ei_cl3_badheaderlen; |
47 | | static expert_field ei_cl3_unsup_ver; |
48 | | |
49 | | |
50 | | /* Known CL3 (sub-)protocol type strings: */ |
51 | | static const value_string cl3_protocols[] = { |
52 | | {0x00DC, "Dual-Channel Wi-Fi Messaging" }, |
53 | | {0, NULL} |
54 | | }; |
55 | | |
56 | | |
57 | | /* called for each incoming framing matching the CL3 ethertype with a version number of 1: */ |
58 | | static void |
59 | | dissect_cl3_v1( |
60 | | tvbuff_t *tvb, |
61 | | packet_info *pinfo, |
62 | | proto_tree *tree, |
63 | | proto_item *ti, |
64 | | proto_tree *cl3_tree, |
65 | | uint16_t header_length |
66 | 1 | ) { |
67 | | |
68 | 1 | dissector_handle_t dh; |
69 | 1 | tvbuff_t *tvb_sub; |
70 | | |
71 | 1 | uint16_t subprotocol_id; |
72 | | |
73 | | /* ensure the header length is valid for version 1 */ |
74 | 1 | if (header_length != 4) { |
75 | 1 | expert_add_info(pinfo, ti, &ei_cl3_badheaderlen); |
76 | 1 | } |
77 | | |
78 | | /* parse the sub-protocol id */ |
79 | 1 | subprotocol_id = tvb_get_ntohs(tvb, 2); |
80 | | |
81 | | /* append the subprotocol id to the "packet summary view" fields */ |
82 | 1 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[Subprotocol 0x%04X]", (unsigned)subprotocol_id); |
83 | | |
84 | | /* add elements to the CL3 tree... |
85 | | CL3 version 1 fields: (pretty much just the sub protocol id) */ |
86 | 1 | proto_tree_add_uint(cl3_tree, hf_cl3_subproto, tvb, 2, 2, subprotocol_id); |
87 | | |
88 | | /* call CL (sub-)protocol dissector */ |
89 | 1 | dh = dissector_get_uint_handle(cl3_command_table, subprotocol_id); |
90 | 1 | if (dh != NULL) { |
91 | 0 | tvb_sub = tvb_new_subset_remaining(tvb, header_length); |
92 | 0 | call_dissector(dh, tvb_sub, pinfo, tree); |
93 | 0 | } |
94 | 1 | } |
95 | | |
96 | | /* called for each incoming framing matching the CL3 ethertype: */ |
97 | | static int |
98 | 4 | dissect_cl3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
99 | | |
100 | 4 | proto_item *ti; |
101 | 4 | proto_tree *cl3_tree; |
102 | | |
103 | 4 | uint16_t version; |
104 | 4 | uint16_t header_length; |
105 | 4 | uint32_t payload_length; |
106 | | |
107 | | /* parse the header fields */ |
108 | 4 | version = header_length = tvb_get_ntohs(tvb, 0); |
109 | 4 | version >>= 12; |
110 | 4 | header_length >>= 8; |
111 | 4 | header_length &= 0x0F; |
112 | 4 | header_length *= 4; |
113 | 4 | payload_length = tvb_captured_length(tvb) - header_length; |
114 | | |
115 | | /* setup the "packet summary view" fields */ |
116 | 4 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "CL3"); |
117 | 4 | col_clear(pinfo->cinfo, COL_INFO); |
118 | 4 | col_add_fstr(pinfo->cinfo, COL_INFO, "CableLabs Layer-3 Protocol (Ver %u)", (unsigned)version); |
119 | | |
120 | | /* create a tree node for us... */ |
121 | 4 | ti = proto_tree_add_protocol_format(tree, proto_cl3, tvb, 0, header_length, "CableLabs Layer-3 Protocol (CL3) Version %u", (unsigned)version); |
122 | 4 | cl3_tree = proto_item_add_subtree(ti, ett_cl3); |
123 | | |
124 | | /* CL3 version agnostic fields: (pretty much just the first byte; like ipv4, version + length) */ |
125 | 4 | proto_tree_add_item(cl3_tree, hf_cl3_version, tvb, 0, 1, ENC_NA); |
126 | 4 | proto_tree_add_uint_bits_format_value(cl3_tree, hf_cl3_headerlen, tvb, 0 + 4, 4, header_length, |
127 | 4 | ENC_BIG_ENDIAN, "%u bytes (%u)", header_length, header_length >> 2); |
128 | | |
129 | | /* validate the header length... */ |
130 | 4 | if ((header_length < 1) || (header_length > tvb_captured_length(tvb))) { |
131 | 3 | expert_add_info(pinfo, ti, &ei_cl3_badheaderlen); |
132 | 3 | } |
133 | | |
134 | | /* version-specific dissection... */ |
135 | 4 | switch (version) { |
136 | 1 | case 1: |
137 | 1 | dissect_cl3_v1(tvb, pinfo, tree, ti, cl3_tree, header_length); |
138 | 1 | break; |
139 | 3 | default: |
140 | 3 | expert_add_info(pinfo, ti, &ei_cl3_unsup_ver); |
141 | 3 | break; |
142 | 4 | } |
143 | | |
144 | | /* add a byte reference to the payload we are carrying */ |
145 | 4 | proto_tree_add_item(cl3_tree, hf_cl3_payload, tvb, header_length, payload_length, ENC_NA); |
146 | | |
147 | 4 | return tvb_captured_length(tvb); |
148 | 4 | } |
149 | | |
150 | | |
151 | | /* initializes this dissector */ |
152 | | void |
153 | 14 | proto_register_cl3(void) { |
154 | 14 | static hf_register_info hf[] = { |
155 | 14 | { &hf_cl3_version, |
156 | 14 | { "Version", "cl3.version", |
157 | 14 | FT_UINT8, BASE_DEC, NULL, 0xF0, |
158 | 14 | "The CableLabs layer-3 protocol version number", HFILL }}, |
159 | 14 | { &hf_cl3_headerlen, |
160 | 14 | { "Header Length", "cl3.headerlen", |
161 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
162 | 14 | "The length of the CableLabs layer-3 protocol header", HFILL }}, |
163 | 14 | { &hf_cl3_subproto, |
164 | 14 | { "Subprotocol", "cl3.subprotocol", |
165 | 14 | FT_UINT16, BASE_HEX, VALS(cl3_protocols), 0x0, |
166 | 14 | "The subprotocol number the CableLabs layer-3 protocol is carrying", HFILL }}, |
167 | 14 | { &hf_cl3_payload, |
168 | 14 | { "CL3 Payload", "cl3.payload", |
169 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
170 | 14 | "The payload carried by this CableLabs layer-3 protocol packet", HFILL}}, |
171 | 14 | }; |
172 | 14 | static int *ett[] = { |
173 | 14 | &ett_cl3, |
174 | 14 | }; |
175 | 14 | static ei_register_info ei[] = { |
176 | 14 | { &ei_cl3_badheaderlen, { "cl3.badheaderlen", PI_MALFORMED, PI_ERROR, "Bad Header Length", EXPFILL }}, |
177 | 14 | { &ei_cl3_unsup_ver, { "cl3.unsup_ver", PI_UNDECODED, PI_WARN, "Unknown protocol version", EXPFILL }}, |
178 | 14 | }; |
179 | | |
180 | 14 | expert_module_t* expert_cl3; |
181 | | |
182 | 14 | proto_cl3 = proto_register_protocol("CableLabs Layer 3 Protocol", "CL3", "cl3"); |
183 | | |
184 | 14 | proto_register_field_array(proto_cl3, hf, array_length(hf)); |
185 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
186 | 14 | expert_cl3 = expert_register_protocol(proto_cl3); |
187 | 14 | expert_register_field_array(expert_cl3, ei, array_length(ei)); |
188 | | |
189 | | /* register the dissector */ |
190 | 14 | cl3_handle = register_dissector("cl3", &dissect_cl3, proto_cl3); |
191 | | |
192 | | /* subdissector code... */ |
193 | 14 | cl3_command_table = register_dissector_table("cl3.subprotocol", "CableLabs Subprotocol", proto_cl3, FT_UINT16, BASE_DEC); |
194 | 14 | } |
195 | | |
196 | | /* hooks in our dissector to be called on matching ethertype */ |
197 | | void |
198 | 14 | proto_reg_handoff_cl3(void) { |
199 | 14 | dissector_add_uint("ethertype", ETHERTYPE_CABLELABS, cl3_handle); |
200 | 14 | } |
201 | | |
202 | | /* |
203 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
204 | | * |
205 | | * Local variables: |
206 | | * c-basic-offset: 2 |
207 | | * tab-width: 8 |
208 | | * indent-tabs-mode: nil |
209 | | * End: |
210 | | * |
211 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
212 | | * :indentSize=2:tabSize=8:noTabs=true: |
213 | | */ |