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
17 #include <epan/packet.h>
18 #include <epan/etypes.h>
19 #include <epan/expert.h>
21 #include <wsutil/array.h>
23 #include "packet-ieee1609dot2.h"
26 #define TRANSMITPW 0x04
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
[] = {
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 */
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" },
89 static const value_string wsmp_wave_information_elements_vals
[] = {
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 */
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 */
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" },
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.
137 dissect_wsmp_psid(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, uint32_t *psid
)
140 uint32_t psidLen
= 0;
142 oct
= tvb_get_uint8(tvb
, offset
);
145 if ((oct
& 0xF0) == 0xF0) {
146 proto_tree_add_expert(tree
, pinfo
, &ei_wsmp_psid_invalid
, tvb
, offset
, 1);
148 } else if ((oct
& 0xF0) == 0xE0) {
150 } else if ((oct
& 0xE0) == 0xC0) {
152 } else if ((oct
& 0xC0) == 0x80) {
154 } else if ((oct
& 0x80) == 0x00) {
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
);
175 /* 8.1.3 Length and Count field encoding*/
177 dissect_wsmp_length_and_count(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, int hf_id
, uint16_t* value
)
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) {
192 val
= tvb_get_ntohs(tvb
, offset
) & 0x3fff;
196 proto_tree_add_expert(tree
, pinfo
, &ei_wsmp_length_field_err
, tvb
, offset
, 1);
197 val
= tvb_get_ntohs(tvb
, offset
) & 0x3fff;
206 proto_tree_add_uint(tree
, hf_id
, tvb
, offset
, len
, val
);
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;
224 uint16_t count
, ie_len
, wsm_len
;
225 uint32_t tpid
, psid
= 0;
227 static int * const flags
[] = {
229 &hf_wsmp_N_header_opt_ind
,
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");
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
);
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
);
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
);
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
);
271 len_to_set
= offset
- ie_start
;
272 proto_item_set_len(item
, len_to_set
);
279 proto_tree_add_item_ret_uint(n_tree
, hf_wsmp_tpid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tpid
);
282 proto_item_set_end(n_tree_item
, tvb
, offset
);
286 t_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_wsmp_t_hdr
, &t_tree_item
, "WSMP-T-Header");
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
);
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
);
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
);
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 */
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
);
339 * Subtype |WSMP-NHeader | WSMP Version
342 oct
= tvb_get_uint8(tvb
, offset
);
343 version
= oct
& 0x07;
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
);
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
))
359 if (elemenId
== CHANNUM
)
361 elemenLen
= tvb_get_uint8(tvb
, offset
);
363 proto_tree_add_item(wsmp_tree
,
364 hf_wsmp_channel
, tvb
, offset
, elemenLen
, ENC_BIG_ENDIAN
);
367 else if (elemenId
== DATARATE
)
369 elemenLen
= tvb_get_uint8(tvb
, offset
);
371 proto_tree_add_item(wsmp_tree
,
372 hf_wsmp_rate
, tvb
, offset
, elemenLen
, ENC_BIG_ENDIAN
);
375 else if (elemenId
== TRANSMITPW
)
377 elemenLen
= tvb_get_uint8(tvb
, offset
);
379 proto_tree_add_item(wsmp_tree
,
380 hf_wsmp_txpower
, tvb
, offset
, elemenLen
, ENC_BIG_ENDIAN
);
383 elemenId
= tvb_get_uint8(tvb
, offset
);
386 proto_tree_add_item(wsmp_tree
,
387 hf_wsmp_WAVEid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
390 wsmlength
= tvb_get_ntohs( tvb
, offset
);
391 proto_tree_add_item(wsmp_tree
,
392 hf_wsmp_wsmlength
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
395 if (elemenId
== WSMP_S
)
401 msb
= tvb_get_uint8(tvb
, offset
+ supLen
);
405 proto_tree_add_item(wsmp_tree
,
406 hf_wsmp_WSMP_S_data
, tvb
, offset
, supLen
, ENC_BIG_ENDIAN
);
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
421 call_data_dissector(wsmdata_tvb
, pinfo
, wsmdata_tree
);
423 return tvb_captured_length(tvb
);
427 proto_register_wsmp(void)
429 static hf_register_info hf
[] = {
431 { "Version", "wsmp.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
434 { &hf_wsmp_var_len_det
,
435 { "Length", "wsmp.len.det",
436 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
440 { "PSID", "wsmp.psid", FT_UINT32
, BASE_HEX
, NULL
, 0x0,
444 { "Channel", "wsmp.channel", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
448 { "Data Rate", "wsmp.rate", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
452 { "Transmit Power", "wsmp.txpower", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
456 { "WAVE element id", "wsmp.WAVEid", FT_UINT8
, BASE_DEC
, VALS(wsmp_elemenid_names
), 0x0,
459 { &hf_wsmp_wsmlength
,
460 { "WSM Length", "wsmp.wsmlength", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
463 { &hf_wsmp_WSMP_S_data
,
464 { "WAVE Supplement Data", "wsmp.supplement", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
468 { "Subtype", "wsmp.subtype", FT_UINT8
, BASE_DEC
, VALS(wsmp_subtype_vals
), 0xF0,
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,
475 { &hf_wsmp_version_v3
,
476 { "Version", "wsmp.version_v3", FT_UINT8
, BASE_DEC
, NULL
, 0x07,
479 { &hf_wsmp_no_elements
,
480 { "Count", "wsmp.no_elements", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
484 { "WAVE IE", "wsmp.wave_ie", FT_UINT8
, BASE_DEC
, VALS(wsmp_wave_information_elements_vals
), 0x0,
487 { &hf_wsmp_wave_ie_len
,
488 { "Length", "wsmp.wave_ie_len", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
491 { &hf_wsmp_wave_ie_data
,
492 { "Data", "wsmp.wave_ie_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
496 { "TPID", "wsmp.tpid", FT_UINT8
, BASE_DEC
, VALS(wsmp_tpid_vals
), 0x0,
501 /* Setup protocol subtree array */
502 static int *ett
[] = {
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)",
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
);
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
547 * indent-tabs-mode: nil
550 * vi: set shiftwidth=4 tabstop=8 expandtab:
551 * :indentSize=4:tabSize=8:noTabs=true: