MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-packetbb.c
blobff98ab256c252460527255d9638d2291993b119f
1 /* packet-packetbb.c
2 * Routines for parsing packetbb rfc 5444
3 * Parser created by Henning Rogge <henning.rogge@fkie.fraunhofer.de> of Fraunhover
5 * http://tools.ietf.org/html/rfc5444
6 * http://tools.ietf.org/html/rfc5498
8 * $Id$
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "config.h"
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
32 #include <epan/uat.h>
34 #include <string.h>
36 #define PACKET_HEADER_HASSEQNR 0x08
37 #define PACKET_HEADER_HASTLV 0x04
39 #define MSG_HEADER_HASORIG 0x80
40 #define MSG_HEADER_HASHOPLIMIT 0x40
41 #define MSG_HEADER_HASHOPCOUNT 0x20
42 #define MSG_HEADER_HASSEQNR 0x10
44 #define ADDR_HASHEAD 0x80
45 #define ADDR_HASFULLTAIL 0x40
46 #define ADDR_HASZEROTAIL 0x20
47 #define ADDR_HASSINGLEPRELEN 0x10
48 #define ADDR_HASMULTIPRELEN 0x08
50 #define TLV_HAS_TYPEEXT 0x80
51 #define TLV_HAS_SINGLEINDEX 0x40
52 #define TLV_HAS_MULTIINDEX 0x20
53 #define TLV_HAS_VALUE 0x10
54 #define TLV_HAS_EXTLEN 0x08
55 #define TLV_HAS_MULTIVALUE 0x04
57 #define MAX_ADDR_SIZE 16
59 #define PACKETBB_MSG_TLV_LENGTH (G_MAXUINT8 + 1)
61 static int proto_packetbb = -1;
62 static guint global_packetbb_port = 269;
64 static int hf_packetbb_error = -1;
65 static int hf_packetbb_header = -1;
66 static int hf_packetbb_version = -1;
67 static int hf_packetbb_header_flags = -1;
68 static int hf_packetbb_header_flags_phasseqnum = -1;
69 static int hf_packetbb_header_flags_phastlv = -1;
70 static int hf_packetbb_seqnr = -1;
71 static int hf_packetbb_msg = -1;
72 static int hf_packetbb_msgheader = -1;
73 static int hf_packetbb_msgheader_type = -1;
74 static int hf_packetbb_msgheader_flags = -1;
75 static int hf_packetbb_msgheader_flags_mhasorig = -1;
76 static int hf_packetbb_msgheader_flags_mhashoplimit = -1;
77 static int hf_packetbb_msgheader_flags_mhashopcount = -1;
78 static int hf_packetbb_msgheader_flags_mhasseqnr = -1;
79 static int hf_packetbb_msgheader_addresssize = -1;
80 static int hf_packetbb_msgheader_size = -1;
81 static int hf_packetbb_msgheader_origaddripv4 = -1;
82 static int hf_packetbb_msgheader_origaddripv6 = -1;
83 static int hf_packetbb_msgheader_origaddrmac = -1;
84 static int hf_packetbb_msgheader_origaddrcustom = -1;
85 static int hf_packetbb_msgheader_hoplimit = -1;
86 static int hf_packetbb_msgheader_hopcount = -1;
87 static int hf_packetbb_msgheader_seqnr = -1;
88 static int hf_packetbb_addr = -1;
89 static int hf_packetbb_addr_num = -1;
90 static int hf_packetbb_addr_flags = -1;
91 static int hf_packetbb_addr_flags_hashead = -1;
92 static int hf_packetbb_addr_flags_hasfulltail = -1;
93 static int hf_packetbb_addr_flags_haszerotail = -1;
94 static int hf_packetbb_addr_flags_hassingleprelen = -1;
95 static int hf_packetbb_addr_flags_hasmultiprelen = -1;
96 static int hf_packetbb_addr_head = -1;
97 static int hf_packetbb_addr_tail = -1;
98 static int hf_packetbb_addr_value[4] = { -1, -1, -1, -1 };
99 static int hf_packetbb_addr_value_mid = -1;
100 static int hf_packetbb_addr_value_prefix = -1;
101 static int hf_packetbb_tlvblock = -1;
102 static int hf_packetbb_tlvblock_length = -1;
103 static int hf_packetbb_tlv = -1;
104 static int hf_packetbb_tlv_type = -1;
105 static int hf_packetbb_tlv_flags = -1;
106 static int hf_packetbb_tlv_flags_hastypext = -1;
107 static int hf_packetbb_tlv_flags_hassingleindex = -1;
108 static int hf_packetbb_tlv_flags_hasmultiindex = -1;
109 static int hf_packetbb_tlv_flags_hasvalue = -1;
110 static int hf_packetbb_tlv_flags_hasextlen = -1;
111 static int hf_packetbb_tlv_flags_hasmultivalue = -1;
112 static int hf_packetbb_tlv_typeext = -1;
113 static int hf_packetbb_tlv_indexstart = -1;
114 static int hf_packetbb_tlv_indexend = -1;
115 static int hf_packetbb_tlv_length = -1;
116 static int hf_packetbb_tlv_value = -1;
117 static int hf_packetbb_tlv_multivalue = -1;
119 static gint ett_packetbb = -1;
120 static gint ett_packetbb_header = -1;
121 static gint ett_packetbb_header_flags = -1;
122 static gint ett_packetbb_msg[PACKETBB_MSG_TLV_LENGTH];
123 static gint ett_packetbb_msgheader = -1;
124 static gint ett_packetbb_msgheader_flags = -1;
125 static gint ett_packetbb_addr = -1;
126 static gint ett_packetbb_addr_flags = -1;
127 static gint ett_packetbb_addr_value = -1;
128 static gint ett_packetbb_tlvblock = -1;
129 static gint ett_packetbb_tlv[PACKETBB_MSG_TLV_LENGTH];
130 static gint ett_packetbb_tlv_flags = -1;
131 static gint ett_packetbb_tlv_value = -1;
133 static int dissect_pbb_tlvblock(tvbuff_t *tvb, proto_tree *tree, guint offset,
134 guint maxoffset, gint8 addrCount) {
135 guint16 tlvblockLength;
136 guint tlvblockEnd;
138 proto_tree *tlvblock_tree = NULL;
139 proto_tree *tlv_tree = NULL;
140 proto_tree *tlv_flags_tree = NULL;
141 proto_tree *tlvValue_tree = NULL;
143 proto_item *tlvBlock_item = NULL;
144 proto_item *tlv_item = NULL;
145 proto_item *tlvFlags_item = NULL;
146 proto_item *tlvValue_item = NULL;
147 proto_item *ti = NULL;
149 int tlvCount = 0;
151 if (maxoffset < offset + 2) {
152 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
153 NULL, "Not enough octets for minimal tlvblock");
154 return maxoffset;
157 tlvblockLength = tvb_get_ntohs(tvb, offset);
159 tlvblockEnd = offset + 2 + tlvblockLength;
160 if (maxoffset < tlvblockEnd) {
161 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
162 NULL, "Not enough octets for tlvblock");
163 return maxoffset;
166 tlvBlock_item = proto_tree_add_item(tree, hf_packetbb_tlvblock, tvb, offset, tlvblockEnd - offset, ENC_NA);
167 tlvblock_tree = proto_item_add_subtree(tlvBlock_item, ett_packetbb_tlvblock);
169 proto_tree_add_item(tlvblock_tree, hf_packetbb_tlvblock_length, tvb, offset, 2, ENC_BIG_ENDIAN);
171 offset += 2;
172 while (offset < tlvblockEnd) {
173 guint tlvStart, tlvLength;
174 guint8 tlvType, tlvFlags, tlvExtType, indexStart, indexEnd;
175 guint16 length = 0;
177 tlvStart = offset;
178 tlvType = tvb_get_guint8(tvb, offset++);
179 tlvFlags = tvb_get_guint8(tvb, offset++);
181 indexStart = 0;
182 indexEnd = addrCount;
183 tlvExtType = 0;
185 if ((tlvFlags & TLV_HAS_TYPEEXT) != 0) {
186 tlvExtType = tvb_get_guint8(tvb, offset++);
189 if ((tlvFlags & TLV_HAS_SINGLEINDEX) != 0) {
190 indexStart = indexEnd = tvb_get_guint8(tvb, offset++);
192 else if ((tlvFlags & TLV_HAS_MULTIINDEX) != 0) {
193 indexStart = tvb_get_guint8(tvb, offset++);
194 indexEnd = tvb_get_guint8(tvb, offset++);
197 if ((tlvFlags & TLV_HAS_VALUE) != 0) {
198 if ((tlvFlags & TLV_HAS_EXTLEN) != 0) {
199 length = tvb_get_ntohs(tvb, offset++);
201 else {
202 length = tvb_get_guint8(tvb, offset++);
206 tlvLength = offset - tlvStart + length;
207 offset = tlvStart;
209 tlv_item = proto_tree_add_item(tlvBlock_item, hf_packetbb_tlv, tvb, tlvStart, tlvLength, ENC_NA);
210 tlv_tree = proto_item_add_subtree(tlv_item, ett_packetbb_tlv[tlvType]);
212 if ((tlvFlags & TLV_HAS_TYPEEXT) == 0) {
213 proto_item_append_text(tlv_item, " (%d)", tlvType);
215 else {
216 proto_item_append_text(tlv_item, " (%d/%d)", tlvType, tlvExtType);
219 /* add type */
220 proto_tree_add_item(tlv_tree, hf_packetbb_tlv_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
222 /* add flags */
223 tlvFlags_item = proto_tree_add_item(tlv_tree, hf_packetbb_tlv_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
224 tlv_flags_tree = proto_item_add_subtree(tlvFlags_item, ett_packetbb_tlv_flags);
226 proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hastypext, tvb, offset, 1, ENC_BIG_ENDIAN);
227 proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hassingleindex, tvb, offset, 1, ENC_BIG_ENDIAN);
228 proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasmultiindex, tvb, offset, 1, ENC_BIG_ENDIAN);
229 proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasvalue, tvb, offset, 1, ENC_BIG_ENDIAN);
230 proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasextlen, tvb, offset, 1, ENC_BIG_ENDIAN);
231 proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasmultivalue, tvb, offset, 1, ENC_BIG_ENDIAN);
232 offset++;
234 if ((tlvFlags & TLV_HAS_TYPEEXT) != 0) {
235 /* add ext-type */
236 proto_tree_add_item(tlv_tree, hf_packetbb_tlv_typeext, tvb, offset++, 1, ENC_BIG_ENDIAN);
239 if (addrCount > 0) {
240 /* add index values */
241 if ((tlvFlags & TLV_HAS_SINGLEINDEX) != 0) {
242 proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset++, 1, indexStart);
244 ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset, 0, indexEnd);
245 proto_item_append_text(ti, " (implicit)");
247 else if ((tlvFlags & TLV_HAS_MULTIINDEX) != 0) {
248 proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset++, 1, indexStart);
249 proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset++, 1, indexEnd);
251 else {
252 ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset, 0, indexStart);
253 proto_item_append_text(ti, " (implicit)");
255 ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset, 0, indexEnd);
256 proto_item_append_text(ti, " (implicit)");
260 /* add length */
261 if ((tlvFlags & TLV_HAS_VALUE) != 0) {
262 if ((tlvFlags & TLV_HAS_EXTLEN) != 0) {
263 proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset, 2, length);
264 offset += 2;
266 else {
267 proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset++, 1, length);
270 else {
271 ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset, 0, 0);
272 proto_item_append_text(ti, " (implicit)");
275 if (length > 0) {
276 /* add value */
277 tlvValue_item = proto_tree_add_item(tlv_tree, hf_packetbb_tlv_value, tvb, offset, length, ENC_NA);
279 if ((tlvFlags & TLV_HAS_MULTIVALUE) == 0) {
280 offset += length;
282 else {
283 int i;
284 guint8 c = indexEnd - indexStart + 1;
285 tlvValue_tree = proto_item_add_subtree(tlvValue_item, ett_packetbb_tlv_value);
287 for (i=indexStart; i<=indexEnd; i++) {
288 proto_tree_add_item(tlvValue_tree, hf_packetbb_tlv_multivalue, tvb, offset, length/c, ENC_NA);
289 offset += (length/c);
293 tlvCount++;
296 proto_item_append_text(tlvBlock_item, " (%d TLVs)", tlvCount);
298 return offset;
301 static int dissect_pbb_addressblock(tvbuff_t *tvb, proto_tree *tree, guint offset, guint maxoffset,
302 guint8 addressType, guint8 addressSize) {
303 guint8 addr[MAX_ADDR_SIZE];
305 guint8 numAddr;
306 guint8 address_flags;
307 guint8 head_length = 0, tail_length = 0;
308 guint block_length = 0, midSize = 0;
309 guint block_index = 0, head_index = 0, tail_index = 0, mid_index = 0, prefix_index = 0;
311 proto_tree *addr_tree = NULL;
312 proto_tree *addrFlags_tree = NULL;
313 proto_tree *addrValue_tree = NULL;
315 proto_item *addr_item = NULL;
316 proto_item *addrFlags_item = NULL;
317 proto_item *addrValue_item = NULL;
319 int i = 0;
321 if (maxoffset - offset < 2) {
322 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
323 NULL, "Not enough octets for minimal addressblock header");
324 return tvb_reported_length(tvb);
327 DISSECTOR_ASSERT(addressSize <= MAX_ADDR_SIZE);
329 memset(addr, 0, addressSize);
331 block_length = 2;
332 block_index = offset;
333 midSize = addressSize;
335 numAddr = tvb_get_guint8(tvb, offset++);
336 address_flags = tvb_get_guint8(tvb, offset++);
338 if ((address_flags & ADDR_HASHEAD) != 0) {
339 head_index = offset;
341 if (maxoffset - offset <= 0) {
342 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
343 NULL, "Not enough octets for addressblock head");
344 return tvb_reported_length(tvb);
346 head_length = tvb_get_guint8(tvb, offset++);
348 if (head_length > addressSize-1) {
349 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
350 NULL, "address head length is too long");
351 return tvb_reported_length(tvb);
353 if (maxoffset - offset < head_length) {
354 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
355 NULL, "Not enough octets for addressblock head");
356 return tvb_reported_length(tvb);
358 tvb_memcpy(tvb, addr, offset, head_length);
360 midSize -= head_length;
361 block_length += (head_length+1);
362 offset += head_length;
364 if ((address_flags & ADDR_HASZEROTAIL) != 0) {
365 tail_index = offset;
367 if (maxoffset - offset <= 0) {
368 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
369 NULL, "Not enough octets for addressblock tail");
370 return tvb_reported_length(tvb);
372 tail_length = tvb_get_guint8(tvb, offset++);
373 if (tail_length > addressSize-1-head_length) {
374 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
375 NULL, "address tail length is too long");
376 return tvb_reported_length(tvb);
378 midSize -= tail_length;
379 block_length++;
381 else if ((address_flags & ADDR_HASFULLTAIL) != 0) {
382 tail_index = offset;
384 if (maxoffset - offset <= 0) {
385 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
386 NULL, "Not enough octets for addressblock tail");
387 return tvb_reported_length(tvb);
389 tail_length = tvb_get_guint8(tvb, offset++);
390 if (tail_length > addressSize-1-head_length) {
391 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
392 NULL, "address tail length is too long");
393 return tvb_reported_length(tvb);
396 if (maxoffset - offset < tail_length) {
397 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
398 NULL, "Not enough octets for addressblock tail");
399 return tvb_reported_length(tvb);
401 tvb_memcpy(tvb, &addr[addressSize - tail_length], offset, tail_length);
403 midSize -= tail_length;
404 block_length += (tail_length+1);
405 offset += tail_length;
408 mid_index = offset;
409 block_length += numAddr * midSize;
410 offset += numAddr * midSize;
412 if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) {
413 prefix_index = offset;
414 block_length++;
416 else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) {
417 prefix_index = offset;
418 block_length += numAddr;
421 if (maxoffset < block_index + block_length) {
422 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
423 NULL, "Not enough octets for address block");
424 return maxoffset;
427 /* add address tree */
428 addr_item = proto_tree_add_item(tree, hf_packetbb_addr, tvb, block_index, block_length, ENC_NA);
429 addr_tree = proto_item_add_subtree(addr_item, ett_packetbb_addr);
430 proto_item_append_text(addr_item, " (%d addresses)", numAddr);
432 /* add num-addr */
433 proto_tree_add_item(addr_tree, hf_packetbb_addr_num, tvb, block_index, 1, ENC_BIG_ENDIAN);
435 /* add flags */
436 addrFlags_item = proto_tree_add_item(addr_tree, hf_packetbb_addr_flags, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
437 addrFlags_tree = proto_item_add_subtree(addrFlags_item, ett_packetbb_addr_flags);
439 proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hashead, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
440 proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasfulltail, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
441 proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_haszerotail, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
442 proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hassingleprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
443 proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasmultiprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
445 if ((address_flags & ADDR_HASHEAD) != 0) {
446 /* add head */
447 proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, head_index, head_length+1, ENC_NA);
450 if ((address_flags & ADDR_HASFULLTAIL) != 0) {
451 /* add full tail */
452 proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, tail_length+1, ENC_NA);
454 else if ((address_flags & ADDR_HASZEROTAIL) != 0) {
455 /* add zero tail */
456 proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, tail_index, 1, ENC_NA);
458 for (i=0; i<numAddr; i++) {
459 guint32 ipv4 = (addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3];
460 guint8 prefix = addressSize * 8;
462 tvb_memcpy(tvb, &addr[head_length], mid_index + midSize*i, midSize);
464 switch (addressType) {
465 case 0:
466 addrValue_item = proto_tree_add_ipv4(addr_tree, hf_packetbb_addr_value[addressType],
467 tvb, mid_index, block_index + block_length - mid_index, ipv4);
468 break;
469 case 1:
470 addrValue_item = proto_tree_add_ipv6(addr_tree, hf_packetbb_addr_value[addressType],
471 tvb, mid_index, block_index + block_length - mid_index, addr);
472 break;
473 case 2:
474 addrValue_item = proto_tree_add_ether(addr_tree, hf_packetbb_addr_value[addressType],
475 tvb, mid_index, block_index + block_length - mid_index, addr);
476 break;
477 case 3:
478 addrValue_item = proto_tree_add_bytes(addr_tree, hf_packetbb_addr_value[addressType],
479 tvb, mid_index, block_index + block_length - mid_index, addr);
480 break;
481 default:
482 break;
484 addrValue_tree = proto_item_add_subtree(addrValue_item, ett_packetbb_addr_value);
486 proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_mid, tvb,
487 mid_index + midSize*i, midSize, ENC_NA);
489 if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) {
490 prefix = tvb_get_guint8(tvb, prefix_index);
491 proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index, 1, ENC_BIG_ENDIAN);
493 else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) {
494 prefix = tvb_get_guint8(tvb, prefix_index + i);
495 proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index + i, 1, ENC_BIG_ENDIAN);
497 proto_item_append_text(addrValue_item, "/%d", prefix);
500 offset = dissect_pbb_tlvblock(tvb, addr_tree, block_index + block_length, maxoffset, numAddr);
501 return offset;
504 static int dissect_pbb_message(tvbuff_t *tvb, proto_tree *tree, guint offset) {
505 proto_tree *message_tree = NULL;
506 proto_tree *header_tree = NULL;
507 proto_tree *headerFlags_tree = NULL;
509 proto_item *message_item = NULL;
510 proto_item *header_item = NULL;
511 proto_item *headerFlags_item = NULL;
513 guint8 messageType;
514 guint8 messageFlags;
515 guint16 messageLength, headerLength, messageEnd;
516 guint8 addressSize, addressType;
518 if (tvb_reported_length(tvb) - offset < 6) {
519 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, -1,
520 NULL, "Not enough octets for minimal message header");
521 return tvb_reported_length(tvb);
524 messageType = tvb_get_guint8(tvb, offset);
525 messageFlags = tvb_get_guint8(tvb, offset+1);
526 messageLength = tvb_get_ntohs(tvb, offset+2);
527 addressSize = (messageFlags & 0x0f) + 1;
529 switch (addressSize) {
530 case 4:
531 addressType = 0;
532 break;
533 case 16:
534 addressType = 1;
535 break;
536 case 6:
537 addressType = 2;
538 break;
539 default:
540 addressType = 3;
541 break;
544 messageEnd = offset + messageLength;
546 headerLength = 4;
548 /* calculate header size */
549 if ((messageFlags & MSG_HEADER_HASORIG) != 0) {
550 headerLength += addressSize;
552 if ((messageFlags & MSG_HEADER_HASHOPLIMIT) != 0) {
553 headerLength ++;
555 if ((messageFlags & MSG_HEADER_HASHOPCOUNT) != 0) {
556 headerLength ++;
558 if ((messageFlags & MSG_HEADER_HASSEQNR) != 0) {
559 headerLength += 2;
562 /* test length for message size */
563 if (tvb_reported_length(tvb) - offset < messageLength) {
564 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, -1,
565 NULL, "Not enough octets for message");
566 return tvb_reported_length(tvb);
569 message_item = proto_tree_add_item(tree, hf_packetbb_msg, tvb, offset, messageLength, ENC_NA);
570 message_tree = proto_item_add_subtree(message_item, ett_packetbb_msg[messageType]);
571 proto_item_append_text(message_item, " (type %d)", messageType);
573 header_item = proto_tree_add_item(message_tree, hf_packetbb_msgheader, tvb, offset, headerLength, ENC_NA);
574 header_tree = proto_item_add_subtree(header_item, ett_packetbb_msgheader);
576 /* type */
577 proto_tree_add_item(header_tree, hf_packetbb_msgheader_type, tvb, offset, 1, ENC_BIG_ENDIAN);
579 /* flags */
580 headerFlags_item = proto_tree_add_uint(header_tree, hf_packetbb_msgheader_flags,
581 tvb, offset+1, 1, messageFlags & 0xf8);
583 headerFlags_tree = proto_item_add_subtree(headerFlags_item, ett_packetbb_msgheader_flags);
584 proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhasorig,
585 tvb, offset+1, 1, messageFlags);
586 proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhashoplimit,
587 tvb, offset+1, 1, messageFlags);
588 proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhashopcount,
589 tvb, offset+1, 1, messageFlags);
590 proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhasseqnr,
591 tvb, offset+1, 1, messageFlags);
593 proto_tree_add_uint(header_tree, hf_packetbb_msgheader_addresssize,
594 tvb, offset + 1, 1, (messageFlags & 0x0f) + 1);
596 /* size */
597 proto_tree_add_item(header_tree, hf_packetbb_msgheader_size, tvb, offset+2, 2, ENC_BIG_ENDIAN);
599 offset += 4;
601 /* originator address */
602 if ((messageFlags & MSG_HEADER_HASORIG) != 0) {
603 switch (addressSize) {
604 case 4:
605 /* IPv4 */
606 proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddripv4,
607 tvb, offset, addressSize, ENC_BIG_ENDIAN);
608 break;
609 case 16:
610 /* IPv6 */
611 proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddripv6,
612 tvb, offset, addressSize, ENC_NA);
613 break;
614 case 6:
615 /* MAC */
616 proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddrmac,
617 tvb, offset, addressSize, ENC_NA);
618 break;
619 default:
620 /* Unknown */
621 proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddrcustom,
622 tvb, offset, addressSize, ENC_NA);
623 break;
625 offset += addressSize;
628 /* hop limit */
629 if ((messageFlags & MSG_HEADER_HASHOPLIMIT) != 0) {
630 proto_tree_add_item(header_tree, hf_packetbb_msgheader_hoplimit, tvb, offset++, 1, ENC_BIG_ENDIAN);
633 /* hop count */
634 if ((messageFlags & MSG_HEADER_HASHOPCOUNT) != 0) {
635 proto_tree_add_item(header_tree, hf_packetbb_msgheader_hopcount, tvb, offset++, 1, ENC_BIG_ENDIAN);
638 /* sequence number */
639 if ((messageFlags & MSG_HEADER_HASSEQNR) != 0) {
640 proto_tree_add_item(header_tree, hf_packetbb_msgheader_seqnr, tvb, offset, 2, ENC_BIG_ENDIAN);
641 offset += 2;
644 if (offset >= messageEnd) {
645 /* this is an error, tlv block is mandatory */
646 return tvb_reported_length(tvb);
648 offset = dissect_pbb_tlvblock(tvb, message_tree, offset, messageEnd, 0);
649 while (offset < messageEnd) {
650 offset = dissect_pbb_addressblock(tvb, message_tree, offset, messageEnd, addressType, addressSize);
652 return offset;
655 static int dissect_pbb_header(tvbuff_t *tvb, proto_tree *tree) {
656 proto_tree *header_tree = NULL;
657 proto_tree *headerFlags_tree = NULL;
659 proto_item *header_item = NULL;
660 proto_item *headerFlags_item = NULL;
662 guint8 packet_flags;
663 guint headerLength = 1;
664 guint tlvIndex = 0;
666 /* calculate header length */
667 packet_flags = tvb_get_guint8(tvb, 0);
668 if ((packet_flags & PACKET_HEADER_HASSEQNR) != 0) {
669 headerLength += 2;
671 if ((packet_flags & PACKET_HEADER_HASTLV) != 0) {
672 tlvIndex = headerLength;
673 headerLength += 2;
676 if (tvb_reported_length(tvb) < headerLength) {
677 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, 0, -1,
678 NULL, "Not enough octets for packetbb header");
679 return tvb_reported_length(tvb);
681 if ((packet_flags & PACKET_HEADER_HASTLV) != 0) {
682 headerLength += tvb_get_ntohs(tvb, tlvIndex);
684 if (tvb_reported_length(tvb) < headerLength) {
685 proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, 0, -1,
686 NULL, "Not enough octets for packetbb tlvblock");
687 return tvb_reported_length(tvb);
690 header_item = proto_tree_add_item(tree, hf_packetbb_header, tvb, 0, headerLength, ENC_NA);
691 header_tree = proto_item_add_subtree(header_item, ett_packetbb_header);
693 /* version */
694 proto_tree_add_uint(header_tree, hf_packetbb_version, tvb, 0, 1, packet_flags >> 4);
696 /* flags */
697 headerFlags_item = proto_tree_add_uint(header_tree, hf_packetbb_header_flags,
698 tvb, 0, 1, packet_flags & 0x0f);
700 headerFlags_tree = proto_item_add_subtree(headerFlags_item, ett_packetbb_header_flags);
701 proto_tree_add_boolean(headerFlags_tree, hf_packetbb_header_flags_phasseqnum, tvb, 0, 1, packet_flags);
702 proto_tree_add_boolean(headerFlags_tree, hf_packetbb_header_flags_phastlv, tvb, 0, 1, packet_flags);
704 /* sequence number */
705 if ((packet_flags & PACKET_HEADER_HASSEQNR) != 0) {
706 proto_tree_add_item(header_tree, hf_packetbb_seqnr, tvb, 1, 2, ENC_BIG_ENDIAN);
709 if ((packet_flags & PACKET_HEADER_HASTLV) != 0) {
710 return dissect_pbb_tlvblock(tvb, tree, tlvIndex, tvb_reported_length(tvb), 0);
712 return headerLength;
715 static void dissect_packetbb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
716 col_set_str(pinfo->cinfo, COL_PROTOCOL, "packetbb");
718 /* Clear out stuff in the info column */
719 col_clear(pinfo->cinfo, COL_INFO);
721 /* we are being asked for details */
722 if (tree) {
723 proto_item *ti = NULL;
724 proto_tree *packetbb_tree = NULL;
725 guint offset;
727 ti = proto_tree_add_item(tree, proto_packetbb, tvb, 0, -1, ENC_NA);
728 packetbb_tree = proto_item_add_subtree(ti, ett_packetbb);
730 offset = dissect_pbb_header(tvb, packetbb_tree);
731 while (offset < tvb_reported_length(tvb)) {
732 offset = dissect_pbb_message(tvb, packetbb_tree, offset);
737 void proto_reg_handoff_packetbb(void) {
738 static gboolean packetbb_prefs_initialized = FALSE;
739 static dissector_handle_t packetbb_handle;
740 static guint packetbb_udp_port;
742 if (!packetbb_prefs_initialized) {
743 packetbb_handle = create_dissector_handle(dissect_packetbb, proto_packetbb);
744 packetbb_prefs_initialized = TRUE;
746 else {
747 dissector_delete_uint("udp.port", global_packetbb_port, packetbb_handle);
750 packetbb_udp_port = global_packetbb_port;
751 dissector_add_uint("udp.port", packetbb_udp_port, packetbb_handle);
754 void proto_register_packetbb(void) {
755 /* Setup list of header fields See Section 1.6.1 for details*/
756 static hf_register_info hf[] = {
757 { &hf_packetbb_error,
758 { "ERROR !", "packetbb.error",
759 FT_BYTES, BASE_NONE, NULL, 0,
760 NULL, HFILL }
762 { &hf_packetbb_header,
763 { "Packet header", "packetbb.header",
764 FT_NONE, BASE_NONE, NULL, 0,
765 NULL, HFILL }
767 { &hf_packetbb_version,
768 { "Version", "packetbb.version",
769 FT_UINT8, BASE_DEC, NULL, 0x0,
770 NULL, HFILL }
772 { &hf_packetbb_header_flags,
773 { "Flags", "packetbb.flags",
774 FT_UINT8, BASE_HEX, NULL, 0x0,
775 NULL, HFILL }
777 { &hf_packetbb_header_flags_phasseqnum,
778 { "Has sequence number", "packetbb.flags.phasseqnum",
779 FT_BOOLEAN, 8, TFS(&tfs_true_false), PACKET_HEADER_HASSEQNR,
780 NULL, HFILL }
782 { &hf_packetbb_header_flags_phastlv,
783 { "Has tlv block", "packetbb.flags.phastlv",
784 FT_BOOLEAN, 8, TFS(&tfs_true_false), PACKET_HEADER_HASTLV,
785 NULL, HFILL }
787 { &hf_packetbb_seqnr,
788 { "Sequence number", "packetbb.seqnr",
789 FT_UINT16, BASE_DEC, NULL, 0x0,
790 NULL, HFILL }
792 { &hf_packetbb_msg,
793 { "Message", "packetbb.msg",
794 FT_NONE, BASE_NONE, NULL, 0,
795 NULL, HFILL }
797 { &hf_packetbb_msgheader,
798 { "Message header", "packetbb.msg.header",
799 FT_NONE, BASE_NONE, NULL, 0,
800 NULL, HFILL }
802 { &hf_packetbb_msgheader_type,
803 { "Type", "packetbb.msg.type",
804 FT_UINT8, BASE_DEC, NULL, 0,
805 NULL, HFILL }
807 { &hf_packetbb_msgheader_flags,
808 { "Flags", "packetbb.msg.flags",
809 FT_UINT8, BASE_HEX, NULL, 0,
810 NULL, HFILL }
812 { &hf_packetbb_msgheader_flags_mhasorig,
813 { "Has originator address", "packetbb.msg.flags.mhasorig",
814 FT_BOOLEAN, 8, TFS(&tfs_true_false), MSG_HEADER_HASORIG,
815 NULL, HFILL }
817 { &hf_packetbb_msgheader_flags_mhashoplimit,
818 { "Has hoplimit", "packetbb.msg.flags.mhashoplimit",
819 FT_BOOLEAN, 8, TFS(&tfs_true_false), MSG_HEADER_HASHOPLIMIT,
820 NULL, HFILL }
822 { &hf_packetbb_msgheader_flags_mhashopcount,
823 { "Has hopcount", "packetbb.msg.flags.mhashopcount",
824 FT_BOOLEAN, 8, TFS(&tfs_true_false), MSG_HEADER_HASHOPCOUNT,
825 NULL, HFILL }
827 { &hf_packetbb_msgheader_flags_mhasseqnr,
828 { "Has sequence number", "packetbb.msg.flags.mhasseqnum",
829 FT_BOOLEAN, 8, TFS(&tfs_true_false), MSG_HEADER_HASSEQNR,
830 NULL, HFILL }
832 { &hf_packetbb_msgheader_addresssize,
833 { "AddressSize", "packetbb.msg.addrsize",
834 FT_UINT8, BASE_DEC, NULL, 0,
835 NULL, HFILL }
837 { &hf_packetbb_msgheader_size,
838 { "Size", "packetbb.msg.size",
839 FT_UINT8, BASE_DEC, NULL, 0,
840 NULL, HFILL }
842 { &hf_packetbb_msgheader_origaddripv4,
843 { "Originator address", "packetbb.msg.origaddr4",
844 FT_IPv4, BASE_NONE, NULL, 0,
845 NULL, HFILL }
847 { &hf_packetbb_msgheader_origaddripv6,
848 { "Originator address", "packetbb.msg.origaddr6",
849 FT_IPv6, BASE_NONE, NULL, 0,
850 NULL, HFILL }
852 { &hf_packetbb_msgheader_origaddrmac,
853 { "Originator address", "packetbb.msg.origaddrmac",
854 FT_ETHER, BASE_NONE, NULL, 0,
855 NULL, HFILL }
857 { &hf_packetbb_msgheader_origaddrcustom,
858 { "Originator address", "packetbb.msg.origaddrcustom",
859 FT_BYTES, BASE_NONE, NULL, 0,
860 NULL, HFILL }
862 { &hf_packetbb_msgheader_hoplimit,
863 { "Hop limit", "packetbb.msg.hoplimit",
864 FT_UINT8, BASE_DEC, NULL, 0,
865 NULL, HFILL }
867 { &hf_packetbb_msgheader_hopcount,
868 { "Hop count", "packetbb.msg.hopcount",
869 FT_UINT8, BASE_DEC, NULL, 0,
870 NULL, HFILL }
872 { &hf_packetbb_msgheader_seqnr,
873 { "Squence number", "packetbb.msg.seqnum",
874 FT_UINT16, BASE_DEC, NULL, 0,
875 NULL, HFILL }
878 { &hf_packetbb_addr,
879 { "Address block", "packetbb.msg.addr",
880 FT_NONE, BASE_NONE, NULL, 0,
881 NULL, HFILL }
883 { &hf_packetbb_addr_num,
884 { "Count", "packetbb.msg.addr.num",
885 FT_UINT8, BASE_DEC, NULL, 0,
886 NULL, HFILL }
888 { &hf_packetbb_addr_flags,
889 { "Flags", "packetbb.msg.addr.flags",
890 FT_UINT8, BASE_HEX, NULL, 0,
891 NULL, HFILL }
893 { &hf_packetbb_addr_flags_hashead,
894 { "Has head", "packetbb.msg.addr.hashead",
895 FT_BOOLEAN, 8, TFS(&tfs_true_false), ADDR_HASHEAD,
896 NULL, HFILL }
898 { &hf_packetbb_addr_flags_hasfulltail,
899 { "Has full tail", "packetbb.msg.addr.hasfulltail",
900 FT_BOOLEAN, 8, TFS(&tfs_true_false), ADDR_HASFULLTAIL,
901 NULL, HFILL }
903 { &hf_packetbb_addr_flags_haszerotail,
904 { "Has zero tail", "packetbb.msg.addr.haszerotail",
905 FT_BOOLEAN, 8, TFS(&tfs_true_false), ADDR_HASZEROTAIL,
906 NULL, HFILL }
908 { &hf_packetbb_addr_flags_hassingleprelen,
909 { "Has single prelen", "packetbb.msg.addr.hassingleprelen",
910 FT_BOOLEAN, 8, TFS(&tfs_true_false), ADDR_HASSINGLEPRELEN,
911 NULL, HFILL }
913 { &hf_packetbb_addr_flags_hasmultiprelen,
914 { "Has multiple prelen", "packetbb.msg.addr.hasmultiprelen",
915 FT_BOOLEAN, 8, TFS(&tfs_true_false), ADDR_HASMULTIPRELEN,
916 NULL, HFILL }
918 { &hf_packetbb_addr_head,
919 { "Head", "packetbb.msg.addr.head",
920 FT_BYTES, BASE_NONE, NULL, 0,
921 NULL, HFILL }
923 { &hf_packetbb_addr_tail,
924 { "Tail", "packetbb.msg.addr.tail",
925 FT_BYTES, BASE_NONE, NULL, 0,
926 NULL, HFILL }
928 { &hf_packetbb_addr_value[0],
929 { "Address", "packetbb.msg.addr.value4",
930 FT_IPv4, BASE_NONE, NULL, 0,
931 NULL, HFILL }
933 { &hf_packetbb_addr_value[1],
934 { "Address", "packetbb.msg.addr.value6",
935 FT_IPv6, BASE_NONE, NULL, 0,
936 NULL, HFILL }
938 { &hf_packetbb_addr_value[2],
939 { "Address", "packetbb.msg.addr.valuemac",
940 FT_ETHER, BASE_NONE, NULL, 0,
941 NULL, HFILL }
943 { &hf_packetbb_addr_value[3],
944 { "Address", "packetbb.msg.addr.valuecustom",
945 FT_UINT_BYTES, BASE_NONE, NULL, 0,
946 NULL, HFILL }
948 { &hf_packetbb_addr_value_mid,
949 { "Mid", "packetbb.msg.addr.value.mid",
950 FT_BYTES, BASE_NONE, NULL, 0,
951 NULL, HFILL }
953 { &hf_packetbb_addr_value_prefix,
954 { "Prefix", "packetbb.msg.addr.value.prefix",
955 FT_UINT8, BASE_DEC, NULL, 0,
956 NULL, HFILL }
958 { &hf_packetbb_tlvblock,
959 { "TLV block", "packetbb.tlvblock",
960 FT_NONE, BASE_NONE, NULL, 0,
961 NULL, HFILL }
963 { &hf_packetbb_tlvblock_length,
964 { "Length", "packetbb.tlvblock.length",
965 FT_UINT16, BASE_DEC, NULL, 0,
966 NULL, HFILL }
968 { &hf_packetbb_tlv,
969 { "TLV", "packetbb.tlv",
970 FT_NONE, BASE_NONE, NULL, 0,
971 NULL, HFILL }
973 { &hf_packetbb_tlv_type,
974 { "Type", "packetbb.tlv.type",
975 FT_UINT8, BASE_DEC, NULL, 0,
976 NULL, HFILL }
978 { &hf_packetbb_tlv_flags,
979 { "Flags", "packetbb.tlv.flags",
980 FT_UINT8, BASE_HEX, NULL, 0,
981 NULL, HFILL }
983 { &hf_packetbb_tlv_typeext,
984 { "Extended Type", "packetbb.tlv.typeext",
985 FT_UINT8, BASE_DEC, NULL, 0,
986 NULL, HFILL }
988 { &hf_packetbb_tlv_flags_hastypext,
989 { "Has type-ext", "packetbb.tlv.hastypeext",
990 FT_BOOLEAN, 8, TFS(&tfs_true_false), TLV_HAS_TYPEEXT,
991 NULL, HFILL }
993 { &hf_packetbb_tlv_flags_hassingleindex,
994 { "Has single index", "packetbb.tlv.hassingleindex",
995 FT_BOOLEAN, 8, TFS(&tfs_true_false), TLV_HAS_SINGLEINDEX,
996 NULL, HFILL }
998 { &hf_packetbb_tlv_flags_hasmultiindex,
999 { "Has multiple indices", "packetbb.tlv.hasmultiindex",
1000 FT_BOOLEAN, 8, TFS(&tfs_true_false), TLV_HAS_MULTIINDEX,
1001 NULL, HFILL }
1003 { &hf_packetbb_tlv_flags_hasvalue,
1004 { "Has value", "packetbb.tlv.hasvalue",
1005 FT_BOOLEAN, 8, TFS(&tfs_true_false), TLV_HAS_VALUE,
1006 NULL, HFILL }
1008 { &hf_packetbb_tlv_flags_hasextlen,
1009 { "Has extended length", "packetbb.tlv.hasextlen",
1010 FT_BOOLEAN, 8, TFS(&tfs_true_false), TLV_HAS_EXTLEN,
1011 NULL, HFILL }
1013 { &hf_packetbb_tlv_flags_hasmultivalue,
1014 { "Has multiple values", "packetbb.tlv.hasmultivalue",
1015 FT_BOOLEAN, 8, TFS(&tfs_true_false), TLV_HAS_MULTIVALUE,
1016 NULL, HFILL }
1018 { &hf_packetbb_tlv_indexstart,
1019 { "Index start", "packetbb.tlv.indexstart",
1020 FT_UINT8, BASE_DEC, NULL, 0,
1021 NULL, HFILL }
1023 { &hf_packetbb_tlv_indexend,
1024 { "Index end", "packetbb.tlv.indexend",
1025 FT_UINT8, BASE_DEC, NULL, 0,
1026 NULL, HFILL }
1028 { &hf_packetbb_tlv_length,
1029 { "Length", "packetbb.tlv.length",
1030 FT_UINT16, BASE_DEC, NULL, 0,
1031 NULL, HFILL }
1033 { &hf_packetbb_tlv_value,
1034 { "Value", "packetbb.tlv.value",
1035 FT_BYTES, BASE_NONE, NULL, 0,
1036 NULL, HFILL }
1038 { &hf_packetbb_tlv_multivalue,
1039 { "Multivalue", "packetbb.tlv.multivalue",
1040 FT_BYTES, BASE_NONE, NULL, 0,
1041 NULL, HFILL }
1045 /* Setup protocol subtree array */
1046 gint *ett_base[] = {
1047 &ett_packetbb,
1048 &ett_packetbb_header,
1049 &ett_packetbb_header_flags,
1050 &ett_packetbb_msgheader,
1051 &ett_packetbb_msgheader_flags,
1052 &ett_packetbb_addr,
1053 &ett_packetbb_addr_flags,
1054 &ett_packetbb_addr_value,
1055 &ett_packetbb_tlvblock,
1056 &ett_packetbb_tlv_flags,
1057 &ett_packetbb_tlv_value
1060 static gint *ett[array_length(ett_base) + 2*PACKETBB_MSG_TLV_LENGTH];
1061 module_t *packetbb_module;
1062 int i,j;
1064 memcpy(ett, ett_base, sizeof(ett_base));
1065 j = array_length(ett_base);
1066 for (i=0; i<PACKETBB_MSG_TLV_LENGTH; i++) {
1067 ett_packetbb_msg[i] = -1;
1068 ett_packetbb_tlv[i] = -1;
1070 ett[j++] = &ett_packetbb_msg[i];
1071 ett[j++] = &ett_packetbb_tlv[i];
1074 /* name, short name, abbrev */
1075 proto_packetbb = proto_register_protocol("PacketBB Protocol", "PacketBB",
1076 "packetbb");
1078 /* Required function calls to register the header fields and subtrees used */
1079 proto_register_field_array(proto_packetbb, hf, array_length(hf));
1080 proto_register_subtree_array(ett, array_length(ett));
1082 /* configurable packetbb port */
1083 packetbb_module = prefs_register_protocol(proto_packetbb, proto_reg_handoff_packetbb);
1084 prefs_register_uint_preference(packetbb_module, "communication_port",
1085 "UDP port for packetbb", "UDP communication port for packetbb PDUs",
1086 10, &global_packetbb_port);