epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-beep.c
blobe0306a830238f21f79ad06dfa1ae12770568a2bb
1 /* packet-beep.c
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
11 * By Gerald Combs
12 * Copyright 1999 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include "config.h"
19 #include <stdlib.h>
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>
27 #endif
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;
55 #if 0
56 static int hf_beep_status;
57 #endif
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;
64 #if 0
65 static const value_string beep_status_vals[] = {
66 { '+', "Positive" },
67 { '-', "Negative" },
69 { 0, NULL }
71 #endif
73 static const value_string beep_more_vals[] = {
74 { '.', "Complete" },
75 { '*', "Intermediate" },
77 { 0, NULL }
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 };
101 static int ett_beep;
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 ... */
113 #define BEEP_VIOL 0
114 #define BEEP_INTERMEDIATE 1
115 #define BEEP_COMPLETE 2
118 * Per-frame data
120 * pl_left is the amount of data in this packet that belongs to another
121 * frame ...
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
129 * in a message
134 * Conversation stuff
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;
152 /* Hash Functions */
153 static int
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);
162 #endif
164 if (v1->conversation == v2->conversation)
165 return 1;
167 return 0;
171 static unsigned
172 beep_hash(const void *v)
174 const struct beep_request_key *key = (const struct beep_request_key *)v;
175 unsigned val;
177 val = key->conversation;
179 #if defined(DEBUG_BEEP_HASH)
180 ws_debug_printf("BEEP Hash calculated as %u\n", val);
181 #endif
183 return val;
188 /* dissect the more flag, and return a value of:
189 * 1 -> more
190 * 0 -> no more
191 * -1 -> Proto violation
194 static int
195 dissect_beep_more(tvbuff_t *tvb, packet_info *pinfo, int offset,
196 proto_tree *tree)
198 proto_item *hidden_item;
199 int ret = 0;
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);
205 switch(more) {
206 case '.':
207 ret = 0;
208 break;
209 case '*':
210 ret = 1;
211 break;
212 default:
213 expert_add_info(pinfo, hidden_item, &ei_beep_more);
214 ret = -1;
215 break;
218 return ret;
221 #if 0
222 static void dissect_beep_status(tvbuff_t *tvb, int offset,
223 proto_tree *tree)
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);
230 #endif
232 static int num_len(tvbuff_t *tvb, int offset)
234 unsigned int i = 0;
236 while (g_ascii_isdigit(tvb_get_uint8(tvb, offset + i))) i++;
238 return 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
249 static int
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);
264 return 2;
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);
271 return 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);
278 return 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));
283 return -1;
286 /* Get the header length, up to CRLF or CR or LF */
287 static int header_len(tvbuff_t *tvb, int offset)
289 int i = 0;
290 uint8_t sc;
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
295 * not set.
298 while (1) {
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 ... */
307 i++;
312 static int
313 dissect_beep_mime_header(tvbuff_t *tvb, packet_info *pinfo, int offset,
314 struct beep_proto_data *beep_frame_data,
315 proto_tree *tree)
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;
322 if (tree) {
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 */
331 if (tree) {
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 */
344 if (tree) {
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 */
360 static int
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;
365 int ival, ind = 0;
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);
371 while (hfa[ind]) {
373 hidden_item = proto_tree_add_uint(tree, *hfa[ind], tvb, offset, len, ival);
374 proto_item_set_hidden(hidden_item);
375 ind++;
379 *val = ival; /* Return the value */
381 return len;
385 static void
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;
401 else {
403 beep_frame_data->mime_hdr = 1;
405 if (more) request_val->c_mime_hdr = 1;
410 else {
412 if (request_val->s_mime_hdr) {
414 beep_frame_data->mime_hdr = 0;
416 if (!more) request_val->s_mime_hdr = 0;
419 else {
421 beep_frame_data->mime_hdr = 1;
423 if (more) request_val->s_mime_hdr = 1;
431 /* Build the tree
433 * A return value of <= 0 says we bailed out, skip the rest of this message,
434 * if any.
436 * A return value > 0 is the count of bytes we consumed ...
439 static int
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,
448 more;
450 const char * cmd_temp = NULL;
451 int is_ANS = 0;
452 st_offset = offset;
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";
464 is_ANS = 1;
467 if (cmd_temp != NULL) {
469 if (tree) {
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);
474 /* Include space */
475 proto_item_set_len(ti, 4);
477 proto_tree_add_boolean(hdr, hf_beep_req, tvb, offset, 3, true);
480 offset += 4;
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
494 * will get it wrong!
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);
503 return -1;
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);
536 return -1;
540 offset += cc;
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
560 if (tree) {
561 proto_tree_add_item(tree, hf_beep_payload, tvb, offset, pl_size, ENC_NA|ENC_ASCII);
564 offset += pl_size;
566 if (request_val) {
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) {
585 if (tree) {
586 ti = proto_tree_add_item(hdr, hf_beep_cmd, tvb, offset, 3, ENC_NA|ENC_ASCII);
587 /* Include space */
588 proto_item_set_len(ti, 4);
591 offset += 3;
593 /* Now check the space: FIXME */
595 offset += 1;
597 offset += dissect_beep_int(tvb, pinfo, offset, tree, hf_beep_channel, &channel, seq_chan_hfa);
599 /* Check the space: FIXME */
601 offset += 1;
603 offset += dissect_beep_int(tvb, pinfo, offset, tree, hf_beep_ackno, &ackno, seq_ackno_hfa);
605 /* Check the space: FIXME */
607 offset += 1;
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);
620 return -1;
624 offset += cc;
626 } else if (tvb_strneql(tvb, offset, "END", 3) == 0) {
628 proto_tree *tr = NULL;
630 if (tree) {
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);
637 offset += 3;
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);
648 return -1;
652 offset += cc;
656 if (tvb_reported_length_remaining(tvb, offset) > 0) { /* Dissect anything left over */
658 int pl_size = 0;
660 if (request_val) {
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);
688 if (pl_size > 0) {
690 if (tree) {
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 */
696 if (request_val){
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;
715 static int
716 dissect_beep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
718 int offset;
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;
725 offset = 0;
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
732 * rest.
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
741 * rebuilt.
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
746 * info first.
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
786 * out of order ...
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);
823 offset += pl_left;
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);
870 static void
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 */
879 void
880 proto_register_beep(void)
882 static hf_register_info hf[] = {
883 { &hf_beep_req,
884 { "Request", "beep.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
886 { &hf_beep_cmd,
887 { "Command", "beep.command", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
889 { &hf_beep_req_chan,
890 { "Request Channel Number", "beep.req.channel", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
892 #if 0
893 { &hf_beep_rsp,
894 { "Response", "beep.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
896 { &hf_beep_rsp_chan,
897 { "Response Channel Number", "beep.rsp.channel", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
898 #endif
900 { &hf_beep_seq_chan,
901 { "Sequence Channel Number", "beep.seq.channel", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
903 { &hf_beep_more,
904 { "More", "beep.more", FT_CHAR, BASE_HEX, VALS(beep_more_vals), 0x0, NULL, HFILL }},
906 { &hf_beep_msgno,
907 { "Msgno", "beep.msgno", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
909 { &hf_beep_ansno,
910 { "Ansno", "beep.ansno", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
912 { &hf_beep_seqno,
913 { "Seqno", "beep.seqno", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
915 { &hf_beep_size,
916 { "Size", "beep.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
918 { &hf_beep_channel,
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 }},
924 { &hf_beep_header,
925 { "Header", "beep.header", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
927 #if 0
928 { &hf_beep_status,
929 { "Status", "beep.status", FT_UINT8, BASE_HEX, VALS(beep_status_vals), 0x0, NULL, HFILL }},
930 #endif
932 { &hf_beep_ackno,
933 { "Ackno", "beep.seq.ackno", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
935 { &hf_beep_window,
936 { "Window", "beep.seq.window", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
938 { &hf_beep_payload,
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[] = {
948 &ett_beep,
949 &ett_mime_header,
950 &ett_header,
951 &ett_trailer,
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",
964 "BEEP", "beep");
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 */
989 void
990 proto_reg_handoff_beep(void)
992 dissector_add_uint_with_preference("tcp.port", TCP_PORT_BEEP, beep_handle);
994 apply_beep_prefs();
998 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1000 * Local Variables:
1001 * c-basic-offset: 2
1002 * tab-width: 8
1003 * indent-tabs-mode: nil
1004 * End:
1006 * ex: set shiftwidth=2 tabstop=8 expandtab:
1007 * :indentSize=2:tabSize=8:noTabs=true: