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
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.
30 #include <epan/packet.h>
31 #include <epan/prefs.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
;
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
;
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");
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");
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
);
172 while (offset
< tlvblockEnd
) {
173 guint tlvStart
, tlvLength
;
174 guint8 tlvType
, tlvFlags
, tlvExtType
, indexStart
, indexEnd
;
178 tlvType
= tvb_get_guint8(tvb
, offset
++);
179 tlvFlags
= tvb_get_guint8(tvb
, offset
++);
182 indexEnd
= addrCount
;
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
++);
202 length
= tvb_get_guint8(tvb
, offset
++);
206 tlvLength
= offset
- tlvStart
+ length
;
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
);
216 proto_item_append_text(tlv_item
, " (%d/%d)", tlvType
, tlvExtType
);
220 proto_tree_add_item(tlv_tree
, hf_packetbb_tlv_type
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
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
);
234 if ((tlvFlags
& TLV_HAS_TYPEEXT
) != 0) {
236 proto_tree_add_item(tlv_tree
, hf_packetbb_tlv_typeext
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
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
);
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)");
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
);
267 proto_tree_add_uint(tlv_tree
, hf_packetbb_tlv_length
, tvb
, offset
++, 1, length
);
271 ti
= proto_tree_add_uint(tlv_tree
, hf_packetbb_tlv_length
, tvb
, offset
, 0, 0);
272 proto_item_append_text(ti
, " (implicit)");
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) {
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
);
296 proto_item_append_text(tlvBlock_item
, " (%d TLVs)", tlvCount
);
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
];
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
;
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
);
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) {
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) {
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
;
381 else if ((address_flags
& ADDR_HASFULLTAIL
) != 0) {
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
;
409 block_length
+= numAddr
* midSize
;
410 offset
+= numAddr
* midSize
;
412 if ((address_flags
& ADDR_HASSINGLEPRELEN
) != 0) {
413 prefix_index
= offset
;
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");
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
);
433 proto_tree_add_item(addr_tree
, hf_packetbb_addr_num
, tvb
, block_index
, 1, ENC_BIG_ENDIAN
);
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) {
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) {
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) {
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
) {
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
);
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
);
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
);
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
);
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
);
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
;
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
) {
544 messageEnd
= offset
+ messageLength
;
548 /* calculate header size */
549 if ((messageFlags
& MSG_HEADER_HASORIG
) != 0) {
550 headerLength
+= addressSize
;
552 if ((messageFlags
& MSG_HEADER_HASHOPLIMIT
) != 0) {
555 if ((messageFlags
& MSG_HEADER_HASHOPCOUNT
) != 0) {
558 if ((messageFlags
& MSG_HEADER_HASSEQNR
) != 0) {
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
);
577 proto_tree_add_item(header_tree
, hf_packetbb_msgheader_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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);
597 proto_tree_add_item(header_tree
, hf_packetbb_msgheader_size
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
601 /* originator address */
602 if ((messageFlags
& MSG_HEADER_HASORIG
) != 0) {
603 switch (addressSize
) {
606 proto_tree_add_item(header_tree
, hf_packetbb_msgheader_origaddripv4
,
607 tvb
, offset
, addressSize
, ENC_BIG_ENDIAN
);
611 proto_tree_add_item(header_tree
, hf_packetbb_msgheader_origaddripv6
,
612 tvb
, offset
, addressSize
, ENC_NA
);
616 proto_tree_add_item(header_tree
, hf_packetbb_msgheader_origaddrmac
,
617 tvb
, offset
, addressSize
, ENC_NA
);
621 proto_tree_add_item(header_tree
, hf_packetbb_msgheader_origaddrcustom
,
622 tvb
, offset
, addressSize
, ENC_NA
);
625 offset
+= addressSize
;
629 if ((messageFlags
& MSG_HEADER_HASHOPLIMIT
) != 0) {
630 proto_tree_add_item(header_tree
, hf_packetbb_msgheader_hoplimit
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
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
);
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
);
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
;
663 guint headerLength
= 1;
666 /* calculate header length */
667 packet_flags
= tvb_get_guint8(tvb
, 0);
668 if ((packet_flags
& PACKET_HEADER_HASSEQNR
) != 0) {
671 if ((packet_flags
& PACKET_HEADER_HASTLV
) != 0) {
672 tlvIndex
= headerLength
;
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
);
694 proto_tree_add_uint(header_tree
, hf_packetbb_version
, tvb
, 0, 1, packet_flags
>> 4);
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);
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 */
723 proto_item
*ti
= NULL
;
724 proto_tree
*packetbb_tree
= NULL
;
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
;
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,
762 { &hf_packetbb_header
,
763 { "Packet header", "packetbb.header",
764 FT_NONE
, BASE_NONE
, NULL
, 0,
767 { &hf_packetbb_version
,
768 { "Version", "packetbb.version",
769 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
772 { &hf_packetbb_header_flags
,
773 { "Flags", "packetbb.flags",
774 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
777 { &hf_packetbb_header_flags_phasseqnum
,
778 { "Has sequence number", "packetbb.flags.phasseqnum",
779 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), PACKET_HEADER_HASSEQNR
,
782 { &hf_packetbb_header_flags_phastlv
,
783 { "Has tlv block", "packetbb.flags.phastlv",
784 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), PACKET_HEADER_HASTLV
,
787 { &hf_packetbb_seqnr
,
788 { "Sequence number", "packetbb.seqnr",
789 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
793 { "Message", "packetbb.msg",
794 FT_NONE
, BASE_NONE
, NULL
, 0,
797 { &hf_packetbb_msgheader
,
798 { "Message header", "packetbb.msg.header",
799 FT_NONE
, BASE_NONE
, NULL
, 0,
802 { &hf_packetbb_msgheader_type
,
803 { "Type", "packetbb.msg.type",
804 FT_UINT8
, BASE_DEC
, NULL
, 0,
807 { &hf_packetbb_msgheader_flags
,
808 { "Flags", "packetbb.msg.flags",
809 FT_UINT8
, BASE_HEX
, NULL
, 0,
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
,
817 { &hf_packetbb_msgheader_flags_mhashoplimit
,
818 { "Has hoplimit", "packetbb.msg.flags.mhashoplimit",
819 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), MSG_HEADER_HASHOPLIMIT
,
822 { &hf_packetbb_msgheader_flags_mhashopcount
,
823 { "Has hopcount", "packetbb.msg.flags.mhashopcount",
824 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), MSG_HEADER_HASHOPCOUNT
,
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
,
832 { &hf_packetbb_msgheader_addresssize
,
833 { "AddressSize", "packetbb.msg.addrsize",
834 FT_UINT8
, BASE_DEC
, NULL
, 0,
837 { &hf_packetbb_msgheader_size
,
838 { "Size", "packetbb.msg.size",
839 FT_UINT8
, BASE_DEC
, NULL
, 0,
842 { &hf_packetbb_msgheader_origaddripv4
,
843 { "Originator address", "packetbb.msg.origaddr4",
844 FT_IPv4
, BASE_NONE
, NULL
, 0,
847 { &hf_packetbb_msgheader_origaddripv6
,
848 { "Originator address", "packetbb.msg.origaddr6",
849 FT_IPv6
, BASE_NONE
, NULL
, 0,
852 { &hf_packetbb_msgheader_origaddrmac
,
853 { "Originator address", "packetbb.msg.origaddrmac",
854 FT_ETHER
, BASE_NONE
, NULL
, 0,
857 { &hf_packetbb_msgheader_origaddrcustom
,
858 { "Originator address", "packetbb.msg.origaddrcustom",
859 FT_BYTES
, BASE_NONE
, NULL
, 0,
862 { &hf_packetbb_msgheader_hoplimit
,
863 { "Hop limit", "packetbb.msg.hoplimit",
864 FT_UINT8
, BASE_DEC
, NULL
, 0,
867 { &hf_packetbb_msgheader_hopcount
,
868 { "Hop count", "packetbb.msg.hopcount",
869 FT_UINT8
, BASE_DEC
, NULL
, 0,
872 { &hf_packetbb_msgheader_seqnr
,
873 { "Squence number", "packetbb.msg.seqnum",
874 FT_UINT16
, BASE_DEC
, NULL
, 0,
879 { "Address block", "packetbb.msg.addr",
880 FT_NONE
, BASE_NONE
, NULL
, 0,
883 { &hf_packetbb_addr_num
,
884 { "Count", "packetbb.msg.addr.num",
885 FT_UINT8
, BASE_DEC
, NULL
, 0,
888 { &hf_packetbb_addr_flags
,
889 { "Flags", "packetbb.msg.addr.flags",
890 FT_UINT8
, BASE_HEX
, NULL
, 0,
893 { &hf_packetbb_addr_flags_hashead
,
894 { "Has head", "packetbb.msg.addr.hashead",
895 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ADDR_HASHEAD
,
898 { &hf_packetbb_addr_flags_hasfulltail
,
899 { "Has full tail", "packetbb.msg.addr.hasfulltail",
900 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ADDR_HASFULLTAIL
,
903 { &hf_packetbb_addr_flags_haszerotail
,
904 { "Has zero tail", "packetbb.msg.addr.haszerotail",
905 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ADDR_HASZEROTAIL
,
908 { &hf_packetbb_addr_flags_hassingleprelen
,
909 { "Has single prelen", "packetbb.msg.addr.hassingleprelen",
910 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ADDR_HASSINGLEPRELEN
,
913 { &hf_packetbb_addr_flags_hasmultiprelen
,
914 { "Has multiple prelen", "packetbb.msg.addr.hasmultiprelen",
915 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ADDR_HASMULTIPRELEN
,
918 { &hf_packetbb_addr_head
,
919 { "Head", "packetbb.msg.addr.head",
920 FT_BYTES
, BASE_NONE
, NULL
, 0,
923 { &hf_packetbb_addr_tail
,
924 { "Tail", "packetbb.msg.addr.tail",
925 FT_BYTES
, BASE_NONE
, NULL
, 0,
928 { &hf_packetbb_addr_value
[0],
929 { "Address", "packetbb.msg.addr.value4",
930 FT_IPv4
, BASE_NONE
, NULL
, 0,
933 { &hf_packetbb_addr_value
[1],
934 { "Address", "packetbb.msg.addr.value6",
935 FT_IPv6
, BASE_NONE
, NULL
, 0,
938 { &hf_packetbb_addr_value
[2],
939 { "Address", "packetbb.msg.addr.valuemac",
940 FT_ETHER
, BASE_NONE
, NULL
, 0,
943 { &hf_packetbb_addr_value
[3],
944 { "Address", "packetbb.msg.addr.valuecustom",
945 FT_UINT_BYTES
, BASE_NONE
, NULL
, 0,
948 { &hf_packetbb_addr_value_mid
,
949 { "Mid", "packetbb.msg.addr.value.mid",
950 FT_BYTES
, BASE_NONE
, NULL
, 0,
953 { &hf_packetbb_addr_value_prefix
,
954 { "Prefix", "packetbb.msg.addr.value.prefix",
955 FT_UINT8
, BASE_DEC
, NULL
, 0,
958 { &hf_packetbb_tlvblock
,
959 { "TLV block", "packetbb.tlvblock",
960 FT_NONE
, BASE_NONE
, NULL
, 0,
963 { &hf_packetbb_tlvblock_length
,
964 { "Length", "packetbb.tlvblock.length",
965 FT_UINT16
, BASE_DEC
, NULL
, 0,
969 { "TLV", "packetbb.tlv",
970 FT_NONE
, BASE_NONE
, NULL
, 0,
973 { &hf_packetbb_tlv_type
,
974 { "Type", "packetbb.tlv.type",
975 FT_UINT8
, BASE_DEC
, NULL
, 0,
978 { &hf_packetbb_tlv_flags
,
979 { "Flags", "packetbb.tlv.flags",
980 FT_UINT8
, BASE_HEX
, NULL
, 0,
983 { &hf_packetbb_tlv_typeext
,
984 { "Extended Type", "packetbb.tlv.typeext",
985 FT_UINT8
, BASE_DEC
, NULL
, 0,
988 { &hf_packetbb_tlv_flags_hastypext
,
989 { "Has type-ext", "packetbb.tlv.hastypeext",
990 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TLV_HAS_TYPEEXT
,
993 { &hf_packetbb_tlv_flags_hassingleindex
,
994 { "Has single index", "packetbb.tlv.hassingleindex",
995 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TLV_HAS_SINGLEINDEX
,
998 { &hf_packetbb_tlv_flags_hasmultiindex
,
999 { "Has multiple indices", "packetbb.tlv.hasmultiindex",
1000 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TLV_HAS_MULTIINDEX
,
1003 { &hf_packetbb_tlv_flags_hasvalue
,
1004 { "Has value", "packetbb.tlv.hasvalue",
1005 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TLV_HAS_VALUE
,
1008 { &hf_packetbb_tlv_flags_hasextlen
,
1009 { "Has extended length", "packetbb.tlv.hasextlen",
1010 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TLV_HAS_EXTLEN
,
1013 { &hf_packetbb_tlv_flags_hasmultivalue
,
1014 { "Has multiple values", "packetbb.tlv.hasmultivalue",
1015 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TLV_HAS_MULTIVALUE
,
1018 { &hf_packetbb_tlv_indexstart
,
1019 { "Index start", "packetbb.tlv.indexstart",
1020 FT_UINT8
, BASE_DEC
, NULL
, 0,
1023 { &hf_packetbb_tlv_indexend
,
1024 { "Index end", "packetbb.tlv.indexend",
1025 FT_UINT8
, BASE_DEC
, NULL
, 0,
1028 { &hf_packetbb_tlv_length
,
1029 { "Length", "packetbb.tlv.length",
1030 FT_UINT16
, BASE_DEC
, NULL
, 0,
1033 { &hf_packetbb_tlv_value
,
1034 { "Value", "packetbb.tlv.value",
1035 FT_BYTES
, BASE_NONE
, NULL
, 0,
1038 { &hf_packetbb_tlv_multivalue
,
1039 { "Multivalue", "packetbb.tlv.multivalue",
1040 FT_BYTES
, BASE_NONE
, NULL
, 0,
1045 /* Setup protocol subtree array */
1046 gint
*ett_base
[] = {
1048 &ett_packetbb_header
,
1049 &ett_packetbb_header_flags
,
1050 &ett_packetbb_msgheader
,
1051 &ett_packetbb_msgheader_flags
,
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
;
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",
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
);