2 * Routines for Tinkerforge protocol packet disassembly
3 * By Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
4 * Copyright 2013 Ishraq Ibne Ashraf
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include "packet-usb.h"
19 #define tfp_PORT 4223 /* Not IANA registered */
21 #define tfp_USB_VENDOR_ID 0x16D0
22 #define tfp_USB_PRODUCT_ID 0x063D
24 #define BASE58_MAX_STR_SIZE 13
26 void proto_reg_handoff_tfp(void);
27 void proto_register_tfp(void);
29 static dissector_handle_t tfp_handle_tcp
;
31 /* variables for creating the tree */
35 /* header field variables */
36 static int hf_tfp_uid
;
37 static int hf_tfp_uid_numeric
;
38 static int hf_tfp_len
;
39 static int hf_tfp_fid
;
40 static int hf_tfp_seq
;
45 static int hf_tfp_future_use
;
46 static int hf_tfp_payload
;
48 /* bit and byte offsets for dissection */
49 static const int byte_offset_len
= 4;
50 static const int byte_offset_fid
= 5;
51 static const int byte_count_tfp_uid
= 4;
52 static const int byte_count_tfp_len
= 1;
53 static const int byte_count_tfp_fid
= 1;
54 static const int byte_count_tfp_flags
= 2;
55 static const int bit_count_tfp_seq
= 4;
56 static const int bit_count_tfp_r
= 1;
57 static const int bit_count_tfp_a
= 1;
58 static const int bit_count_tfp_oo
= 2;
59 static const int bit_count_tfp_e
= 2;
60 static const int bit_count_tfp_future_use
= 6;
62 /* base58 encoding variable */
63 static const char BASE58_ALPHABET
[] =
64 "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
66 /* function for encoding a number to base58 string */
68 base58_encode(uint32_t value
, char *str
) {
73 char reverse_str
[BASE58_MAX_STR_SIZE
] = {'\0'};
77 reverse_str
[i
] = BASE58_ALPHABET
[mod
];
82 reverse_str
[i
] = BASE58_ALPHABET
[value
];
84 for (k
= 0; k
<= i
; k
++) {
85 str
[k
] = reverse_str
[i
- k
];
88 for (; k
< BASE58_MAX_STR_SIZE
; k
++) {
93 /* common dissector function for dissecting TFP payloads */
95 dissect_tfp_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
104 char tfp_uid_string
[BASE58_MAX_STR_SIZE
];
106 base58_encode(tvb_get_letohl(tvb
, 0), &tfp_uid_string
[0]);
108 hv_tfp_len
= tvb_get_uint8(tvb
, byte_offset_len
);
109 hv_tfp_fid
= tvb_get_uint8(tvb
, byte_offset_fid
);
110 hv_tfp_seq
= tvb_get_bits8(tvb
, bit_offset
, bit_count_tfp_seq
);
112 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
113 "UID: %s, Len: %d, FID: %d, Seq: %d",
114 &tfp_uid_string
[0], hv_tfp_len
, hv_tfp_fid
, hv_tfp_seq
);
116 /* call for details */
118 proto_tree
*tfp_tree
;
121 ti
= proto_tree_add_protocol_format(tree
, proto_tfp
, tvb
, 0, -1,
122 "Tinkerforge Protocol, UID: %s, Len: %d, FID: %d, Seq: %d",
123 &tfp_uid_string
[0], hv_tfp_len
, hv_tfp_fid
, hv_tfp_seq
);
124 tfp_tree
= proto_item_add_subtree(ti
, ett_tfp
);
126 /* Use ...string_format_value() so we can show the complete generated string but specify */
127 /* the field length as being just the 4 bytes from which the string is generated. */
128 ti
= proto_tree_add_string_format_value(tfp_tree
,
130 tvb
, byte_offset
, byte_count_tfp_uid
,
131 &tfp_uid_string
[0], "%s", &tfp_uid_string
[0]);
132 proto_item_set_generated(ti
);
134 proto_tree_add_item(tfp_tree
,
141 byte_offset
+= byte_count_tfp_uid
;
143 proto_tree_add_item(tfp_tree
,
150 byte_offset
+= byte_count_tfp_len
;
152 proto_tree_add_item(tfp_tree
,
159 byte_offset
+= byte_count_tfp_fid
;
161 proto_tree_add_bits_item(tfp_tree
,
168 bit_offset
+= bit_count_tfp_seq
;
170 proto_tree_add_bits_item(tfp_tree
,
177 bit_offset
+= bit_count_tfp_r
;
179 proto_tree_add_bits_item(tfp_tree
,
186 bit_offset
+= bit_count_tfp_a
;
188 proto_tree_add_bits_item(tfp_tree
,
195 bit_offset
+= bit_count_tfp_oo
;
197 proto_tree_add_bits_item(tfp_tree
,
204 bit_offset
+= bit_count_tfp_e
;
206 proto_tree_add_bits_item(tfp_tree
,
210 bit_count_tfp_future_use
,
213 /*bit_offset += bit_count_tfp_future_use;*/
215 if ((tvb_reported_length(tvb
)) > 8) {
217 byte_offset
+= byte_count_tfp_flags
;
219 proto_tree_add_item(tfp_tree
, hf_tfp_payload
, tvb
, byte_offset
, -1, ENC_NA
);
224 /* dissector function for dissecting TCP payloads */
226 dissect_tfp_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
228 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TFP over TCP");
229 col_clear(pinfo
->cinfo
, COL_INFO
);
231 dissect_tfp_common(tvb
, pinfo
, tree
);
232 return tvb_captured_length(tvb
);
235 /* dissector function for dissecting USB payloads */
237 dissect_tfp_bulk_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
239 urb_info_t
*urb
= (urb_info_t
*)data
;
241 if ((urb
!= NULL
) && (urb
->conv
!= NULL
) &&
242 (urb
->conv
->deviceVendor
== tfp_USB_VENDOR_ID
) &&
243 (urb
->conv
->deviceProduct
== tfp_USB_PRODUCT_ID
)) {
244 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TFP over USB");
245 col_clear(pinfo
->cinfo
, COL_INFO
);
246 dissect_tfp_common(tvb
, pinfo
, tree
);
253 /* protocol register function */
255 proto_register_tfp(void)
257 /* defining header formats */
258 static hf_register_info hf_tfp
[] = {
270 { &hf_tfp_uid_numeric
,
315 { "Response Expected",
358 { &hf_tfp_future_use
,
382 /* setup protocol subtree array */
383 static int *ett
[] = {
387 /* defining the protocol and its names */
388 proto_tfp
= proto_register_protocol (
389 "Tinkerforge Protocol",
394 proto_register_field_array(proto_tfp
, hf_tfp
, array_length(hf_tfp
));
395 proto_register_subtree_array(ett
, array_length(ett
));
396 tfp_handle_tcp
= register_dissector("tfp", dissect_tfp_tcp
, proto_tfp
);
399 /* handoff function */
401 proto_reg_handoff_tfp(void) {
403 dissector_add_uint_with_preference("tcp.port", tfp_PORT
, tfp_handle_tcp
);
404 heur_dissector_add("usb.bulk", dissect_tfp_bulk_heur
, "Tinkerforge USB bulk endpoint", "tfp_usb_bulk", proto_tfp
, HEURISTIC_ENABLE
);
408 * Editor modelines - https://www.wireshark.org/tools/modelines.html
413 * indent-tabs-mode: t
416 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
417 * :indentSize=8:tabSize=8:noTabs=false: