Fixup: tvb_get_string(z) -> tvb_get_string(z)_enc
[metze/wireshark/wip.git] / epan / dissectors / packet-tfp.c
1 /* packet-tfp.c
2  * Routines for Tinkerforge protocol packet disassembly
3  * By Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
4  * Copyright 2013 Ishraq Ibne Ashraf
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <glib.h>
28 #include <epan/packet.h>
29 #include <epan/dissectors/packet-usb.h>
30
31 /* defines */
32 #define tfp_PORT 4223
33
34 #define tfp_USB_VENDOR_ID  0x16D0
35 #define tfp_USB_PRODUCT_ID 0x063D
36
37 #define BASE58_MAX_STR_SIZE 13
38
39 void proto_reg_handoff_tfp(void);
40 void proto_register_tfp(void);
41
42 /* variables for creating the tree */
43 static gint proto_tfp = -1;
44 static gint ett_tfp = -1;
45
46 /* header field variables */
47 static gint hf_tfp_uid = -1;
48 static gint hf_tfp_uid_numeric = -1;
49 static gint hf_tfp_len = -1;
50 static gint hf_tfp_fid = -1;
51 static gint hf_tfp_seq = -1;
52 static gint hf_tfp_r = -1;
53 static gint hf_tfp_a = -1;
54 static gint hf_tfp_oo = -1;
55 static gint hf_tfp_e = -1;
56 static gint hf_tfp_future_use = -1;
57 static gint hf_tfp_payload = -1;
58
59 /* bit and byte offsets for dissection */
60 static const gint byte_offset_len          = 4;
61 static const gint byte_offset_fid          = 5;
62 static const gint byte_count_tfp_uid       = 4;
63 static const gint byte_count_tfp_len       = 1;
64 static const gint byte_count_tfp_fid       = 1;
65 static const gint byte_count_tfp_flags     = 2;
66 static const gint bit_count_tfp_seq        = 4;
67 static const gint bit_count_tfp_r          = 1;
68 static const gint bit_count_tfp_a          = 1;
69 static const gint bit_count_tfp_oo         = 2;
70 static const gint bit_count_tfp_e          = 2;
71 static const gint bit_count_tfp_future_use = 6;
72
73 /* base58 encoding variable */
74 static const char BASE58_ALPHABET[] =
75         "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
76
77 /* function for encoding a number to base58 string */
78 static void
79 base58_encode(guint32 value, char *str) {
80
81         guint32 mod;
82         gint    i = 0;
83         gint    k;
84         gchar   reverse_str[BASE58_MAX_STR_SIZE] = {'\0'};
85
86         while (value >= 58) {
87                 mod = value % 58;
88                 reverse_str[i] = BASE58_ALPHABET[mod];
89                 value = value / 58;
90                 ++i;
91         }
92
93         reverse_str[i] = BASE58_ALPHABET[value];
94
95         for (k = 0; k <= i; k++) {
96                 str[k] = reverse_str[i - k];
97         }
98
99         for (; k < BASE58_MAX_STR_SIZE; k++) {
100                 str[k] = '\0';
101         }
102 }
103
104 /* common dissector function for dissecting TFP payloads */
105 static void
106 dissect_tfp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
107
108         gint   byte_offset = 0;
109         gint   bit_offset  = 48;
110
111         guint8 hv_tfp_len;
112         guint8 hv_tfp_fid;
113         guint8 hv_tfp_seq;
114
115         gchar  tfp_uid_string[BASE58_MAX_STR_SIZE];
116
117         base58_encode(tvb_get_letohl(tvb, 0), &tfp_uid_string[0]);
118
119         hv_tfp_len = tvb_get_guint8(tvb, byte_offset_len);
120         hv_tfp_fid = tvb_get_guint8(tvb, byte_offset_fid);
121         hv_tfp_seq = tvb_get_bits8(tvb, bit_offset, bit_count_tfp_seq);
122
123         col_add_fstr(pinfo->cinfo, COL_INFO,
124                         "UID: %s, Len: %d, FID: %d, Seq: %d",
125                         &tfp_uid_string[0], hv_tfp_len, hv_tfp_fid, hv_tfp_seq);
126
127         /* call for details */
128         if (tree) {
129                 proto_tree *tfp_tree;
130                 proto_item *ti;
131
132                 ti = proto_tree_add_protocol_format(tree, proto_tfp, tvb, 0, -1,
133                                                     "Tinkerforge Protocol, UID: %s, Len: %d, FID: %d, Seq: %d",
134                                                     &tfp_uid_string[0], hv_tfp_len, hv_tfp_fid, hv_tfp_seq);
135                 tfp_tree = proto_item_add_subtree(ti, ett_tfp);
136
137                 /* Use ...string_format_value() so we can show the complete generated string but specify */
138                 /*  the field length as being just the 4 bytes from which the string is generated.       */
139                 ti = proto_tree_add_string_format_value(tfp_tree,
140                                                         hf_tfp_uid,
141                                                         tvb, byte_offset, byte_count_tfp_uid,
142                                                         &tfp_uid_string[0], "%s", &tfp_uid_string[0]);
143                 PROTO_ITEM_SET_GENERATED(ti);
144
145                 proto_tree_add_item(tfp_tree,
146                                     hf_tfp_uid_numeric,
147                                     tvb,
148                                     byte_offset,
149                                     byte_count_tfp_uid,
150                                     ENC_LITTLE_ENDIAN);
151
152                 byte_offset += byte_count_tfp_uid;
153
154                 proto_tree_add_item(tfp_tree,
155                                     hf_tfp_len,
156                                     tvb,
157                                     byte_offset,
158                                     byte_count_tfp_len,
159                                     ENC_LITTLE_ENDIAN);
160
161                 byte_offset += byte_count_tfp_len;
162
163                 proto_tree_add_item(tfp_tree,
164                                     hf_tfp_fid,
165                                     tvb,
166                                     byte_offset,
167                                     byte_count_tfp_fid,
168                                     ENC_LITTLE_ENDIAN);
169
170                 byte_offset += byte_count_tfp_fid;
171
172                 proto_tree_add_bits_item(tfp_tree,
173                                          hf_tfp_seq,
174                                          tvb,
175                                          bit_offset,
176                                          bit_count_tfp_seq,
177                                          ENC_LITTLE_ENDIAN);
178
179                 bit_offset += bit_count_tfp_seq;
180
181                 proto_tree_add_bits_item(tfp_tree,
182                                          hf_tfp_r,
183                                          tvb,
184                                          bit_offset,
185                                          bit_count_tfp_r,
186                                          ENC_LITTLE_ENDIAN);
187
188                 bit_offset += bit_count_tfp_r;
189
190                 proto_tree_add_bits_item(tfp_tree,
191                                          hf_tfp_a,
192                                          tvb,
193                                          bit_offset,
194                                          bit_count_tfp_a,
195                                          ENC_LITTLE_ENDIAN);
196
197                 bit_offset += bit_count_tfp_a;
198
199                 proto_tree_add_bits_item(tfp_tree,
200                                          hf_tfp_oo,
201                                          tvb,
202                                          bit_offset,
203                                          bit_count_tfp_oo,
204                                          ENC_LITTLE_ENDIAN);
205
206                 bit_offset += bit_count_tfp_oo;
207
208                 proto_tree_add_bits_item(tfp_tree,
209                                          hf_tfp_e,
210                                          tvb,
211                                          bit_offset,
212                                          bit_count_tfp_e,
213                                          ENC_LITTLE_ENDIAN);
214
215                 bit_offset += bit_count_tfp_e;
216
217                 proto_tree_add_bits_item(tfp_tree,
218                                          hf_tfp_future_use,
219                                          tvb,
220                                          bit_offset,
221                                          bit_count_tfp_future_use,
222                                          ENC_LITTLE_ENDIAN);
223
224                 /*bit_offset += bit_count_tfp_future_use;*/
225
226                 if ((tvb_reported_length(tvb)) > 8) {
227
228                         byte_offset += byte_count_tfp_flags;
229
230                         proto_tree_add_item(tfp_tree, hf_tfp_payload, tvb, byte_offset, -1, ENC_NA);
231                 }
232         }
233 }
234
235 /* dissector function for dissecting TCP payloads */
236 static void
237 dissect_tfp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
238 {
239         col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFP over TCP");
240         col_clear(pinfo->cinfo, COL_INFO);
241
242         dissect_tfp_common(tvb, pinfo, tree);
243 }
244
245 /* dissector function for dissecting USB payloads */
246 static gboolean
247 dissect_tfp_bulk_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
248 {
249         usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data;
250
251         if ((usb_conv_info != NULL) &&
252                 (usb_conv_info->deviceVendor == tfp_USB_VENDOR_ID) &&
253                 (usb_conv_info->deviceProduct == tfp_USB_PRODUCT_ID)) {
254                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFP over USB");
255                 col_clear(pinfo->cinfo, COL_INFO);
256                 dissect_tfp_common(tvb, pinfo, tree);
257                 return TRUE;
258         }
259
260         return FALSE;
261 }
262
263 /* protocol register function */
264 void
265 proto_register_tfp(void)
266 {
267         /* defining header formats */
268         static hf_register_info hf_tfp[] = {
269                 { &hf_tfp_uid,
270                         { "UID (String)",
271                           "tfp.uid",
272                           FT_STRINGZ,
273                           BASE_NONE,
274                           NULL,
275                           0x0,
276                           NULL,
277                           HFILL
278                         }
279                 },
280                 { &hf_tfp_uid_numeric,
281                         { "UID (Numeric)",
282                           "tfp.uid_numeric",
283                           FT_UINT32,
284                           BASE_DEC,
285                           NULL,
286                           0x0,
287                           NULL,
288                           HFILL
289                         }
290                 },
291                 { &hf_tfp_len,
292                         { "Length",
293                           "tfp.len",
294                           FT_UINT8,
295                           BASE_DEC,
296                           NULL,
297                           0x0,
298                           NULL,
299                           HFILL
300                         }
301                 },
302                 { &hf_tfp_fid,
303                         { "Function ID",
304                           "tfp.fid",
305                           FT_UINT8,
306                           BASE_DEC,
307                           NULL,
308                           0x0,
309                           NULL,
310                           HFILL
311                         }
312                 },
313                 { &hf_tfp_seq,
314                         { "Sequence Number",
315                           "tfp.seq",
316                           FT_UINT8,
317                           BASE_DEC,
318                           NULL,
319                           0x0,
320                           NULL,
321                           HFILL
322                         }
323                 },
324                 { &hf_tfp_r,
325                         { "Response Expected",
326                           "tfp.r",
327                           FT_UINT8,
328                           BASE_DEC,
329                           NULL,
330                           0x0,
331                           NULL,
332                           HFILL
333                         }
334                 },
335                 { &hf_tfp_a,
336                         { "Authentication",
337                           "tfp.a",
338                           FT_UINT8,
339                           BASE_DEC,
340                           NULL,
341                           0x0,
342                           NULL,
343                           HFILL
344                         }
345                 },
346                 { &hf_tfp_oo,
347                         { "Other Options",
348                           "tfp.oo",
349                           FT_UINT8,
350                           BASE_DEC,
351                           NULL,
352                           0x0,
353                           NULL,
354                           HFILL
355                         }
356                 },
357                 { &hf_tfp_e,
358                         { "Error Code",
359                           "tfp.e",
360                           FT_UINT8,
361                           BASE_DEC,
362                           NULL,
363                           0x0,
364                           NULL,
365                           HFILL
366                         }
367                 },
368                 { &hf_tfp_future_use,
369                         { "Future Use",
370                           "tfp.future_use",
371                           FT_UINT8,
372                           BASE_DEC,
373                           NULL,
374                           0x0,
375                           NULL,
376                           HFILL
377                         }
378                 },
379                 { &hf_tfp_payload,
380                         { "Payload",
381                           "tfp.payload",
382                           FT_BYTES,
383                           BASE_NONE,
384                           NULL,
385                           0x0,
386                           NULL,
387                           HFILL
388                         }
389                 }
390         };
391
392         /* setup protocol subtree array */
393         static gint *ett[] = {
394                 &ett_tfp
395         };
396
397         /* defining the protocol and its names */
398         proto_tfp = proto_register_protocol (
399                 "Tinkerforge Protocol",
400                 "TFP",
401                 "tfp"
402         );
403
404         proto_register_field_array(proto_tfp, hf_tfp, array_length(hf_tfp));
405         proto_register_subtree_array(ett, array_length(ett));
406 }
407
408 /* handoff function */
409 void
410 proto_reg_handoff_tfp(void) {
411
412         dissector_handle_t tfp_handle_tcp;
413
414         tfp_handle_tcp = create_dissector_handle(dissect_tfp_tcp, proto_tfp);
415
416         dissector_add_uint("tcp.port", tfp_PORT, tfp_handle_tcp);
417         heur_dissector_add("usb.bulk", dissect_tfp_bulk_heur, proto_tfp);
418 }
419
420 /*
421  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
422  *
423  * Local variables:
424  * c-basic-offset: 8
425  * tab-width: 8
426  * indent-tabs-mode: t
427  * End:
428  *
429  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
430  * :indentSize=8:tabSize=8:noTabs=false:
431  */