2 * Owen Kirby <osk@exegin.com>
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include <epan/packet.h>
14 #include "packet-tcp.h"
16 /* Default SCOP Port numbers. */
17 #define SCOP_DEFAULT_PORT_RANGE "17755-17756"
19 void proto_register_scop(void);
21 /* Structure to contain information from the SCoP packet. */
31 /* Header definitions for use with the TCP transport layer. */
32 #define SCOP_HEADER_LENGTH 4
33 #define SCOP_LENGTH_OFFSET 2
35 /* SCoP Transport Types */
36 #define SCOP_TRANSPORT_UDP 1
37 #define SCOP_TRANSPORT_TCP 2
38 #define SCOP_TRANSPORT_UDP_CCM 129
39 #define SCOP_TRANSPORT_TCP_CCM 130
40 #define SCOP_TRANSPORT_TCP_SSL 131
42 /* Service Identifier Field */
43 #define SCOP_SERVICE_SCOP 0x00
44 #define SCOP_SERVICE_BRIDGE 0x01
45 #define SCOP_SERVICE_GATEWAY 0x02
47 /* SCoP Command Values */
48 #define SCOP_CMD_HELLO 0x00
49 #define SCOP_CMD_HELLO_RESP 0x01
50 #define SCOP_CMD_HELLO_ACK 0x02
51 #define SCOP_CMD_GOODBYE 0x04
52 #define SCOP_CMD_GOODBYE_RESP 0x05
53 #define SCOP_CMD_KEEPALIVE_PING 0x06
54 #define SCOP_CMD_KEEPALIVE_PONG 0x07
56 /* Bridge Command type values. */
57 #define SCOP_BRIDGE_CMD 0x00
58 #define SCOP_BRIDGE_MSG 0x01
60 /* Function declarations */
61 void proto_reg_handoff_scop(void);
63 static void dissect_scop_zip (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
64 static void dissect_scop_bridge (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
66 static unsigned get_scop_length(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data
);
68 /* Initialize protocol and registered fields */
69 static int proto_scop
;
70 static int hf_scop_transport
;
71 static int hf_scop_version
;
72 static int hf_scop_length
;
73 static int hf_scop_service
;
74 static int hf_scop_type
;
75 static int hf_scop_status
;
79 static const value_string scop_transports
[] = {
80 { SCOP_TRANSPORT_UDP
, "UDP Mode 1" },
81 { SCOP_TRANSPORT_TCP
, "TCP Mode 2" },
82 { SCOP_TRANSPORT_UDP_CCM
, "UDP Mode 1 with CCM* Security" },
83 { SCOP_TRANSPORT_TCP_CCM
, "TCP Mode 2 with CCM* Security" },
84 { SCOP_TRANSPORT_TCP_SSL
, "TCP Mode 3 with SSL/TSL Tunnel" },
88 static const value_string scop_types
[] = {
89 { SCOP_CMD_HELLO
, "Hello" },
90 { SCOP_CMD_HELLO_RESP
, "Hello Response" },
91 { SCOP_CMD_HELLO_ACK
, "Hello Acknowledgment" },
92 { SCOP_CMD_GOODBYE
, "Goodbye" },
93 { SCOP_CMD_GOODBYE_RESP
, "Goodbye Response" },
94 { SCOP_CMD_KEEPALIVE_PING
, "Keep Alive Ping" },
95 { SCOP_CMD_KEEPALIVE_PONG
, "Keep Alive Pong" },
99 static const value_string scop_services
[] = {
100 { SCOP_SERVICE_SCOP
, "SCoP" },
101 { SCOP_SERVICE_BRIDGE
, "Bridge" },
102 { SCOP_SERVICE_GATEWAY
, "Gateway" },
106 /* Dissector handle */
107 static dissector_handle_t ieee802154_handle
;
108 static dissector_handle_t scop_udp_handle
;
109 static dissector_handle_t scop_tcp_handle
;
112 /*FUNCTION:------------------------------------------------------
116 * ZigBee SCoP packet dissection routine for Wireshark.
118 * tvbuff_t *tvb - pointer to buffer containing raw packet.
119 * packet_info *pinfo - pointer to packet information fields
120 * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
123 *---------------------------------------------------------------
126 dissect_scop(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
129 proto_item
*proto_root
;
130 proto_tree
*scop_tree
;
135 memset(&packet
, 0, sizeof(packet
));
137 /* Set the protocol name. */
138 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCoP");
140 /* Clear the info column. */
141 col_clear(pinfo
->cinfo
, COL_INFO
);
143 /* Create the protocol display tree. */
144 proto_root
= proto_tree_add_protocol_format(tree
, proto_scop
, tvb
, 0, tvb_captured_length(tvb
),
146 scop_tree
= proto_item_add_subtree(proto_root
, ett_scop
);
148 /* Extract the SCoP Transport type. */
149 packet
.transport
= tvb_get_uint8(tvb
, offset
);
150 proto_tree_add_uint(scop_tree
, hf_scop_transport
, tvb
, offset
, 1, packet
.transport
);
153 /* Extract the SCoP Version. */
154 packet
.version
= tvb_get_uint8(tvb
, offset
);
155 proto_tree_add_uint(scop_tree
, hf_scop_version
, tvb
, offset
, 1, packet
.version
);
158 /* Extract the SCoP Packet length. */
159 packet
.length
= tvb_get_ntohs(tvb
, offset
);
160 proto_tree_add_uint(scop_tree
, hf_scop_length
, tvb
, offset
, 2, packet
.length
);
163 if ( (packet
.transport
== SCOP_TRANSPORT_UDP_CCM
)
164 || (packet
.transport
== SCOP_TRANSPORT_TCP_CCM
)) {
165 /* Decryption Failed. */
170 /* Extract the service type. */
171 packet
.service
= tvb_get_uint8(next_tvb
, offset
);
172 proto_tree_add_uint(scop_tree
, hf_scop_service
, next_tvb
, offset
, 1, packet
.service
);
175 /* Call the appropriate helper routine to dissect based on the service type. */
176 switch (packet
.service
) {
177 case SCOP_SERVICE_SCOP
:
178 dissect_scop_zip(tvb_new_subset_remaining(next_tvb
, offset
), pinfo
, scop_tree
);
180 case SCOP_SERVICE_BRIDGE
:
181 dissect_scop_bridge(tvb_new_subset_remaining(next_tvb
, offset
), pinfo
, scop_tree
);
183 case SCOP_SERVICE_GATEWAY
:
184 /* Nothing yet defined for the gateway. Fall-Through. */
186 /* Unknown Service Type. */
187 call_data_dissector(tvb_new_subset_remaining(next_tvb
, offset
), pinfo
, tree
);
191 return tvb_captured_length(tvb
);
192 } /* dissect_scop() */
194 /*FUNCTION:------------------------------------------------------
198 * Returns the length of a SCoP packet. For use with the TCP
201 * packet_info *pinfo - pointer to packet information fields
202 * tvbuff_t *tvb - pointer to buffer containing the packet.
203 * int offset - beginning of packet.
205 * unsigned - Length of SCoP packet
206 *---------------------------------------------------------------
209 get_scop_length(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
211 /* Byte 0: Protocol Type.
212 * Byte 1: Protocol Version.
213 * Bytes 2-3: Packet Length (network order).
215 return tvb_get_ntohs(tvb
, offset
+ SCOP_LENGTH_OFFSET
);
216 } /* get_scop_length */
218 /*FUNCTION:------------------------------------------------------
222 * ZigBee SCoP packet dissection routine for Wireshark.
223 * for use with TCP ports.
225 * tvbuff_t *tvb - pointer to buffer containing raw packet.
226 * packet_info *pinfo - pointer to packet information fields
227 * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
230 *---------------------------------------------------------------
233 dissect_scop_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
235 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, SCOP_HEADER_LENGTH
, get_scop_length
, dissect_scop
, data
);
236 return tvb_captured_length(tvb
);
237 } /* dissect_scop_tcp */
240 /*FUNCTION:------------------------------------------------------
244 * Intermediate dissector for the SCoP service type.
246 * tvbuff_t *tvb - pointer to buffer containing raw packet.
247 * packet_info *pinfo - pointer to packet information fields
248 * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
251 *---------------------------------------------------------------
254 dissect_scop_zip(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
257 uint8_t type
= tvb_get_uint8(tvb
, offset
);
260 /* Display the Packet type*/
261 proto_tree_add_uint(tree
, hf_scop_type
, tvb
, offset
, 1, type
);
262 proto_item_append_text(tree
, ", %s", val_to_str_const(type
, scop_types
, "Reserved Type"));
263 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(type
, scop_types
, "Reserved Type"));
266 if (type
== SCOP_CMD_HELLO_RESP
) {
267 status
= tvb_get_ntohs(tvb
, 1);
268 proto_tree_add_uint_format_value(tree
, hf_scop_status
, tvb
, offset
, 2, status
, "%s", (status
==0x0000)?"Success":"Failure");
272 /* If there are any bytes left over, pass them to the data dissector. */
273 if (offset
< tvb_reported_length(tvb
)) {
274 tvbuff_t
*payload_tvb
= tvb_new_subset_remaining(tvb
, offset
);
275 proto_tree
*root
= proto_tree_get_root(tree
);
276 call_data_dissector(payload_tvb
, pinfo
, root
);
278 } /* dissect_scop_zip() */
280 /*FUNCTION:------------------------------------------------------
282 * dissect_scop_bridge
284 * Intermediate dissector for the Bridge service type.
286 * tvbuff_t *tvb - pointer to buffer containing raw packet.
287 * packet_info *pinfo - pointer to packet information fields
288 * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
291 *---------------------------------------------------------------
294 dissect_scop_bridge(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
296 call_dissector(ieee802154_handle
, tvb
, pinfo
, proto_tree_get_root(tree
));
297 } /* dissect_scop_bridge() */
299 /*FUNCTION:------------------------------------------------------
301 * proto_register_scop
303 * SCoP protocol registration.
308 *---------------------------------------------------------------
310 void proto_register_scop(void)
312 static hf_register_info hf
[] = {
313 { &hf_scop_transport
,
314 { "Transport Type", "scop.transport", FT_UINT8
, BASE_DEC
, VALS(scop_transports
), 0x0,
315 "The type of transport used.", HFILL
}},
318 { "Version", "scop.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
319 "The version of the sniffer.", HFILL
}},
322 { "Length", "scop.length", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
326 { "Service Identifier", "scop.service", FT_UINT8
, BASE_DEC
, VALS(scop_services
), 0x0,
330 { "Packet Type", "scop.type", FT_UINT8
, BASE_DEC
, VALS(scop_types
), 0x0,
331 "Service-specific packet type.", HFILL
}},
334 { "Status", "scop.status", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
335 "Status of the SCoP Command.", HFILL
}}
338 static int *ett
[] = {
342 /* Register protocol name and description. */
343 proto_scop
= proto_register_protocol("ZigBee SCoP", "SCoP", "scop");
345 /* Register header fields and subtrees. */
346 proto_register_field_array(proto_scop
, hf
, array_length(hf
));
347 proto_register_subtree_array(ett
, array_length(ett
));
349 /* Register dissector with Wireshark. */
350 scop_udp_handle
= register_dissector("scop.udp", dissect_scop
, proto_scop
);
351 scop_tcp_handle
= register_dissector("scop.tcp", dissect_scop_tcp
, proto_scop
);
352 } /* proto_register_scop() */
354 /*FUNCTION:------------------------------------------------------
356 * proto_reg_handoff_scop
358 * Registers the zigbee dissector with Wireshark.
359 * Will be called every time 'apply' is pressed in the preferences menu.
364 *---------------------------------------------------------------
366 void proto_reg_handoff_scop(void)
368 ieee802154_handle
= find_dissector_add_dependency("wpan_nofcs", proto_scop
);
370 dissector_add_uint_range_with_preference("udp.port", SCOP_DEFAULT_PORT_RANGE
, scop_udp_handle
);
371 dissector_add_uint_range_with_preference("tcp.port", SCOP_DEFAULT_PORT_RANGE
, scop_tcp_handle
);
375 * Editor modelines - https://www.wireshark.org/tools/modelines.html
380 * indent-tabs-mode: nil
383 * vi: set shiftwidth=4 tabstop=8 expandtab:
384 * :indentSize=4:tabSize=8:noTabs=true: