2 * Routines for the disassembly of the Trapeze TAPA protocol
6 * Copyright 2007 Joerg Mayer (see AUTHORS file)
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 #include <epan/packet.h>
42 /* protocol handles */
43 static int proto_tapa = -1;
46 static int ett_tapa_discover = -1;
47 static int ett_tapa_discover_req = -1;
48 static int ett_tapa_tunnel = -1;
51 static int hf_tapa_discover_type = -1;
52 static int hf_tapa_discover_flags = -1;
53 static int hf_tapa_discover_length = -1;
54 static int hf_tapa_discover_unknown = -1;
56 static int hf_tapa_discover_req_type = -1;
57 static int hf_tapa_discover_req_pad = -1;
58 static int hf_tapa_discover_req_length = -1;
59 static int hf_tapa_discover_req_value = -1;
61 static int hf_tapa_discover_newtlv_type = -1;
62 static int hf_tapa_discover_newtlv_pad = -1;
63 static int hf_tapa_discover_newtlv_length = -1;
64 static int hf_tapa_discover_newtlv_valuetext = -1;
65 static int hf_tapa_discover_newtlv_valuehex = -1;
67 static int hf_tapa_discover_reply_switchip = -1;
68 static int hf_tapa_discover_reply_unused = -1;
69 static int hf_tapa_discover_reply_bias = -1;
70 static int hf_tapa_discover_reply_pad = -1;
72 static int hf_tapa_tunnel_version = -1;
73 static int hf_tapa_tunnel_five = -1;
74 static int hf_tapa_tunnel_type = -1;
75 static int hf_tapa_tunnel_zero = -1;
76 static int hf_tapa_tunnel_dmac = -1;
77 static int hf_tapa_tunnel_smac = -1;
78 static int hf_tapa_tunnel_seqno = -1;
79 static int hf_tapa_tunnel_length = -1;
80 static int hf_tapa_tunnel_0804 = -1;
81 static int hf_tapa_tunnel_tagsetc = -1;
83 static int hf_tapa_tunnel_remaining = -1;
85 #define PROTO_SHORT_NAME "TAPA"
86 #define PROTO_LONG_NAME "Trapeze Access Point Access Protocol"
88 #define PORT_TAPA 5000
91 TAPA_TYPE_REQUEST = 0x01,
92 TAPA_TYPE_REPLY = 0x02,
93 TAPA_TYPE_REQUEST_NEW = 0x04,
94 TAPA_TYPE_REPLY_NEW = 0x05
95 } tapa_discover_type_t;
97 static const value_string tapa_discover_type_vals[] = {
98 { TAPA_TYPE_REQUEST, "Request" },
99 { TAPA_TYPE_REPLY, "Reply" },
100 { TAPA_TYPE_REQUEST_NEW, "NewRequest" },
101 { TAPA_TYPE_REPLY_NEW, "NewReply" },
107 TAPA_TUNNEL_TYPE_0 = 0x00,
108 TAPA_TUNNEL_TYPE_1 = 0x01
109 } tapa_tunnel_type_t;
111 static const value_string tapa_tunnel_type_vals[] = {
112 { TAPA_TUNNEL_TYPE_0, "Type 0" },
113 { TAPA_TUNNEL_TYPE_1, "Type 1" },
119 TAPA_REQUEST_SERIAL = 0x01,
120 TAPA_REQUEST_MODEL = 0x02
121 } tapa_discover_request_t;
123 static const value_string tapa_discover_request_vals[] = {
124 { TAPA_REQUEST_SERIAL, "SerialNo" },
125 { TAPA_REQUEST_MODEL, "Model" },
131 static const value_string tapa_discover_unknown_vals[] = {
138 check_ascii(tvbuff_t *tvb, gint offset, gint length)
143 for (i = 0; i < length; i++) {
144 buf = tvb_get_guint8(tvb, offset+i);
145 if (buf < 0x20 || buf >= 0x80) {
153 dissect_tapa_discover_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tapa_discover_tree, guint32 offset, gint remaining)
155 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_reply_switchip, tvb, offset, 4,
158 if (check_col(pinfo->cinfo, COL_INFO))
159 col_append_fstr(pinfo->cinfo, COL_INFO, ", Switch: %s",
160 tvb_ip_to_str(tvb, offset));
164 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_reply_unused, tvb, offset, 1,
168 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_reply_bias, tvb, offset, 1,
173 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_reply_pad, tvb, offset, remaining,
181 dissect_tapa_discover_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tapa_discover_tree, guint32 offset, gint remaining)
184 proto_tree *tapa_discover_item_tree;
188 const gchar *item_type_text;
190 while (remaining > 0) {
191 item_type = tvb_get_guint8(tvb, offset);
192 item_type_text = val_to_str(item_type, tapa_discover_request_vals, "%d");
193 item_length = tvb_get_ntohs(tvb, offset + 2);
194 item_text = tvb_format_text(tvb, offset + 4, item_length);
196 DISSECTOR_ASSERT(item_length > 0);
198 if (check_col(pinfo->cinfo, COL_INFO))
199 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s: %s",
200 item_type_text, item_text);
202 item = proto_tree_add_text(tapa_discover_tree, tvb, offset, 4 + item_length,
203 "Type %d = %s, length %d, value %s",
204 item_type, item_type_text, item_length, item_text);
206 tapa_discover_item_tree = proto_item_add_subtree(item, ett_tapa_discover_req);
208 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_req_type, tvb, offset, 1,
212 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_req_pad, tvb, offset, 1,
216 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_req_length, tvb, offset, 2,
219 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_req_value, tvb, offset, item_length,
221 offset += item_length;
223 remaining -= (item_length + 4);
229 dissect_tapa_discover_unknown_new_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tapa_discover_tree, guint32 offset, gint remaining)
232 proto_tree *tapa_discover_item_tree;
235 const gchar *item_text;
236 /*const gchar *item_type_text;*/
239 while (remaining > 0) {
240 item_type = tvb_get_guint8(tvb, offset);
241 /*item_type_text = val_to_str(item_type, tapa_discover_unknown_vals, "%d");*/
242 item_length = tvb_get_ntohs(tvb, offset + 2) - 4;
244 DISSECTOR_ASSERT(item_length > 0);
246 is_ascii = check_ascii(tvb, offset + 4, item_length);
248 item_text = tvb_format_text(tvb, offset + 4, item_length);
250 item_text = "BINARY-DATA";
252 if (check_col(pinfo->cinfo, COL_INFO))
253 col_append_fstr(pinfo->cinfo, COL_INFO, ", T=%d L=%d",
254 item_type, item_length);
256 item = proto_tree_add_text(tapa_discover_tree, tvb, offset, 4 + item_length,
257 "Type %d, length %d, value %s",
258 item_type, item_length, item_text);
260 tapa_discover_item_tree = proto_item_add_subtree(item, ett_tapa_discover_req);
262 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_newtlv_type, tvb, offset, 1,
266 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_newtlv_pad, tvb, offset, 1,
270 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_newtlv_length, tvb, offset, 2,
275 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_newtlv_valuetext,
276 tvb, offset, item_length, ENC_BIG_ENDIAN);
278 proto_tree_add_item(tapa_discover_item_tree, hf_tapa_discover_newtlv_valuehex,
279 tvb, offset, item_length, ENC_NA);
280 offset += item_length;
282 remaining -= (item_length + 4);
288 dissect_tapa_discover(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
291 proto_tree *tapa_discover_tree = NULL;
296 packet_type = tvb_get_guint8(tvb, 0);
297 remaining = tvb_get_ntohs(tvb, 2) - 4;
299 DISSECTOR_ASSERT(remaining > 4);
301 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
302 if (check_col(pinfo->cinfo, COL_INFO))
303 col_add_fstr(pinfo->cinfo, COL_INFO, "Discover - %s",
304 val_to_str(packet_type, tapa_discover_type_vals, "Unknown (%d)"));
307 ti = proto_tree_add_item(tree, proto_tapa, tvb, offset, -1,
309 tapa_discover_tree = proto_item_add_subtree(ti, ett_tapa_discover);
311 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_type, tvb, offset, 1,
315 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_flags, tvb, offset, 1,
319 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_length, tvb, offset, 2,
323 switch (packet_type) {
324 case TAPA_TYPE_REQUEST:
325 offset = dissect_tapa_discover_req(tvb, pinfo, tapa_discover_tree, offset, remaining);
327 case TAPA_TYPE_REPLY:
328 offset = dissect_tapa_discover_reply(tvb, pinfo, tapa_discover_tree, offset, remaining);
330 case TAPA_TYPE_REQUEST_NEW:
331 case TAPA_TYPE_REPLY_NEW:
332 offset = dissect_tapa_discover_unknown_new_tlv(tvb, pinfo, tapa_discover_tree,
336 proto_tree_add_item(tapa_discover_tree, hf_tapa_discover_unknown, tvb, offset,
347 dissect_tapa_tunnel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
350 proto_tree *tapa_tunnel_tree = NULL;
356 version = tvb_get_guint8(tvb, 0) & 0xF0;
357 type = tvb_get_guint8(tvb, 1);
358 remaining = tvb_reported_length(tvb);
360 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
361 if (check_col(pinfo->cinfo, COL_INFO))
362 col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel - V=%d, T=%s", version >> 4,
363 val_to_str(type, tapa_tunnel_type_vals, "Unknown (%d)"));
366 ti = proto_tree_add_item(tree, proto_tapa, tvb, offset, -1,
368 tapa_tunnel_tree = proto_item_add_subtree(ti, ett_tapa_tunnel);
370 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_version, tvb, offset, 1,
372 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_five, tvb, offset, 1,
376 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_type, tvb, offset, 1,
380 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_zero, tvb, offset, 8,
384 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_dmac, tvb, offset, 6,
388 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_smac, tvb, offset, 6,
393 case TAPA_TUNNEL_TYPE_0:
394 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_0804, tvb, offset, 2,
398 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_tagsetc, tvb, offset, 6,
403 case TAPA_TUNNEL_TYPE_1:
404 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_seqno, tvb, offset, 2,
408 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_length, tvb, offset, 2,
417 /* FIXME: This is just to help figuring out what the bytes mean */
418 proto_tree_add_item(tapa_tunnel_tree, hf_tapa_tunnel_remaining, tvb,
419 offset, remaining - offset, ENC_NA);
427 test_tapa_discover(tvbuff_t *tvb)
429 guint8 type, req_type;
432 if (tvb_length(tvb) < 4)
435 /* Type(1 byte) <= 5, unknown(1 byte), length(2 bytes) */
436 type = tvb_get_guint8(tvb, 0);
437 /* unknown = tvb_get_guint8(tvb, 1); */
438 length = tvb_get_ntohs(tvb, 2);
439 req_type = tvb_get_guint8(tvb, 4);
441 if (type < TAPA_TYPE_REQUEST ||
442 type > TAPA_TYPE_REPLY_NEW ||
445 (type == TAPA_TYPE_REQUEST && (req_type < TAPA_REQUEST_SERIAL || req_type > TAPA_REQUEST_MODEL))) {
453 test_tapa_tunnel(tvbuff_t *tvb)
455 /* If it isn't IPv4, it's TAPA. IPv4: Version(1 byte) = 4,
456 length(2 bytes) >= 20 */
457 if (tvb_length(tvb) < 4 ||
458 (tvb_get_guint8(tvb, 0) & 0xF0) >= 0x40 ||
459 tvb_get_ntohs(tvb, 2) > 0 ||
460 tvb_get_guint8(tvb, 1) > 1) { /* Is tunnel type known? */
467 dissect_tapa_static(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
469 if (test_tapa_discover(tvb)) {
470 return dissect_tapa_discover(tvb, pinfo, tree);
471 } else if (test_tapa_tunnel(tvb)) {
472 return dissect_tapa_tunnel(tvb, pinfo, tree);
478 proto_register_tapa(void)
480 static hf_register_info hf[] = {
482 /* TAPA discover header */
483 { &hf_tapa_discover_type,
484 { "Type", "tapa.discover.type", FT_UINT8, BASE_DEC, VALS(tapa_discover_type_vals),
487 { &hf_tapa_discover_flags,
488 { "Flags", "tapa.discover.flags", FT_UINT8, BASE_HEX, NULL,
491 { &hf_tapa_discover_length,
492 { "Length", "tapa.discover.length", FT_UINT16, BASE_DEC, NULL,
495 /* TAPA discover request */
496 { &hf_tapa_discover_req_type,
497 { "Req type", "tapa.discover.req.type", FT_UINT8, BASE_DEC, VALS(tapa_discover_request_vals),
500 { &hf_tapa_discover_req_pad,
501 { "Req padding", "tapa.discover.req.pad", FT_UINT8, BASE_DEC, NULL,
504 { &hf_tapa_discover_req_length,
505 { "Req length", "tapa.discover.req.length", FT_UINT16, BASE_DEC, NULL,
508 { &hf_tapa_discover_req_value,
509 { "Req value", "tapa.discover.req.value", FT_BYTES, BASE_NONE, NULL,
512 /* TAPA discover reply */
513 { &hf_tapa_discover_reply_switchip,
514 { "Switch Ip", "tapa.discover.reply.switchip", FT_IPv4, BASE_NONE, NULL,
517 { &hf_tapa_discover_reply_unused,
518 { "Reply unused", "tapa.discover.reply.unused", FT_UINT8, BASE_DEC, NULL,
521 { &hf_tapa_discover_reply_bias,
522 { "Reply bias", "tapa.discover.reply.bias", FT_UINT8, BASE_DEC, NULL,
525 { &hf_tapa_discover_reply_pad,
526 { "Reply pad", "tapa.discover.reply.pad", FT_BYTES, BASE_NONE, NULL,
529 /* TAPA discover new request/reply tlv */
530 { &hf_tapa_discover_newtlv_type,
531 { "New tlv type", "tapa.discover.newtlv.type", FT_UINT8, BASE_DEC, VALS(tapa_discover_request_vals),
534 { &hf_tapa_discover_newtlv_pad,
535 { "New tlv padding", "tapa.discover.newtlv.pad", FT_UINT8, BASE_DEC, NULL,
538 { &hf_tapa_discover_newtlv_length,
539 { "New tlv length", "tapa.discover.newtlv.length", FT_UINT16, BASE_DEC, NULL,
542 { &hf_tapa_discover_newtlv_valuetext,
543 { "New tlv value", "tapa.discover.newtlv.valuetext", FT_STRING, BASE_NONE, NULL,
546 { &hf_tapa_discover_newtlv_valuehex,
547 { "New tlv value", "tapa.discover.newtlv.valuehex", FT_BYTES, BASE_NONE, NULL,
550 /* TAPA discover unknown packet */
551 { &hf_tapa_discover_unknown,
552 { "Tapa unknown packet", "tapa.discover.unknown", FT_BYTES, BASE_NONE, NULL,
556 { &hf_tapa_tunnel_version,
557 { "Tapa tunnel version", "tapa.tunnel.version", FT_UINT8, BASE_HEX, NULL,
558 0xF0, NULL, HFILL }},
560 { &hf_tapa_tunnel_five,
561 { "Tapa tunnel five", "tapa.tunnel.five", FT_UINT8, BASE_HEX, NULL,
562 0x0F, NULL, HFILL }},
564 { &hf_tapa_tunnel_type,
565 { "Tapa tunnel type", "tapa.tunnel.type", FT_UINT8, BASE_HEX, VALS(tapa_tunnel_type_vals),
568 { &hf_tapa_tunnel_zero,
569 { "Tapa tunnel zeroes", "tapa.tunnel.zero", FT_BYTES, BASE_NONE, NULL,
572 { &hf_tapa_tunnel_dmac,
573 { "Tapa tunnel dest mac", "tapa.tunnel.dmac", FT_ETHER, BASE_NONE, NULL,
576 { &hf_tapa_tunnel_smac,
577 { "Tapa tunnel src mac", "tapa.tunnel.smac", FT_ETHER, BASE_NONE, NULL,
580 /* TAPA tunnel type 0 */
581 { &hf_tapa_tunnel_0804,
582 { "Tapa tunnel 0804", "tapa.tunnel.0804", FT_UINT16, BASE_HEX, NULL,
585 { &hf_tapa_tunnel_tagsetc,
586 { "Tapa tunnel tags, seqno, pad", "tapa.tunnel.tags", FT_BYTES, BASE_NONE, NULL,
589 /* TAPA tunnel type 1 */
590 { &hf_tapa_tunnel_seqno,
591 { "Tapa tunnel seqno", "tapa.tunnel.seqno", FT_UINT16, BASE_DEC, NULL,
594 { &hf_tapa_tunnel_length,
595 { "Tapa tunnel length", "tapa.tunnel.length", FT_UINT16, BASE_DEC, NULL,
599 /* TAPA tunnel remaining stuff */
600 { &hf_tapa_tunnel_remaining,
601 { "Tapa tunnel all data", "tapa.tunnel.remaining", FT_BYTES, BASE_NONE, NULL,
605 static gint *ett[] = {
607 &ett_tapa_discover_req,
611 proto_tapa = proto_register_protocol(PROTO_LONG_NAME,
612 PROTO_SHORT_NAME, "tapa");
613 proto_register_field_array(proto_tapa, hf, array_length(hf));
614 proto_register_subtree_array(ett, array_length(ett));
616 new_register_dissector("tapa", dissect_tapa_static, proto_tapa);
621 proto_reg_handoff_tapa(void)
623 dissector_handle_t tapa_handle;
625 tapa_handle = find_dissector("tapa");
626 dissector_add_uint("udp.port", PORT_TAPA, tapa_handle);