Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-wsmp.c
blobf08c4487c427481cb45887242fc96c6e53413476
1 /* packet-wsmp.c
2 * Routines for WAVE Short Message dissection (WSMP)
3 * Copyright 2013, Savari Networks (http://www.savarinetworks.com) (email: smooney@savarinetworks.com)
4 * Based on packet-wsmp.c implemented by
5 * Arada Systems (http://www.aradasystems.com) (email: siva@aradasystems.com)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 * Ref IEEE 1609.3
15 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/etypes.h>
19 #include <epan/expert.h>
20 #include <epan/tfs.h>
21 #include <wsutil/array.h>
23 #include "packet-ieee1609dot2.h"
25 /* elemenID Types */
26 #define TRANSMITPW 0x04
27 #define CHANNUM 0x0F
28 #define DATARATE 0x10
29 #define WSMP 0x80
30 #define WSMP_S 0x81
31 #define WSMP_I 0x82
33 void proto_register_wsmp(void);
34 void proto_reg_handoff_wsmp(void);
36 static dissector_handle_t wsmp_handle;
38 static const value_string wsmp_elemenid_names[] = {
39 { 0x80, "WSMP" },
40 { 0x81, "WSMP-S" },
41 { 0x82, "WSMP-I" },
42 { 0, NULL }
46 /* Initialize the protocol and registered fields */
47 static int proto_wsmp;
48 static int hf_wsmp_version;
49 static int hf_wsmp_var_len_det;
50 static int hf_wsmp_psid;
51 static int hf_wsmp_rate;
52 static int hf_wsmp_channel;
53 static int hf_wsmp_txpower;
54 static int hf_wsmp_WAVEid;
55 static int hf_wsmp_wsmlength;
56 static int hf_wsmp_WSMP_S_data;
58 static int hf_wsmp_subtype;
59 static int hf_wsmp_N_header_opt_ind;
60 static int hf_wsmp_version_v3;
61 static int hf_wsmp_no_elements;
62 static int hf_wsmp_wave_ie;
63 static int hf_wsmp_wave_ie_len;
64 static int hf_wsmp_wave_ie_data;
65 static int hf_wsmp_tpid;
67 /* Initialize the subtree pointers */
68 static int ett_wsmp;
69 static int ett_wsmdata;
70 static int ett_wsmp_n_hdr;
71 static int ett_wsmp_t_hdr;
72 static int ett_wsmp_ie_ext;
73 static int ett_wsmp_ie;
75 static expert_field ei_wsmp_length_field_err;
76 static expert_field ei_wsmp_psid_invalid;
78 dissector_handle_t IEEE1609dot2_handle;
81 static const value_string wsmp_subtype_vals[] = {
82 { 0x0, "Null-networking protocol" },
83 { 0x1, "ITS station-internal forwarding" },
84 { 0x2, "N-hop forwarding" },
85 { 0x3, "Enables the features of GeoNetworking" },
86 { 0, NULL }
89 static const value_string wsmp_wave_information_elements_vals[] = {
90 { 0, "Reserved" },
91 { 1, "Reserved" },
92 { 2, "Reserved" },
93 { 3, "Reserved" },
94 { 4, "Transmit Power Used" }, /* WSMP - N - Header 8.3.4.4 */
95 { 5, "2D Location" }, /* WSA header 8.2.2.6 */
96 { 6, "3D Location" }, /* WSA header 8.2.2.6 */
97 { 7, "Advertiser Identifier" }, /* WSA header 8.2.2.6 */
98 { 8, "Provider Service Context" }, /* WSA Service Info 8.2.3.5 */
99 { 9, "IPv6 Address" }, /* WSA Service Info 8.2.3.5 */
100 { 10, "Service Por" }, /* WSA Service Info 8.2.3.5 */
101 { 11, "Provider MAC Address" }, /* WSA Service Info 8.2.3.5 */
102 { 12, "EDCA Parameter Set" }, /* WSA Channel Info 8.2.4.8 */
103 { 13, "Secondary DNS" }, /* WSA WRA 8.2.5.7 */
104 { 14, "Gateway MAC Address" }, /* WSA WRA 8.2.5.7 */
105 { 15, "Channel Number" }, /* WSMP - N - Header 8.3.4.2 */
106 { 16, "Data Rate" }, /* WSMP - N - Header 8.3.4.3 */
107 { 17, "Repeat Rate" }, /* WSA header 8.2.2.6 */
108 { 18, "Reserved" },
109 { 19, "RCPI Threshold" }, /* WSA Service Info 8.2.3.5 */
110 { 20, "WSA Count Threshold" }, /* WSA Service Info 8.2.3.5 */
111 { 21, "Channel Access" }, /* WSA Channel Info 8.2.4.8 */
112 { 22, "WSA Count Threshold Interval" }, /* WSA Service Info 8.2.3.5 */
113 { 23, "Channel Load" }, /* WSMP-N-Header 8.3.4.5 */
114 { 0, NULL }
117 static const value_string wsmp_tpid_vals[] = {
118 { 0, "The Address Info field contains a PSID and a WAVE Information Element Extension field is not present" },
119 { 1, "The Address Info field contains a PSID and a WAVE Information Element Extension field is present" },
120 { 2, "The Address Info field contains source and destination ITS port numbers and a WAVE Information Element Extension field is not present" },
121 { 3, "The Address Info field contains source and destination ITS port numbers and a WAVE Information Element Extension field is present" },
122 { 4, "LPP mode and a WAVE Information Element Extension field is not present" },
123 { 5, "LPP mode and a WAVE Information Element Extension field is present" },
124 { 0, NULL }
128 4.1.2 P-encoding of PSIDs
129 This standard defines a compact encoding for PSID referred to as p-encoding. Octets are numbered from the
130 left starting at zero (Octet 0). The length of the PSID is indicated by Octet 0, where the position of the first
131 zero-value bit in descending order of bit significance in the octet indicates the length in octets of the p?encoded
132 PSID. Using p-encoding, a binary "0" in the most-significant bit indicates a one-octet PSID; a binary "10"
133 in the two most-significant bits indicates a two-octet PSID; a binary "110" in the three most-significant bits
134 indicates a three-octet PSID; and a binary "1110" in the four most-significant bits indicates a four-octet PSID.
136 static int
137 dissect_wsmp_psid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, uint32_t *psid)
139 uint8_t oct;
140 uint32_t psidLen = 0;
142 oct = tvb_get_uint8(tvb, offset);
143 *psid = 0;
145 if ((oct & 0xF0) == 0xF0) {
146 proto_tree_add_expert(tree, pinfo, &ei_wsmp_psid_invalid, tvb, offset, 1);
147 return offset + 1;
148 } else if ((oct & 0xF0) == 0xE0) {
149 psidLen = 4;
150 } else if ((oct & 0xE0) == 0xC0) {
151 psidLen = 3;
152 } else if ((oct & 0xC0) == 0x80) {
153 psidLen = 2;
154 } else if ((oct & 0x80) == 0x00) {
155 psidLen = 1;
158 if (psidLen == 1)
159 *psid = oct;
160 else if (psidLen == 2)
161 *psid = (tvb_get_ntohs(tvb, offset) & ~0x8000) + 0x80;
162 else if (psidLen == 3)
163 *psid = (tvb_get_ntoh24(tvb, offset) & ~0xc00000) + 0x4080;
164 else if (psidLen == 4)
165 *psid = (tvb_get_ntohl(tvb, offset) & ~0xe0000000) + 0x204080;
167 proto_tree_add_bits_item(tree, hf_wsmp_var_len_det, tvb, offset << 3, psidLen, ENC_NA);
168 proto_tree_add_uint_bits_format_value(tree, hf_wsmp_psid, tvb, (offset << 3) + psidLen,
169 (psidLen << 3) - psidLen,*psid,ENC_BIG_ENDIAN,"%s(%u)", val64_to_str_const(*psid, ieee1609dot2_Psid_vals, "Unknown"), *psid);
170 offset += psidLen;
172 return offset;
175 /* 8.1.3 Length and Count field encoding*/
176 static int
177 dissect_wsmp_length_and_count(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int hf_id, uint16_t* value)
179 uint8_t oct, len;
180 uint16_t val;
181 /* For values in the range of 0 through 127, Length and Count values
182 * are represented in a single-octet encoded as an unsigned integer. For values in the range 128 through 16
183 * 383, values are represented as two octets encoded as follows. If the most significant bit of the field is 0b0,
184 * then this indicates a one-octet Length or Count field. If the two most significant bits of the field are 0b10,
185 * the Length or Count field is a two-octet field, with the remaining 14 bits representing the value encoded as
186 * an unsigned integer.*/
188 oct = tvb_get_uint8(tvb, offset);
189 if ((oct & 0x80) == 0x80) {
190 if ((oct & 0xc0) == 0x80) {
191 /* Two bytes */
192 val = tvb_get_ntohs(tvb, offset) & 0x3fff;
193 len = 2;
194 } else {
195 /* Error */
196 proto_tree_add_expert(tree, pinfo, &ei_wsmp_length_field_err, tvb, offset, 1);
197 val = tvb_get_ntohs(tvb, offset) & 0x3fff;
198 len = 2;
200 }else{
201 /* One byte */
202 val = oct;
203 len = 1;
206 proto_tree_add_uint(tree, hf_id, tvb, offset, len, val);
207 offset += len;
209 if (value){
210 *value = val;
213 return offset;
216 static int
217 dissect_wsmp_v3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint8_t oct)
219 proto_tree *sub_tree, *n_tree, *t_tree, *data_tree;
220 proto_item *item, *n_tree_item, *t_tree_item;
221 int offset = 0, ie_start, len_to_set;
222 uint8_t header_opt_ind = (oct & 0x08) >> 3;
223 uint8_t ie;
224 uint16_t count, ie_len, wsm_len;
225 uint32_t tpid, psid = 0;
227 static int * const flags[] = {
228 &hf_wsmp_subtype,
229 &hf_wsmp_N_header_opt_ind,
230 &hf_wsmp_version_v3,
231 NULL
234 /* 8.3.2 WSMP Network Header (WSMP-N-Header) */
236 n_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_wsmp_n_hdr, &n_tree_item, "WSMP-N-Header");
237 /* In Version 3
238 * B7 B4 B3 B2 B0 | Variable | 1 octet
239 * Subtype |WSMP-NHeader | WSMP Version | WAVE Information Element Extension | TPID
240 * | Option Indicator | | |
243 proto_tree_add_bitmask_list(n_tree, tvb, offset, 1, flags, ENC_BIG_ENDIAN);
244 offset++;
246 /* WAVE Information Element Extension */
247 if (header_opt_ind) {
248 sub_tree = proto_tree_add_subtree(n_tree, tvb, offset, -1, ett_wsmp_ie_ext, &item, "WAVE Information Element Extension");
249 /* Figure 14 WAVE Information Element Extension */
250 /* 8.1.3 Length and Count field encoding*/
251 /* Count( Number of WAVE Information Elements )*/
252 offset = dissect_wsmp_length_and_count(tvb, pinfo, sub_tree, offset, hf_wsmp_no_elements, &count);
254 while (count) {
255 proto_tree* ie_tree;
256 ie_start = offset;
257 /* WAVE Element ID 1 octet*/
258 ie = tvb_get_uint8(tvb, offset);
259 ie_tree = proto_tree_add_subtree_format(sub_tree, tvb, offset, -1, ett_wsmp_ie, &item, "%s",
260 val_to_str_const(ie, wsmp_wave_information_elements_vals, "Unknown"));
262 proto_tree_add_item(ie_tree, hf_wsmp_wave_ie, tvb, offset, 1, ENC_BIG_ENDIAN);
263 offset++;
265 /* Length */
266 offset = dissect_wsmp_length_and_count(tvb, pinfo, ie_tree, offset, hf_wsmp_wave_ie_len, &ie_len);
268 proto_tree_add_item(ie_tree, hf_wsmp_wave_ie_data, tvb, offset, ie_len, ENC_NA);
269 offset += ie_len;
271 len_to_set = offset - ie_start;
272 proto_item_set_len(item, len_to_set);
274 count--;
278 /* TPID */
279 proto_tree_add_item_ret_uint(n_tree, hf_wsmp_tpid, tvb, offset, 1, ENC_BIG_ENDIAN, &tpid);
280 offset++;
282 proto_item_set_end(n_tree_item, tvb, offset);
285 /* WSMP-T-Header */
286 t_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_wsmp_t_hdr, &t_tree_item, "WSMP-T-Header");
287 switch (tpid) {
288 case 0:
289 /* The Address Info field contains a PSID and a WAVE Information Element Extension field is not present.*/
290 offset = dissect_wsmp_psid(tvb, pinfo, t_tree, offset, &psid);
291 break;
292 default:
293 break;
296 /* WSM Length */
297 offset = dissect_wsmp_length_and_count(tvb, pinfo, t_tree, offset, hf_wsmp_wave_ie_len, &wsm_len);
299 proto_item_set_end(t_tree_item, tvb, offset);
302 /* WSM Data */
303 data_tree = proto_tree_add_subtree(tree, tvb, offset, wsm_len, ett_wsmdata, NULL, "Wave Short Message");
305 if((psid == (uint32_t)psid_vehicle_to_vehicle_safety_and_awarenesss) && (IEEE1609dot2_handle)){
306 ieee1609dot2_set_next_default_psid(pinfo, psid);
307 tvbuff_t * tvb_new = tvb_new_subset_remaining(tvb, offset);
308 call_dissector(IEEE1609dot2_handle, tvb_new, pinfo, data_tree);
309 } else if ((psid == (uint32_t)psid_intersection_safety_and_awareness) && (IEEE1609dot2_handle)) {
310 ieee1609dot2_set_next_default_psid(pinfo, psid);
311 tvbuff_t * tvb_new = tvb_new_subset_remaining(tvb, offset);
312 call_dissector(IEEE1609dot2_handle, tvb_new, pinfo, data_tree);
315 return tvb_captured_length(tvb);
317 static int
318 dissect_wsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
320 /* Set up structures needed to add the protocol subtree and manage it */
321 proto_item *ti;
322 proto_tree *wsmp_tree, *wsmdata_tree;
323 tvbuff_t *wsmdata_tvb;
324 uint16_t wsmlength, offset = 0;
325 uint32_t psid, supLen;
326 uint8_t elemenId, elemenLen, msb, oct, version;
328 /* Make entries in Protocol column and Info column on summary display */
329 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSMP");
331 col_set_str(pinfo->cinfo, COL_INFO, "WAVE Short Message Protocol IEEE P1609.3");
333 /* create display subtree for the protocol */
334 ti = proto_tree_add_item(tree, proto_wsmp, tvb, 0, -1, ENC_NA);
335 wsmp_tree = proto_item_add_subtree(ti, ett_wsmp);
337 /* In Version 3
338 * B7 B4 B3 B2 B0
339 * Subtype |WSMP-NHeader | WSMP Version
340 * | Option Indicator
342 oct = tvb_get_uint8(tvb, offset);
343 version = oct & 0x07;
344 if (version == 3) {
345 /* Version 3 */
346 return dissect_wsmp_v3(tvb, pinfo, wsmp_tree, oct);
349 proto_tree_add_item(wsmp_tree, hf_wsmp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
350 offset++;
352 offset = dissect_wsmp_psid(tvb, pinfo, wsmp_tree, offset, &psid);
354 /* TLV decoder that does not display the T and L elements */
355 elemenId = tvb_get_uint8(tvb, offset);
356 while ((elemenId != WSMP) && (elemenId != WSMP_S) && (elemenId != WSMP_I))
358 offset++;
359 if (elemenId == CHANNUM)
361 elemenLen = tvb_get_uint8(tvb, offset);
362 offset++;
363 proto_tree_add_item(wsmp_tree,
364 hf_wsmp_channel, tvb, offset, elemenLen, ENC_BIG_ENDIAN);
365 offset += elemenLen;
367 else if (elemenId == DATARATE)
369 elemenLen = tvb_get_uint8(tvb, offset);
370 offset++;
371 proto_tree_add_item(wsmp_tree,
372 hf_wsmp_rate, tvb, offset, elemenLen, ENC_BIG_ENDIAN);
373 offset += elemenLen;
375 else if (elemenId == TRANSMITPW)
377 elemenLen = tvb_get_uint8(tvb, offset);
378 offset++;
379 proto_tree_add_item(wsmp_tree,
380 hf_wsmp_txpower, tvb, offset, elemenLen, ENC_BIG_ENDIAN);
381 offset += elemenLen;
383 elemenId = tvb_get_uint8(tvb, offset);
386 proto_tree_add_item(wsmp_tree,
387 hf_wsmp_WAVEid, tvb, offset, 1, ENC_BIG_ENDIAN);
388 offset++;
390 wsmlength = tvb_get_ntohs( tvb, offset);
391 proto_tree_add_item(wsmp_tree,
392 hf_wsmp_wsmlength, tvb, offset, 2, ENC_BIG_ENDIAN);
393 offset += 2;
395 if (elemenId == WSMP_S)
397 msb = 1;
398 supLen = 0;
399 while (msb)
401 msb = tvb_get_uint8(tvb, offset + supLen);
402 msb = msb & 0x80;
403 supLen++;
405 proto_tree_add_item(wsmp_tree,
406 hf_wsmp_WSMP_S_data, tvb, offset, supLen, ENC_BIG_ENDIAN);
407 wsmlength -= supLen;
408 offset += supLen;
411 wsmdata_tree = proto_tree_add_subtree(wsmp_tree, tvb, offset, wsmlength,
412 ett_wsmdata, NULL, "Wave Short Message");
414 wsmdata_tvb = tvb_new_subset_length(tvb, offset, wsmlength);
416 /* TODO: Branch on the application context and display accordingly
417 * Default: call the data dissector
419 if (psid == 0x4070)
421 call_data_dissector(wsmdata_tvb, pinfo, wsmdata_tree);
423 return tvb_captured_length(tvb);
426 void
427 proto_register_wsmp(void)
429 static hf_register_info hf[] = {
430 { &hf_wsmp_version,
431 { "Version", "wsmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
432 NULL, HFILL }},
434 { &hf_wsmp_var_len_det,
435 { "Length", "wsmp.len.det",
436 FT_UINT8, BASE_HEX, NULL, 0x0,
437 NULL, HFILL }},
439 { &hf_wsmp_psid,
440 { "PSID", "wsmp.psid", FT_UINT32, BASE_HEX, NULL, 0x0,
441 NULL, HFILL }},
443 { &hf_wsmp_channel,
444 { "Channel", "wsmp.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
445 NULL, HFILL }},
447 { &hf_wsmp_rate,
448 { "Data Rate", "wsmp.rate", FT_UINT8, BASE_DEC, NULL, 0x0,
449 NULL, HFILL }},
451 { &hf_wsmp_txpower,
452 { "Transmit Power", "wsmp.txpower", FT_UINT8, BASE_DEC, NULL, 0x0,
453 NULL, HFILL }},
455 { &hf_wsmp_WAVEid,
456 { "WAVE element id", "wsmp.WAVEid", FT_UINT8, BASE_DEC, VALS(wsmp_elemenid_names), 0x0,
457 NULL, HFILL }},
459 { &hf_wsmp_wsmlength,
460 { "WSM Length", "wsmp.wsmlength", FT_UINT16, BASE_DEC, NULL, 0x0,
461 NULL, HFILL }},
463 { &hf_wsmp_WSMP_S_data,
464 { "WAVE Supplement Data", "wsmp.supplement", FT_UINT8, BASE_HEX, NULL, 0x0,
465 NULL, HFILL }},
467 { &hf_wsmp_subtype,
468 { "Subtype", "wsmp.subtype", FT_UINT8, BASE_DEC, VALS(wsmp_subtype_vals), 0xF0,
469 NULL, HFILL }},
471 { &hf_wsmp_N_header_opt_ind,
472 { "WSMP-NHeader Option Indicator(WAVE Information Element Extension)", "wsmp.N_header_opt_ind", FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x08,
473 NULL, HFILL }},
475 { &hf_wsmp_version_v3,
476 { "Version", "wsmp.version_v3", FT_UINT8, BASE_DEC, NULL, 0x07,
477 NULL, HFILL }},
479 { &hf_wsmp_no_elements,
480 { "Count", "wsmp.no_elements", FT_UINT16, BASE_DEC, NULL, 0x0,
481 NULL, HFILL }},
483 { &hf_wsmp_wave_ie,
484 { "WAVE IE", "wsmp.wave_ie", FT_UINT8, BASE_DEC, VALS(wsmp_wave_information_elements_vals), 0x0,
485 NULL, HFILL }},
487 { &hf_wsmp_wave_ie_len,
488 { "Length", "wsmp.wave_ie_len", FT_UINT16, BASE_DEC, NULL, 0x0,
489 NULL, HFILL }},
491 { &hf_wsmp_wave_ie_data,
492 { "Data", "wsmp.wave_ie_data", FT_BYTES, BASE_NONE, NULL, 0x0,
493 NULL, HFILL }},
495 { &hf_wsmp_tpid,
496 { "TPID", "wsmp.tpid", FT_UINT8, BASE_DEC, VALS(wsmp_tpid_vals), 0x0,
497 NULL, HFILL }},
501 /* Setup protocol subtree array */
502 static int *ett[] = {
503 &ett_wsmp,
504 &ett_wsmdata,
505 &ett_wsmp_n_hdr,
506 &ett_wsmp_t_hdr,
507 &ett_wsmp_ie_ext,
508 &ett_wsmp_ie,
511 static ei_register_info ei[] = {
512 { &ei_wsmp_length_field_err, { "wsmp.length_field_err", PI_PROTOCOL, PI_ERROR,
513 "Length field wrongly encoded, b6 not 0. The rest of the dissection is suspect", EXPFILL }},
514 { &ei_wsmp_psid_invalid, { "wsmp.psid.invalid", PI_PROTOCOL, PI_ERROR, "Invalid PSID", EXPFILL }},
517 expert_module_t* expert_wsmp;
519 /* Register the protocol name and description */
520 proto_wsmp = proto_register_protocol("Wave Short Message Protocol(IEEE P1609.3)",
521 "WSMP", "wsmp");
523 /* Required function calls to register the header fields and subtrees used */
524 proto_register_field_array(proto_wsmp, hf, array_length(hf));
525 proto_register_subtree_array(ett, array_length(ett));
526 expert_wsmp = expert_register_protocol(proto_wsmp);
527 expert_register_field_array(expert_wsmp, ei, array_length(ei));
529 /* Register the dissector handle */
530 wsmp_handle = register_dissector("wsmp", dissect_wsmp, proto_wsmp);
533 void
534 proto_reg_handoff_wsmp(void)
536 dissector_add_uint("ethertype", ETHERTYPE_WSMP, wsmp_handle);
538 IEEE1609dot2_handle = find_dissector_add_dependency("ieee1609dot2.data", proto_wsmp);
542 * Editor modelines - https://www.wireshark.org/tools/modelines.html
544 * Local variables:
545 * c-basic-offset: 4
546 * tab-width: 8
547 * indent-tabs-mode: nil
548 * End:
550 * vi: set shiftwidth=4 tabstop=8 expandtab:
551 * :indentSize=4:tabSize=8:noTabs=true: