2 * Routines for BEEP packet disassembly
4 * Copyright (c) 2000 by Richard Sharpe <rsharpe@ns.aus.com>
5 * Modified 2001 Darren New <dnew@invisible.net> for BEEP.
7 * Original BXXP dissector developed with funding from InvisibleWorlds
8 * (www.invisibleworlds.com) via Collab.Net.
10 * Wireshark - Network traffic analyzer
12 * Copyright 1999 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <epan/packet.h>
21 #include <epan/prefs.h>
22 #include <epan/conversation.h>
23 #include <epan/expert.h>
24 #include <epan/proto_data.h>
25 #if defined(DEBUG_BEEP_HASH)
26 #include <epan/ws_printf.h>
29 #define TCP_PORT_BEEP 10288 /* Don't think this is IANA registered */
31 void proto_register_beep(void);
32 void proto_reg_handoff_beep(void);
34 static dissector_handle_t beep_handle
;
36 static range_t
*global_beep_tcp_ports
;
37 static bool global_beep_strict_term
= true;
39 static int proto_beep
;
41 static int hf_beep_req
;
42 static int hf_beep_cmd
;
43 static int hf_beep_req_chan
;
44 /* static int hf_beep_rsp_chan; */
45 static int hf_beep_seq_chan
;
46 /* static int hf_beep_rsp; */
47 static int hf_beep_more
;
48 static int hf_beep_msgno
;
49 static int hf_beep_ansno
;
50 static int hf_beep_seqno
;
51 static int hf_beep_size
;
52 static int hf_beep_channel
;
53 static int hf_beep_mime_header
;
54 static int hf_beep_header
;
56 static int hf_beep_status
;
58 static int hf_beep_ackno
;
59 static int hf_beep_window
;
60 static int hf_beep_payload
;
61 static int hf_beep_payload_undissected
;
62 static int hf_beep_crlf_terminator
;
65 static const value_string beep_status_vals
[] = {
73 static const value_string beep_more_vals
[] = {
75 { '*', "Intermediate" },
82 /* Arrays of hf entry pointers for some routines to use. If you want more
83 * hidden items added for a field, add them to the list before the NULL,
84 * and the various routines that these are passed to will add them.
87 static int *req_msgno_hfa
[] = { &hf_beep_msgno
, NULL
};
88 static int *req_ansno_hfa
[] = { &hf_beep_ansno
, NULL
};
89 static int *req_seqno_hfa
[] = { &hf_beep_seqno
, NULL
};
90 static int *req_size_hfa
[] = { &hf_beep_size
, NULL
};
91 static int *req_chan_hfa
[] = { &hf_beep_channel
, &hf_beep_req_chan
, NULL
};
93 static int *rsp_msgno_hfa[] = { &hf_beep_msgno, NULL };
94 static int *rsp_seqno_hfa[] = { &hf_beep_seqno, NULL };
95 static int *rsp_size_hfa[] = { &hf_beep_size, NULL };
97 static int *seq_chan_hfa
[] = { &hf_beep_channel
, &hf_beep_seq_chan
, NULL
};
98 static int *seq_ackno_hfa
[] = { &hf_beep_ackno
, NULL
};
99 static int *seq_window_hfa
[] = { &hf_beep_window
, NULL
};
102 static int ett_mime_header
;
103 static int ett_header
;
104 static int ett_trailer
;
106 static expert_field ei_beep_more
;
107 static expert_field ei_beep_cr_terminator
;
108 static expert_field ei_beep_lf_terminator
;
109 static expert_field ei_beep_invalid_terminator
;
111 /* Get the state of the more flag ... */
114 #define BEEP_INTERMEDIATE 1
115 #define BEEP_COMPLETE 2
120 * pl_left is the amount of data in this packet that belongs to another
123 * It relies on TCP segments not being re-ordered too much ...
125 struct beep_proto_data
{
126 int pl_left
; /* Payload at beginning of frame */
127 int pl_size
; /* Payload in current message ...*/
128 int mime_hdr
; /* Whether we expect a mime header. 1 on first, 0 on rest
137 struct beep_request_key
{
138 uint32_t conversation
;
141 struct beep_request_val
{
142 uint16_t processed
; /* Have we processed this conversation? */
143 int size
; /* Size of the message */
144 /* We need an indication in each dirn of
145 * whether on not a mime header is expected
147 int c_mime_hdr
, s_mime_hdr
;
150 static wmem_map_t
*beep_request_hash
;
154 beep_equal(const void *v
, const void *w
)
156 const struct beep_request_key
*v1
= (const struct beep_request_key
*)v
;
157 const struct beep_request_key
*v2
= (const struct beep_request_key
*)w
;
159 #if defined(DEBUG_BEEP_HASH)
160 ws_debug_printf("Comparing %08X\n and %08X\n",
161 v1
->conversation
, v2
->conversation
);
164 if (v1
->conversation
== v2
->conversation
)
172 beep_hash(const void *v
)
174 const struct beep_request_key
*key
= (const struct beep_request_key
*)v
;
177 val
= key
->conversation
;
179 #if defined(DEBUG_BEEP_HASH)
180 ws_debug_printf("BEEP Hash calculated as %u\n", val
);
188 /* dissect the more flag, and return a value of:
191 * -1 -> Proto violation
195 dissect_beep_more(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
198 proto_item
*hidden_item
;
200 uint8_t more
= tvb_get_uint8(tvb
, offset
);
202 hidden_item
= proto_tree_add_item(tree
, hf_beep_more
, tvb
, offset
, 1, ENC_ASCII
|ENC_NA
);
203 proto_item_set_hidden(hidden_item
);
213 expert_add_info(pinfo
, hidden_item
, &ei_beep_more
);
222 static void dissect_beep_status(tvbuff_t
*tvb
, int offset
,
226 /* FIXME: We should return a value to indicate all OK. */
228 proto_tree_add_item(item_tree
, hf_beep_status
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
232 static int num_len(tvbuff_t
*tvb
, int offset
)
236 while (g_ascii_isdigit(tvb_get_uint8(tvb
, offset
+ i
))) i
++;
243 * We check for a terminator. This can be CRLF, which will be recorded
244 * as a terminator, or CR or LF by itself, which will be redorded as
245 * an incorrect terminator ... We build the tree at this point
246 * However, we depend on the variable beep_strict_term
250 check_term(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, proto_tree
*tree
)
252 /* First, check for CRLF, or, if global_beep_strict_term is false,
253 * one of CR or LF ... If neither of these hold, we add an element
254 * that complains of a protocol violation, and return -1, else
255 * we add a terminator to the tree (possibly non-standard) and return
256 * the count of characters we saw ... This may throw off the rest of the
257 * dissection ... so-be-it!
260 if ((tvb_get_uint8(tvb
, offset
) == 0x0d &&
261 tvb_get_uint8(tvb
, offset
+ 1) == 0x0a)){ /* Correct terminator */
263 proto_tree_add_item(tree
, hf_beep_crlf_terminator
, tvb
, offset
, 2, ENC_NA
);
268 if ((tvb_get_uint8(tvb
, offset
) == 0x0d) && !global_beep_strict_term
) {
270 proto_tree_add_expert(tree
, pinfo
, &ei_beep_cr_terminator
, tvb
, offset
, 1);
275 if ((tvb_get_uint8(tvb
, offset
) == 0x0a) && !global_beep_strict_term
) {
277 proto_tree_add_expert(tree
, pinfo
, &ei_beep_lf_terminator
, tvb
, offset
, 1);
281 proto_tree_add_expert_format(tree
, pinfo
, &ei_beep_invalid_terminator
, tvb
,
282 offset
, 1, "Terminator: %s", tvb_format_text(pinfo
->pool
, tvb
, offset
, 2));
286 /* Get the header length, up to CRLF or CR or LF */
287 static int header_len(tvbuff_t
*tvb
, int offset
)
292 /* FIXME: Have to make sure we stop looking at the end of the tvb ... */
294 /* We look for CRLF, or CR or LF if global_beep_strict_term is
300 if ((sc
= tvb_get_uint8(tvb
, offset
+ i
)) == 0x0d
301 && tvb_get_uint8(tvb
, offset
+ i
+ 1) == 0x0a)
302 return i
; /* Done here ... */
304 if (!global_beep_strict_term
&& (sc
== 0x0d || sc
== 0x0a))
305 return i
; /* Done here also ... */
313 dissect_beep_mime_header(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
314 struct beep_proto_data
*beep_frame_data
,
317 proto_tree
*ti
= NULL
, *mime_tree
= NULL
;
318 int mime_length
= header_len(tvb
, offset
), cc
= 0;
320 if (beep_frame_data
&& !beep_frame_data
->mime_hdr
) return 0;
324 /* FIXME: Should calculate the whole length of the mime headers */
325 ti
= proto_tree_add_item(tree
, hf_beep_mime_header
, tvb
, offset
, mime_length
, ENC_NA
|ENC_ASCII
);
326 mime_tree
= proto_item_add_subtree(ti
, ett_mime_header
);
329 if (mime_length
== 0) { /* Default header */
332 proto_tree_add_string_format(mime_tree
, hf_beep_header
, tvb
, offset
, 0, "", "Default values");
335 if ((cc
= check_term(tvb
, pinfo
, offset
, mime_tree
)) <= 0) {
337 /* Ignore it, it will cause funnies in the rest of the dissect */
342 else { /* FIXME: Process the headers */
345 proto_tree_add_item(mime_tree
, hf_beep_header
, tvb
, offset
, mime_length
, ENC_NA
|ENC_ASCII
);
348 if ((cc
= check_term(tvb
, pinfo
, offset
+ mime_length
, mime_tree
)) <= 0) {
350 /* Ignore it, it will cause funnies in the rest of the dissect */
356 return mime_length
+ cc
; /* FIXME: Check that the CRLF is there */
361 dissect_beep_int(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
362 proto_tree
*tree
, int hf
, int *val
, int *hfa
[])
364 proto_item
*hidden_item
;
366 unsigned int len
= num_len(tvb
, offset
);
368 ival
= (int)strtol(tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, len
, ENC_ASCII
), NULL
, 10);
369 proto_tree_add_uint(tree
, hf
, tvb
, offset
, len
, ival
);
373 hidden_item
= proto_tree_add_uint(tree
, *hfa
[ind
], tvb
, offset
, len
, ival
);
374 proto_item_set_hidden(hidden_item
);
379 *val
= ival
; /* Return the value */
386 set_mime_hdr_flags(int more
, struct beep_request_val
*request_val
,
387 struct beep_proto_data
*beep_frame_data
, packet_info
*pinfo
)
390 if (!request_val
) return; /* Nothing to do ??? */
392 if (value_is_in_range(global_beep_tcp_ports
, pinfo
->destport
)) { /* Going to the server ... client */
394 if (request_val
->c_mime_hdr
) {
396 beep_frame_data
->mime_hdr
= 0;
398 if (!more
) request_val
->c_mime_hdr
= 0;
403 beep_frame_data
->mime_hdr
= 1;
405 if (more
) request_val
->c_mime_hdr
= 1;
412 if (request_val
->s_mime_hdr
) {
414 beep_frame_data
->mime_hdr
= 0;
416 if (!more
) request_val
->s_mime_hdr
= 0;
421 beep_frame_data
->mime_hdr
= 1;
423 if (more
) request_val
->s_mime_hdr
= 1;
433 * A return value of <= 0 says we bailed out, skip the rest of this message,
436 * A return value > 0 is the count of bytes we consumed ...
440 // NOLINTNEXTLINE(misc-no-recursion)
441 dissect_beep_tree(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
442 proto_tree
*tree
, struct beep_request_val
*request_val
,
443 struct beep_proto_data
*beep_frame_data
)
445 proto_tree
*ti
= NULL
, *hdr
= NULL
;
446 /*proto_item *hidden_item;*/
447 int st_offset
, msgno
, ansno
, seqno
, size
, channel
, ackno
, window
, cc
,
450 const char * cmd_temp
= NULL
;
454 if (tvb_strneql(tvb
, offset
, "MSG ", 4) == 0)
455 cmd_temp
= "Command: MSG";
456 if (tvb_strneql(tvb
, offset
, "RPY ", 4) == 0)
457 cmd_temp
= "Command: RPY";
458 if (tvb_strneql(tvb
, offset
, "ERR ", 4) == 0)
459 cmd_temp
= "Command: ERR";
460 if (tvb_strneql(tvb
, offset
, "NUL ", 4) == 0)
461 cmd_temp
= "Command: NUL";
462 if (tvb_strneql(tvb
, offset
, "ANS ", 4) == 0) {
463 cmd_temp
= "Command: ANS";
467 if (cmd_temp
!= NULL
) {
470 hdr
= proto_tree_add_subtree(tree
, tvb
, offset
, header_len(tvb
, offset
) + 2,
471 ett_header
, NULL
, "Header");
473 ti
= proto_tree_add_item(hdr
, hf_beep_cmd
, tvb
, offset
, 3, ENC_NA
|ENC_ASCII
);
475 proto_item_set_len(ti
, 4);
477 proto_tree_add_boolean(hdr
, hf_beep_req
, tvb
, offset
, 3, true);
482 /* Get the channel */
483 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, hdr
, hf_beep_channel
, &channel
, req_chan_hfa
);
484 offset
+= 1; /* Skip the space */
486 /* Dissect the message number */
487 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, hdr
, hf_beep_msgno
, &msgno
, req_msgno_hfa
);
488 offset
+= 1; /* skip the space */
490 /* Insert the more elements ... */
491 if ((more
= dissect_beep_more(tvb
, pinfo
, offset
, hdr
)) >= 0) {
492 /* Figure out which direction this is in and what mime_hdr flag to
493 * add to the beep_frame_data. If there are missing segments, this code
496 set_mime_hdr_flags(more
, request_val
, beep_frame_data
, pinfo
);
498 else { /* Protocol violation, so dissect rest as undissectable */
499 if (tree
&& (tvb_reported_length_remaining(tvb
, offset
) > 0)) {
500 proto_tree_add_item(tree
, hf_beep_payload_undissected
, tvb
, offset
,
501 tvb_reported_length_remaining(tvb
, offset
), ENC_NA
|ENC_ASCII
);
506 offset
+= 2; /* Skip the flag and the space ... */
508 /* now for the seqno */
509 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, hdr
, hf_beep_seqno
, &seqno
, req_seqno_hfa
);
510 offset
+= 1; /* skip the space */
512 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, hdr
, hf_beep_size
, &size
, req_size_hfa
);
513 if (request_val
) /* FIXME, is this the right order ... */
514 request_val
-> size
= size
; /* Stash this away */
515 else if (beep_frame_data
) {
516 beep_frame_data
->pl_size
= size
;
517 if (beep_frame_data
->pl_size
< 0) beep_frame_data
->pl_size
= 0; /* FIXME: OK? */
519 /* offset += 1; skip the space */
521 if (is_ANS
) { /* We need to put in the ansno */
522 offset
+= 1; /* skip the space */
523 /* Dissect the message number */
524 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, hdr
, hf_beep_ansno
, &ansno
, req_ansno_hfa
);
527 if ((cc
= check_term(tvb
, pinfo
, offset
, hdr
)) <= 0) {
529 /* We dissect the rest as data and bail ... */
531 if (tree
&& (tvb_reported_length_remaining(tvb
, offset
) > 0)) {
532 proto_tree_add_item(tree
, hf_beep_payload_undissected
, tvb
, offset
,
533 tvb_reported_length_remaining(tvb
, offset
), ENC_NA
|ENC_ASCII
);
542 /* Insert MIME header ... */
544 if (beep_frame_data
&& beep_frame_data
->mime_hdr
)
545 offset
+= dissect_beep_mime_header(tvb
, pinfo
, offset
, beep_frame_data
, hdr
);
547 /* Now for the payload, if any */
549 if (tvb_reported_length_remaining(tvb
, offset
) > 0) { /* Dissect what is left as payload */
551 int pl_size
= MIN(size
, tvb_reported_length_remaining(tvb
, offset
));
553 /* Except, check the payload length, and only dissect that much */
555 /* We need to keep track, in the conversation, of how much is left
556 * so in the next packet, we can figure out what is part of the payload
557 * and what is the next message
561 proto_tree_add_item(tree
, hf_beep_payload
, tvb
, offset
, pl_size
, ENC_NA
|ENC_ASCII
);
567 request_val
->size
-= pl_size
;
568 if (request_val
->size
< 0) request_val
->size
= 0;
570 else if (beep_frame_data
) {
571 beep_frame_data
->pl_size
-= pl_size
;
572 if (beep_frame_data
->pl_size
< 0) beep_frame_data
->pl_size
= 0;
576 /* If anything else left, dissect it ... */
578 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
579 increment_dissection_depth(pinfo
);
580 offset
+= dissect_beep_tree(tvb
, offset
, pinfo
, tree
, request_val
, beep_frame_data
);
581 decrement_dissection_depth(pinfo
);
583 } else if (tvb_strneql(tvb
, offset
, "SEQ ", 4) == 0) {
586 ti
= proto_tree_add_item(hdr
, hf_beep_cmd
, tvb
, offset
, 3, ENC_NA
|ENC_ASCII
);
588 proto_item_set_len(ti
, 4);
593 /* Now check the space: FIXME */
597 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, tree
, hf_beep_channel
, &channel
, seq_chan_hfa
);
599 /* Check the space: FIXME */
603 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, tree
, hf_beep_ackno
, &ackno
, seq_ackno_hfa
);
605 /* Check the space: FIXME */
609 offset
+= dissect_beep_int(tvb
, pinfo
, offset
, tree
, hf_beep_window
, &window
, seq_window_hfa
);
611 if ((cc
= check_term(tvb
, pinfo
, offset
, tree
)) <= 0) {
613 /* We dissect the rest as data and bail ... */
615 if (tree
&& (tvb_reported_length_remaining(tvb
, offset
) > 0)) {
616 proto_tree_add_item(tree
, hf_beep_payload_undissected
, tvb
, offset
,
617 tvb_reported_length_remaining(tvb
, offset
), ENC_NA
|ENC_ASCII
);
626 } else if (tvb_strneql(tvb
, offset
, "END", 3) == 0) {
628 proto_tree
*tr
= NULL
;
631 tr
= proto_tree_add_subtree(tree
, tvb
, offset
, MIN(5, MAX(0, tvb_reported_length_remaining(tvb
, offset
))),
632 ett_trailer
, NULL
, "Trailer");
634 proto_tree_add_item(hdr
, hf_beep_cmd
, tvb
, offset
, 3, ENC_NA
|ENC_ASCII
);
639 if ((cc
= check_term(tvb
, pinfo
, offset
, tr
)) <= 0) {
641 /* We dissect the rest as data and bail ... */
643 if (tree
&& (tvb_reported_length_remaining(tvb
, offset
) > 0)) {
644 proto_tree_add_item(tree
, hf_beep_payload_undissected
, tvb
, offset
,
645 tvb_reported_length_remaining(tvb
, offset
), ENC_NA
|ENC_ASCII
);
656 if (tvb_reported_length_remaining(tvb
, offset
) > 0) { /* Dissect anything left over */
662 pl_size
= MIN(request_val
->size
, tvb_reported_length_remaining(tvb
, offset
));
664 if (pl_size
== 0) { /* The whole of the rest must be payload */
666 pl_size
= tvb_reported_length_remaining(tvb
, offset
); /* Right place ? */
670 } else if (beep_frame_data
) {
671 pl_size
= MIN(beep_frame_data
->pl_size
, tvb_reported_length_remaining(tvb
, offset
));
672 } else { /* Just in case */
673 pl_size
= tvb_reported_length_remaining(tvb
, offset
);
676 /* Take care here to handle the payload correctly, and if there is
677 * another message here, then handle it correctly as well.
680 /* If the pl_size == 0 and the offset == 0?, then we have not processed
681 * anything in this frame above, so we better treat all this data as
682 * payload to avoid recursion loops
685 if (pl_size
== 0 && offset
== st_offset
)
686 pl_size
= tvb_reported_length_remaining(tvb
, offset
);
691 proto_tree_add_item(tree
, hf_beep_payload
, tvb
, offset
, pl_size
, ENC_NA
|ENC_ASCII
);
694 offset
+= pl_size
; /* Advance past the payload */
697 request_val
->size
-= pl_size
; /* Reduce payload by what we added */
698 if (request_val
->size
< 0) request_val
->size
= 0;
700 else if (beep_frame_data
) {
701 beep_frame_data
->pl_size
-= pl_size
;
702 if (beep_frame_data
->pl_size
< 0) beep_frame_data
->pl_size
= 0;
706 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
707 offset
+= dissect_beep_tree(tvb
, offset
, pinfo
, tree
, request_val
, beep_frame_data
);
711 return offset
- st_offset
;
716 dissect_beep(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
719 struct beep_proto_data
*beep_frame_data
;
720 proto_tree
*beep_tree
= NULL
, *ti
= NULL
;
721 conversation_t
*conversation
= NULL
;
722 struct beep_request_key request_key
, *new_request_key
;
723 struct beep_request_val
*request_val
= NULL
;
727 /* If we have per frame data, use that, else, we must have lost the per-
728 * frame data, and we have to do a full dissect pass again.
730 * The per-frame data tells us how much of this frame is left over from a
731 * previous frame, so we dissect it as payload and then try to dissect the
734 * We use the conversation to build up info on the first pass over the
735 * packets of type BEEP, and record anything that is needed if the user
736 * does random dissects of packets in per packet data.
738 * Once we have per-packet data, we don't need the conversation stuff
739 * anymore, but if per-packet data and conversation stuff gets deleted, as
740 * it does under some circumstances when a rescan is done, it all gets
744 /* Find out what conversation this packet is part of ... but only
745 * if we have no information on this packet, so find the per-frame
749 beep_frame_data
= (struct beep_proto_data
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_beep
, 0);
751 if (!beep_frame_data
) {
753 conversation
= find_or_create_conversation(pinfo
);
756 * Check for and insert an entry in the request table if does not exist
758 request_key
.conversation
= conversation
->conv_index
;
760 request_val
= (struct beep_request_val
*)wmem_map_lookup(beep_request_hash
, &request_key
);
762 if (!request_val
) { /* Create one */
764 new_request_key
= wmem_new(wmem_file_scope(), struct beep_request_key
);
765 new_request_key
->conversation
= conversation
->conv_index
;
767 request_val
= wmem_new0(wmem_file_scope(), struct beep_request_val
);
769 wmem_map_insert(beep_request_hash
, new_request_key
, request_val
);
774 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "BEEP");
777 /* "tvb_format_text()" is passed a value that won't go past the end
778 * of the packet, so it won't throw an exception.
780 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
781 col_add_str(pinfo
->cinfo
, COL_INFO
, tvb_format_text(pinfo
->pool
, tvb
, offset
, tvb_reported_length_remaining(tvb
, offset
)));
783 /* Here, we parse the message so we can retrieve the info we need, which
784 * is that there is some payload left from a previous segment on the
785 * front of this segment ... This all depends on TCP segments not getting
788 * As a huge kludge, we push the checking for the tree down into the code
789 * and process as if we were given a tree but not call the routines that
790 * adorn the protocol tree if they were NULL.
793 if (tree
) { /* Build the tree info ... */
795 ti
= proto_tree_add_item(tree
, proto_beep
, tvb
, offset
, -1, ENC_NA
);
797 beep_tree
= proto_item_add_subtree(ti
, ett_beep
);
801 /* Check the per-frame data and the conversation for any left-over
802 * payload from the previous frame
804 * We check that per-frame data exists first, and if so, use it,
805 * else we use the conversation data.
807 * We create per-frame data here as well, but we must ensure we create it
808 * after we have done the check for per-frame or conversation data.
810 * We also depend on the first frame in a group having a pl_size of 0.
813 if (beep_frame_data
!= NULL
&& beep_frame_data
->pl_left
> 0) {
815 int pl_left
= beep_frame_data
->pl_left
;
817 pl_left
= MIN(pl_left
, MAX(0, tvb_reported_length_remaining(tvb
, offset
)));
819 /* Add the payload bit, only if we have a tree */
820 if (tree
&& (pl_left
> 0)) {
821 proto_tree_add_item(tree
, hf_beep_payload
, tvb
, offset
, pl_left
, ENC_NA
|ENC_ASCII
);
825 else if (request_val
&& request_val
->size
> 0) {
827 int pl_left
= request_val
->size
;
829 request_val
->size
= 0;
831 /* We create the frame data here for this case, and
832 * elsewhere for other frames
835 beep_frame_data
= wmem_new(wmem_file_scope(), struct beep_proto_data
);
837 beep_frame_data
->pl_left
= pl_left
;
838 beep_frame_data
->pl_size
= 0;
839 beep_frame_data
->mime_hdr
= 0;
841 p_add_proto_data(wmem_file_scope(), pinfo
, proto_beep
, 0, beep_frame_data
);
845 /* Set up the per-frame data here if not already done so
846 * This _must_ come after the checks above ...
849 if (beep_frame_data
== NULL
) {
851 beep_frame_data
= wmem_new(wmem_file_scope(), struct beep_proto_data
);
853 beep_frame_data
->pl_left
= 0;
854 beep_frame_data
->pl_size
= 0;
855 beep_frame_data
->mime_hdr
= 0;
857 p_add_proto_data(wmem_file_scope(), pinfo
, proto_beep
, 0, beep_frame_data
);
861 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
863 /*offset += */dissect_beep_tree(tvb
, offset
, pinfo
, beep_tree
, request_val
, beep_frame_data
);
867 return tvb_captured_length(tvb
);
871 apply_beep_prefs(void)
873 /* Beep uses the port preference to determine client/server */
874 global_beep_tcp_ports
= prefs_get_range_value("beep", "tcp.port");
877 /* Register all the bits needed with the filtering engine */
880 proto_register_beep(void)
882 static hf_register_info hf
[] = {
884 { "Request", "beep.req", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
887 { "Command", "beep.command", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
890 { "Request Channel Number", "beep.req.channel", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
894 { "Response", "beep.rsp", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
897 { "Response Channel Number", "beep.rsp.channel", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
901 { "Sequence Channel Number", "beep.seq.channel", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
904 { "More", "beep.more", FT_CHAR
, BASE_HEX
, VALS(beep_more_vals
), 0x0, NULL
, HFILL
}},
907 { "Msgno", "beep.msgno", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
910 { "Ansno", "beep.ansno", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
913 { "Seqno", "beep.seqno", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
916 { "Size", "beep.size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
919 { "Channel", "beep.channel", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
921 { &hf_beep_mime_header
,
922 { "Mime header", "beep.mime_header", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
925 { "Header", "beep.header", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
929 { "Status", "beep.status", FT_UINT8
, BASE_HEX
, VALS(beep_status_vals
), 0x0, NULL
, HFILL
}},
933 { "Ackno", "beep.seq.ackno", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
936 { "Window", "beep.seq.window", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
939 { "Payload", "beep.payload", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
941 { &hf_beep_payload_undissected
,
942 { "Undissected Payload", "beep.payload_undissected", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
944 { &hf_beep_crlf_terminator
,
945 { "Terminator: CRLF", "beep.crlf_terminator", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
947 static int *ett
[] = {
953 static ei_register_info ei
[] = {
954 { &ei_beep_more
, { "beep.more.expected", PI_PROTOCOL
, PI_WARN
, "Expected More Flag (* or .)", EXPFILL
}},
955 { &ei_beep_cr_terminator
, { "beep.cr_terminator", PI_PROTOCOL
, PI_WARN
, "Nonstandard Terminator: CR", EXPFILL
}},
956 { &ei_beep_lf_terminator
, { "beep.lf_terminator", PI_PROTOCOL
, PI_WARN
, "Nonstandard Terminator: LF", EXPFILL
}},
957 { &ei_beep_invalid_terminator
, { "beep.invalid_terminator", PI_PROTOCOL
, PI_WARN
, "Invalid Terminator", EXPFILL
}},
960 module_t
*beep_module
;
961 expert_module_t
* expert_beep
;
963 proto_beep
= proto_register_protocol("Blocks Extensible Exchange Protocol",
966 proto_register_field_array(proto_beep
, hf
, array_length(hf
));
967 proto_register_subtree_array(ett
, array_length(ett
));
968 expert_beep
= expert_register_protocol(proto_beep
);
969 expert_register_field_array(expert_beep
, ei
, array_length(ei
));
971 beep_request_hash
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), beep_hash
, beep_equal
);
973 /* Register our configuration options for BEEP, particularly our port */
975 beep_module
= prefs_register_protocol(proto_beep
, apply_beep_prefs
);
976 /* For reading older preference files with "bxxp." preferences */
977 prefs_register_module_alias("bxxp", beep_module
);
979 prefs_register_bool_preference(beep_module
, "strict_header_terminator",
980 "BEEP Header Requires CRLF",
981 "Specifies that BEEP requires CRLF as a "
982 "terminator, and not just CR or LF",
983 &global_beep_strict_term
);
985 beep_handle
= register_dissector("beep", dissect_beep
, proto_beep
);
988 /* The registration hand-off routine */
990 proto_reg_handoff_beep(void)
992 dissector_add_uint_with_preference("tcp.port", TCP_PORT_BEEP
, beep_handle
);
998 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1003 * indent-tabs-mode: nil
1006 * ex: set shiftwidth=2 tabstop=8 expandtab:
1007 * :indentSize=2:tabSize=8:noTabs=true: