3 * Routines for UDPCP packet dissection (UDP-based reliable communication protocol).
4 * Described in the Open Base Station Initiative Reference Point 1 Specification
5 * (see https://web.archive.org/web/20171206005927/http://www.obsai.com/specs/RP1%20Spec%20v2_1.pdf, Appendix A)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
16 * - Calculate/verify Checksum field
21 #include <epan/conversation.h>
22 #include <epan/reassemble.h>
23 #include <epan/expert.h>
24 #include <epan/prefs.h>
27 void proto_register_udpcp(void);
29 static int proto_udpcp
;
31 static int hf_udpcp_checksum
;
32 static int hf_udpcp_msg_type
;
33 static int hf_udpcp_version
;
35 static int hf_udpcp_packet_transfer_options
;
36 static int hf_udpcp_n
;
37 static int hf_udpcp_c
;
38 static int hf_udpcp_s
;
39 static int hf_udpcp_d
;
40 static int hf_udpcp_reserved
;
42 static int hf_udpcp_fragment_amount
;
43 static int hf_udpcp_fragment_number
;
45 static int hf_udpcp_message_id
;
46 static int hf_udpcp_message_data_length
;
48 static int hf_udpcp_payload
;
50 static int hf_udpcp_ack_frame
;
51 static int hf_udpcp_sn_frame
;
55 static int hf_udpcp_fragments
;
56 static int hf_udpcp_fragment
;
57 static int hf_udpcp_fragment_overlap
;
58 static int hf_udpcp_fragment_overlap_conflict
;
59 static int hf_udpcp_fragment_multiple_tails
;
60 static int hf_udpcp_fragment_too_long_fragment
;
61 static int hf_udpcp_fragment_error
;
62 static int hf_udpcp_fragment_count
;
63 static int hf_udpcp_reassembled_in
;
64 static int hf_udpcp_reassembled_length
;
65 static int hf_udpcp_reassembled_data
;
70 static int ett_udpcp_packet_transfer_options
;
71 static int ett_udpcp_fragments
;
72 static int ett_udpcp_fragment
;
74 static const fragment_items udpcp_frag_items
= {
79 &hf_udpcp_fragment_overlap
,
80 &hf_udpcp_fragment_overlap_conflict
,
81 &hf_udpcp_fragment_multiple_tails
,
82 &hf_udpcp_fragment_too_long_fragment
,
83 &hf_udpcp_fragment_error
,
84 &hf_udpcp_fragment_count
,
85 &hf_udpcp_reassembled_in
,
86 &hf_udpcp_reassembled_length
,
87 &hf_udpcp_reassembled_data
,
92 static expert_field ei_udpcp_checksum_should_be_zero
;
93 static expert_field ei_udpcp_d_not_zero_for_data
;
94 static expert_field ei_udpcp_reserved_not_zero
;
95 static expert_field ei_udpcp_n_s_ack
;
96 static expert_field ei_udpcp_payload_wrong_size
;
97 static expert_field ei_udpcp_wrong_sequence_number
;
98 static expert_field ei_udpcp_no_ack
;
99 static expert_field ei_udpcp_no_sn_frame
;
101 static dissector_handle_t udpcp_handle
;
104 void proto_reg_handoff_udpcp (void);
106 /* User definable values */
107 static range_t
*global_udpcp_port_range
;
109 #define DATA_FORMAT 0x01
110 #define ACK_FORMAT 0x02
113 static const value_string msg_type_vals
[] = {
114 { DATA_FORMAT
, "Data Packet" },
115 { ACK_FORMAT
, "Ack Packet" },
120 /* Protocol is bi-directional, so need to distinguish */
121 uint16_t first_dest_port
;
122 address first_dest_address
;
124 /* Main these so can link between SN frames and ACKs */
125 wmem_tree_t
*sn_table_first
;
126 wmem_tree_t
*ack_table_first
;
127 wmem_tree_t
*sn_table_second
;
128 wmem_tree_t
*ack_table_second
;
130 /* Remember next expected message-id in each direction */
131 uint32_t next_message_id_first
;
132 uint32_t next_message_id_second
;
133 } udpcp_conversation_t
;
136 /* Framenum -> expected_sequence_number */
137 static wmem_tree_t
*sequence_number_result_table
;
140 /* Reassembly table. */
141 static reassembly_table udpcp_reassembly_table
;
143 static void *udpcp_temporary_key(const packet_info
*pinfo _U_
, const uint32_t id _U_
, const void *data
)
148 static void *udpcp_persistent_key(const packet_info
*pinfo _U_
, const uint32_t id _U_
,
154 static void udpcp_free_temporary_key(void *ptr _U_
)
158 static void udpcp_free_persistent_key(void *ptr _U_
)
162 static reassembly_table_functions udpcp_reassembly_table_functions
=
167 udpcp_persistent_key
,
168 udpcp_free_temporary_key
,
169 udpcp_free_persistent_key
173 /**************************************************************************/
174 /* Preferences state */
175 /**************************************************************************/
177 /* Reassemble by default */
178 static bool global_udpcp_reassemble
= true;
180 /* By default do try to decode payload as XML/SOAP */
181 static bool global_udpcp_decode_payload_as_soap
= true;
184 static dissector_handle_t xml_handle
;
186 /******************************/
187 /* Main dissection function. */
189 dissect_udpcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
191 proto_tree
*udpcp_tree
;
195 /* Must be at least 12 bytes */
196 if (tvb_reported_length(tvb
) < 12) {
200 /* Has to be Data or Ack format. */
201 uint32_t msg_type
= tvb_get_uint8(tvb
, 4) >> 6;
202 if ((msg_type
!= DATA_FORMAT
) && (msg_type
!= ACK_FORMAT
)) {
206 /* Protocol column */
207 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "UDPCP");
210 root_ti
= proto_tree_add_item(tree
, proto_udpcp
, tvb
, offset
, -1, ENC_NA
);
211 udpcp_tree
= proto_item_add_subtree(root_ti
, ett_udpcp
);
215 proto_item
*checksum_ti
= proto_tree_add_item_ret_uint(udpcp_tree
, hf_udpcp_checksum
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &checksum
);
219 proto_tree_add_item_ret_uint(udpcp_tree
, hf_udpcp_msg_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &msg_type
);
220 col_add_str(pinfo
->cinfo
, COL_INFO
,
221 (msg_type
== DATA_FORMAT
) ? "[Data] " : "[Ack] ");
222 proto_item_append_text(root_ti
, (msg_type
== DATA_FORMAT
) ? " [Data]" : " [Ack]");
225 proto_tree_add_item(udpcp_tree
, hf_udpcp_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
228 /***************************/
229 /* Packet Transfer Options */
230 proto_item
*packet_transfer_options_ti
=
231 proto_tree_add_string_format(udpcp_tree
, hf_udpcp_packet_transfer_options
, tvb
, offset
, 2,
232 "", "Packet Transfer Options (");
233 proto_tree
*packet_transfer_options_tree
=
234 proto_item_add_subtree(packet_transfer_options_ti
, ett_udpcp_packet_transfer_options
);
238 proto_tree_add_item_ret_uint(packet_transfer_options_tree
, hf_udpcp_n
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &n
);
240 proto_item_append_text(packet_transfer_options_ti
, "N");
244 proto_tree_add_item_ret_uint(packet_transfer_options_tree
, hf_udpcp_c
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &c
);
246 proto_item_append_text(packet_transfer_options_ti
, "C");
248 if (!c
&& checksum
) {
249 /* Expert info warning that checksum should be 0 if !c */
250 expert_add_info(pinfo
, checksum_ti
, &ei_udpcp_checksum_should_be_zero
);
254 proto_tree_add_item_ret_uint(packet_transfer_options_tree
, hf_udpcp_s
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &s
);
257 proto_item_append_text(packet_transfer_options_ti
, "S");
261 proto_item
*d_ti
= proto_tree_add_item_ret_uint(packet_transfer_options_tree
, hf_udpcp_d
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &d
);
263 proto_item_append_text(packet_transfer_options_ti
, "D");
265 /* Expert info if D not zero for data */
266 if ((msg_type
== DATA_FORMAT
) && d
) {
267 expert_add_info(pinfo
, d_ti
, &ei_udpcp_d_not_zero_for_data
);
272 proto_item
*reserved_ti
= proto_tree_add_item_ret_uint(packet_transfer_options_tree
, hf_udpcp_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &reserved
);
274 /* Expert info if reserved not 0 */
276 expert_add_info(pinfo
, reserved_ti
, &ei_udpcp_reserved_not_zero
);
279 proto_item_append_text(packet_transfer_options_ti
, ")");
280 /*************************/
283 /* Fragment Amount & Fragment Number */
284 uint32_t fragment_amount
, fragment_number
;
285 proto_tree_add_item_ret_uint(udpcp_tree
, hf_udpcp_fragment_amount
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &fragment_amount
);
287 proto_tree_add_item_ret_uint(udpcp_tree
, hf_udpcp_fragment_number
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &fragment_number
);
290 /* Message ID & Message Data Length */
292 proto_item
*message_id_ti
= proto_tree_add_item_ret_uint(udpcp_tree
, hf_udpcp_message_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &message_id
);
293 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Msg_ID=%3u", message_id
);
295 uint32_t data_length
;
296 proto_tree_add_item_ret_uint(udpcp_tree
, hf_udpcp_message_data_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &data_length
);
299 if (msg_type
== DATA_FORMAT
) {
301 /* This could just be a sync frame */
302 if (!message_id
&& !n
&& !s
) {
303 col_append_str(pinfo
->cinfo
, COL_INFO
, " [Sync]");
307 /* Show if/when this frame should be acknowledged */
309 proto_item_append_text(packet_transfer_options_ti
, " (All packets ACKd)");
312 proto_item_append_text(packet_transfer_options_ti
, " (Last fragment ACKd)");
315 proto_item_append_text(packet_transfer_options_ti
, " (Not ACKd)");
318 /* Show fragment numbering. Ignore confusing 0-based fragment numbering.. */
319 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Frag %u/%u]",
320 fragment_number
+1, fragment_amount
);
323 if ((fragment_amount
== 1) && (fragment_number
== 0) && data_length
) {
324 /* Not fragmented - show payload now */
325 proto_item
*data_ti
= proto_tree_add_item(udpcp_tree
, hf_udpcp_payload
, tvb
, offset
, -1, ENC_ASCII
);
326 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Data (%u bytes)", data_length
);
328 /* Check length is as signalled */
329 if (data_length
!= (uint32_t)tvb_reported_length_remaining(tvb
, offset
)) {
330 expert_add_info_format(pinfo
, data_ti
, &ei_udpcp_payload_wrong_size
, "Data length field was %u but %u bytes found",
331 data_length
, tvb_reported_length_remaining(tvb
, offset
));
334 if (global_udpcp_decode_payload_as_soap
) {
335 /* Send to XML dissector */
336 tvbuff_t
*next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
337 call_dissector_only(xml_handle
, next_tvb
, pinfo
, tree
, NULL
);
342 if (global_udpcp_reassemble
&& data_length
) {
344 /* Set fragmented flag. */
345 bool save_fragmented
= pinfo
->fragmented
;
346 pinfo
->fragmented
= true;
348 unsigned frag_data_len
= tvb_reported_length_remaining(tvb
, offset
);
350 /* Add this fragment into reassembly */
351 fh
= fragment_add_seq_check(&udpcp_reassembly_table
, tvb
, offset
, pinfo
,
353 GUINT_TO_POINTER(message_id
), /* data */
354 fragment_number
, /* frag_number */
355 frag_data_len
, /* frag_data_len */
356 (fragment_number
< (fragment_amount
-1)) /* more_frags */
359 bool update_col_info
= true;
360 /* See if this completes an SDU */
361 tvbuff_t
*next_tvb
= process_reassembled_data(tvb
, offset
, pinfo
, "Reassembled UDPCP Payload",
362 fh
, &udpcp_frag_items
,
363 &update_col_info
, udpcp_tree
);
365 /* Have reassembled data */
366 proto_item
*data_ti
= proto_tree_add_item(udpcp_tree
, hf_udpcp_payload
, next_tvb
, 0, -1, ENC_ASCII
);
367 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Reassembled Data (%u bytes)", data_length
);
369 /* Check length is as signalled */
370 if (data_length
!= (uint32_t)tvb_reported_length_remaining(next_tvb
, 0)) {
371 expert_add_info_format(pinfo
, data_ti
, &ei_udpcp_payload_wrong_size
, "Data length field was %u but %u bytes found (reassembled)",
372 data_length
, tvb_reported_length_remaining(next_tvb
, 0));
375 if (global_udpcp_decode_payload_as_soap
) {
376 /* Send to XML dissector */
377 call_dissector_only(xml_handle
, next_tvb
, pinfo
, tree
, NULL
);
381 /* Restore fragmented flag */
382 pinfo
->fragmented
= save_fragmented
;
386 else if (msg_type
== ACK_FORMAT
) {
387 /* N and S should be set - complain if not */
389 expert_add_info(pinfo
, packet_transfer_options_ti
, &ei_udpcp_n_s_ack
);
393 /* Duplicate data detected */
394 proto_item_append_text(packet_transfer_options_ti
, " (duplicate)");
395 col_append_str(pinfo
->cinfo
, COL_INFO
, " (duplicate)");
398 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " ACK for Msg_ID=%3u", message_id
);
401 /* Look up conversation */
402 if (!PINFO_FD_VISITED(pinfo
)) {
404 conversation_t
*p_conv
;
405 udpcp_conversation_t
*p_conv_data
;
407 p_conv
= find_conversation(pinfo
->num
, &pinfo
->net_dst
, &pinfo
->net_src
,
408 conversation_pt_to_conversation_type(pinfo
->ptype
),
409 pinfo
->destport
, pinfo
->srcport
,
412 /* Look up data from conversation */
413 p_conv_data
= (udpcp_conversation_t
*)conversation_get_proto_data(p_conv
, proto_udpcp
);
415 /* Create new data for conversation data if not found */
417 p_conv_data
= wmem_new(wmem_file_scope(), udpcp_conversation_t
);
419 /* Set initial values */
420 p_conv_data
->first_dest_port
= pinfo
->destport
;
421 copy_address(&p_conv_data
->first_dest_address
, &pinfo
->dst
);
422 p_conv_data
->next_message_id_first
= 0;
423 p_conv_data
->next_message_id_second
= 0;
425 /* SN and ACK tables */
426 p_conv_data
->sn_table_first
= wmem_tree_new(wmem_file_scope());
427 p_conv_data
->ack_table_first
= wmem_tree_new(wmem_file_scope());
428 p_conv_data
->sn_table_second
= wmem_tree_new(wmem_file_scope());
429 p_conv_data
->ack_table_second
= wmem_tree_new(wmem_file_scope());
431 /* Store in conversation */
432 conversation_add_proto_data(p_conv
, proto_udpcp
, p_conv_data
);
435 /* Check which direction this is in */
436 bool first_dir
= (pinfo
->destport
== p_conv_data
->first_dest_port
) &&
437 addresses_equal(&pinfo
->dst
, &p_conv_data
->first_dest_address
);
439 /* Check for expected sequence number */
440 if (msg_type
== DATA_FORMAT
) {
442 if (message_id
!= p_conv_data
->next_message_id_first
) {
443 wmem_tree_insert32(sequence_number_result_table
, pinfo
->num
, GUINT_TO_POINTER(p_conv_data
->next_message_id_first
));
445 /* Only inc when have seen last fragment */
446 if (fragment_number
== fragment_amount
-1) {
447 p_conv_data
->next_message_id_first
= message_id
+ 1;
450 /* Store SN entry in table */
451 wmem_tree_insert32(p_conv_data
->sn_table_first
, message_id
, GUINT_TO_POINTER(pinfo
->num
));
455 if (message_id
!= p_conv_data
->next_message_id_second
) {
456 wmem_tree_insert32(sequence_number_result_table
, pinfo
->num
, GUINT_TO_POINTER(p_conv_data
->next_message_id_second
));
458 /* Only inc when have seen last fragment */
459 if (fragment_number
== fragment_amount
-1) {
460 p_conv_data
->next_message_id_second
= message_id
+ 1;
463 /* Store SN entry in table */
464 wmem_tree_insert32(p_conv_data
->sn_table_second
, message_id
, GUINT_TO_POINTER(pinfo
->num
));
468 if (msg_type
== ACK_FORMAT
) {
469 /* N.B., directions reversed here to apply to data direction */
471 wmem_tree_insert32(p_conv_data
->ack_table_first
, message_id
, GUINT_TO_POINTER(pinfo
->num
));
474 wmem_tree_insert32(p_conv_data
->ack_table_second
, message_id
, GUINT_TO_POINTER(pinfo
->num
));
479 /* Later passes - look up conversation here */
480 conversation_t
*p_conv
;
481 udpcp_conversation_t
*p_conv_data
;
483 p_conv
= find_conversation(pinfo
->num
, &pinfo
->net_dst
, &pinfo
->net_src
,
484 conversation_pt_to_conversation_type(pinfo
->ptype
),
485 pinfo
->destport
, pinfo
->srcport
,
488 /* Look up data from conversation */
489 p_conv_data
= (udpcp_conversation_t
*)conversation_get_proto_data(p_conv
, proto_udpcp
);
491 /* TODO: error if not found? */
495 /* Check which direction this is in */
496 bool first_dir
= (pinfo
->destport
== p_conv_data
->first_dest_port
) &&
497 addresses_equal(&pinfo
->dst
, &p_conv_data
->first_dest_address
);
500 if (msg_type
== DATA_FORMAT
) {
501 /* Check for unexpected sequence number, but not if message_id is still 0 (as it may be repeated) */
502 if (message_id
> 1) {
503 if (wmem_tree_contains32(sequence_number_result_table
, pinfo
->num
)) {
504 uint32_t seqno
= GPOINTER_TO_UINT(wmem_tree_lookup32(sequence_number_result_table
, pinfo
->num
));
505 expert_add_info_format(pinfo
, message_id_ti
, &ei_udpcp_wrong_sequence_number
, "SN %u expected, but found %u instead",
510 /* Look for ACK for this data PDU, link or expert info */
511 wmem_tree_t
*ack_table
= (first_dir
) ? p_conv_data
->ack_table_second
: p_conv_data
->ack_table_first
;
512 if (wmem_tree_contains32(ack_table
, message_id
)) {
513 uint32_t ack
= GPOINTER_TO_UINT(wmem_tree_lookup32(ack_table
, message_id
));
514 proto_tree_add_uint(udpcp_tree
, hf_udpcp_ack_frame
, tvb
, 0, 0, ack
);
517 expert_add_info_format(pinfo
, message_id_ti
, &ei_udpcp_no_ack
, "No ACK seen for this data frame (message_id=%u",
523 else if (msg_type
== ACK_FORMAT
) {
524 /* Look up corresponding Data frame, link or expert info */
525 wmem_tree_t
*sn_table
= (first_dir
) ? p_conv_data
->sn_table_second
: p_conv_data
->sn_table_first
;
526 if (wmem_tree_contains32(sn_table
, message_id
)) {
527 uint32_t sn_frame
= GPOINTER_TO_UINT(wmem_tree_lookup32(sn_table
, message_id
));
528 proto_tree_add_uint(udpcp_tree
, hf_udpcp_sn_frame
, tvb
, 0, 0, sn_frame
);
531 expert_add_info_format(pinfo
, message_id_ti
, &ei_udpcp_no_sn_frame
, "No SN frame seen corresponding to this ACK (message_id=%u",
541 proto_register_udpcp(void)
543 static hf_register_info hf
[] = {
544 { &hf_udpcp_checksum
,
545 { "Checksum", "udpcp.checksum", FT_UINT32
, BASE_HEX
,
546 NULL
, 0x0, "Adler32 checksum", HFILL
}},
547 { &hf_udpcp_msg_type
,
548 { "Msg Type", "udpcp.msg-type", FT_UINT8
, BASE_HEX
,
549 VALS(msg_type_vals
), 0xc0, NULL
, HFILL
}},
551 { "Version", "udpcp.version", FT_UINT8
, BASE_HEX
,
552 NULL
, 0x38, NULL
, HFILL
}},
554 { &hf_udpcp_packet_transfer_options
,
555 { "Packet Transport Options", "udpcp.pto", FT_STRING
, BASE_NONE
,
556 NULL
, 0x0, NULL
, HFILL
}},
558 { "N", "udpcp.n", FT_UINT8
, BASE_HEX
,
559 NULL
, 0x04, "Along with S bit, indicates whether acknowledgements should be sent", HFILL
}},
561 { "C", "udpcp.c", FT_UINT8
, BASE_HEX
,
562 NULL
, 0x02, "When set, the checksum should be valid", HFILL
}},
564 { "S", "udpcp.s", FT_UINT8
, BASE_HEX
,
565 NULL
, 0x01, "Along with N bit, indicates whether acknowledgements should be sent", HFILL
}},
567 { "D", "udpcp.d", FT_UINT8
, BASE_HEX
,
568 NULL
, 0x80, "For ACK, indicates duplicate ACK", HFILL
}},
569 { &hf_udpcp_reserved
,
570 { "Reserved", "udpcp.reserved", FT_UINT8
, BASE_HEX
,
571 NULL
, 0x7f, "Shall be set to 0", HFILL
}},
573 { &hf_udpcp_fragment_amount
,
574 { "Fragment Amount", "udpcp.fragment-amount", FT_UINT8
, BASE_DEC
,
575 NULL
, 0x0, "Total number of fragments of a message", HFILL
}},
576 { &hf_udpcp_fragment_number
,
577 { "Fragment Number", "udpcp.fragment-number", FT_UINT8
, BASE_DEC
,
578 NULL
, 0x0, "Fragment number of current packet within msg. Starts at 0", HFILL
}},
580 { &hf_udpcp_message_id
,
581 { "Message ID", "udpcp.message-id", FT_UINT16
, BASE_DEC
,
582 NULL
, 0x0, NULL
, HFILL
}},
583 { &hf_udpcp_message_data_length
,
584 { "Message Data Length", "udpcp.message-data-length", FT_UINT16
, BASE_DEC
,
585 NULL
, 0x0, NULL
, HFILL
}},
588 { "Payload", "udpcp.payload", FT_BYTES
, BASE_SHOW_ASCII_PRINTABLE
,
589 NULL
, 0x0, "Complete or reassembled payload", HFILL
}},
592 { &hf_udpcp_fragment
,
593 { "Fragment", "udpcp.fragment", FT_FRAMENUM
, BASE_NONE
,
594 NULL
, 0x0, NULL
, HFILL
}},
595 { &hf_udpcp_fragments
,
596 { "Fragments", "udpcp.fragments", FT_BYTES
, BASE_NONE
,
597 NULL
, 0x0, NULL
, HFILL
}},
598 { &hf_udpcp_fragment_overlap
,
599 { "Fragment overlap", "udpcp.fragment.overlap", FT_BOOLEAN
, BASE_NONE
,
600 NULL
, 0x0, "Fragment overlaps with other fragments", HFILL
}},
601 { &hf_udpcp_fragment_overlap_conflict
,
602 { "Conflicting data in fragment overlap", "udpcp.fragment.overlap.conflict",
603 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
604 "Overlapping fragments contained conflicting data", HFILL
}},
605 { &hf_udpcp_fragment_multiple_tails
,
606 { "Multiple tail fragments found", "udpcp.fragment.multipletails",
607 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
608 "Several tails were found when defragmenting the packet", HFILL
}},
609 { &hf_udpcp_fragment_too_long_fragment
,
610 { "Fragment too long", "udpcp.fragment.toolongfragment",
611 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
612 "Fragment contained data past end of packet", HFILL
}},
613 { &hf_udpcp_fragment_error
,
614 { "Defragmentation error", "udpcp.fragment.error", FT_FRAMENUM
, BASE_NONE
,
615 NULL
, 0x0, "Defragmentation error due to illegal fragments", HFILL
}},
616 { &hf_udpcp_fragment_count
,
617 { "Fragment count", "udpcp.fragment.count", FT_UINT32
, BASE_DEC
,
618 NULL
, 0x0, NULL
, HFILL
}},
619 { &hf_udpcp_reassembled_in
,
620 { "Reassembled payload in frame", "udpcp.reassembled_in", FT_FRAMENUM
, BASE_NONE
,
621 NULL
, 0x0, "This payload packet is reassembled in this frame", HFILL
}},
622 { &hf_udpcp_reassembled_length
,
623 { "Reassembled payload length", "udpcp.reassembled.length", FT_UINT32
, BASE_DEC
,
624 NULL
, 0x0, "The total length of the reassembled payload", HFILL
}},
625 { &hf_udpcp_reassembled_data
,
626 { "Reassembled data", "udpcp.reassembled.data", FT_BYTES
, BASE_NONE
,
627 NULL
, 0x0, "The reassembled payload", HFILL
}},
629 { &hf_udpcp_ack_frame
,
630 { "Ack Frame", "udpcp.ack-frame", FT_FRAMENUM
, BASE_NONE
,
631 NULL
, 0x0, "Frame that ACKs this data", HFILL
}},
632 { &hf_udpcp_sn_frame
,
633 { "SN Frame", "udpcp.sn-frame", FT_FRAMENUM
, BASE_NONE
,
634 NULL
, 0x0, "Data frame ACKd by this one", HFILL
}},
637 static int *ett
[] = {
639 &ett_udpcp_packet_transfer_options
,
640 &ett_udpcp_fragments
,
644 static ei_register_info ei
[] = {
645 { &ei_udpcp_checksum_should_be_zero
, { "udpcp.checksum-not-zero", PI_CHECKSUM
, PI_WARN
, "Checksum should be zero if !C.", EXPFILL
}},
646 { &ei_udpcp_d_not_zero_for_data
, { "udpcp.d-not-zero-data", PI_SEQUENCE
, PI_ERROR
, "D should be zero for data frames", EXPFILL
}},
647 { &ei_udpcp_reserved_not_zero
, { "udpcp.reserved-not-zero", PI_MALFORMED
, PI_WARN
, "Reserved bits not zero", EXPFILL
}},
648 { &ei_udpcp_n_s_ack
, { "udpcp.n-s-set-ack", PI_MALFORMED
, PI_ERROR
, "N or S set for ACK frame", EXPFILL
}},
649 { &ei_udpcp_payload_wrong_size
, { "udpcp.payload-wrong-size", PI_MALFORMED
, PI_ERROR
, "Payload seen does not match size field", EXPFILL
}},
650 { &ei_udpcp_wrong_sequence_number
, { "udpcp.sequence-number-wrong", PI_SEQUENCE
, PI_WARN
, "Unexpected sequence number", EXPFILL
}},
651 { &ei_udpcp_no_ack
, { "udpcp.no-ack", PI_SEQUENCE
, PI_WARN
, "No ACK seen for data frame", EXPFILL
}},
652 { &ei_udpcp_no_sn_frame
, { "udpcp.no-sn-frame", PI_SEQUENCE
, PI_WARN
, "No SN frame seen for ACK", EXPFILL
}},
655 module_t
*udpcp_module
;
656 expert_module_t
*expert_udpcp
;
658 proto_udpcp
= proto_register_protocol("UDPCP", "UDPCP", "udpcp");
659 proto_register_field_array(proto_udpcp
, hf
, array_length(hf
));
660 proto_register_subtree_array(ett
, array_length(ett
));
661 expert_udpcp
= expert_register_protocol(proto_udpcp
);
662 expert_register_field_array(expert_udpcp
, ei
, array_length(ei
));
664 udpcp_handle
= register_dissector("udpcp", dissect_udpcp
, proto_udpcp
);
666 /* Register reassembly table. */
667 reassembly_table_register(&udpcp_reassembly_table
,
668 &udpcp_reassembly_table_functions
);
671 udpcp_module
= prefs_register_protocol(proto_udpcp
, NULL
);
673 /* Payload reassembly */
674 prefs_register_bool_preference(udpcp_module
, "attempt_reassembly",
675 "Reassemble payload",
677 &global_udpcp_reassemble
);
679 /* Whether to try XML dissector on payload.
680 * TODO: are there any other payload types we might see? */
681 prefs_register_bool_preference(udpcp_module
, "attempt_xml_decode",
682 "Call XML dissector for payload",
684 &global_udpcp_decode_payload_as_soap
);
686 sequence_number_result_table
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
690 apply_udpcp_prefs(void)
692 global_udpcp_port_range
= prefs_get_range_value("udpcp", "udp.port");
696 proto_reg_handoff_udpcp(void)
698 dissector_add_uint_range_with_preference("udp.port", "", udpcp_handle
);
701 xml_handle
= find_dissector("xml");
705 * Editor modelines - https://www.wireshark.org/tools/modelines.html
710 * indent-tabs-mode: nil
713 * vi: set shiftwidth=4 tabstop=8 expandtab:
714 * :indentSize=4:tabSize=8:noTabs=true: