aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-p_mul.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2005-11-07 19:35:48 +0000
committerAnders Broman <anders.broman@ericsson.com>2005-11-07 19:35:48 +0000
commit8586ce47d2f318a5f3d1037d246b61655c7505ad (patch)
treefdfe0e4a2f8952a8c944801297af30c816ee7d2f /epan/dissectors/packet-p_mul.c
parent60c4c050d05daeda20a9a09647fb44d67f30855a (diff)
From Stig Bjørlykke
A new dissector for P_Mul (ACP142) http://www.jcs.mil/j6/cceb/acps/Acp142.pdf svn path=/trunk/; revision=16417
Diffstat (limited to 'epan/dissectors/packet-p_mul.c')
-rw-r--r--epan/dissectors/packet-p_mul.c577
1 files changed, 577 insertions, 0 deletions
diff --git a/epan/dissectors/packet-p_mul.c b/epan/dissectors/packet-p_mul.c
new file mode 100644
index 0000000000..070170f610
--- /dev/null
+++ b/epan/dissectors/packet-p_mul.c
@@ -0,0 +1,577 @@
+/* packet-p_mul.c
+ *
+ * Routines for P_Mul (ACP142) packet disassembly.
+ * A protocol for reliable multicast messaging in bandwidth constrained
+ * and delayed acknowledgement (EMCON) environments.
+ *
+ * Copyright 2005, Stig Bj›rlykke <stig@bjorlykke.org>, Thales Norway AS
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Ref: http://www.jcs.mil/j6/cceb/acps/Acp142.pdf
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/to_str.h>
+#include <epan/prefs.h>
+
+
+/* Recommended UDP Port Numbers */
+#define P_MUL_TPORT 2751
+#define P_MUL_RPORT 2752
+#define P_MUL_DPORT 2753
+#define P_MUL_APORT 2754
+
+/* PDU Types */
+#define Data_PDU 0x00
+#define Ack_PDU 0x01
+#define Address_PDU 0x02
+#define Discard_Message_PDU 0x03
+#define Announce_PDU 0x04
+#define Request_PDU 0x05
+#define Reject_PDU 0x06
+#define Release_PDU 0x07
+
+void proto_reg_handoff_p_mul (void);
+
+static int proto_p_mul = -1;
+
+static int hf_length = -1;
+static int hf_priority = -1;
+static int hf_map_first = -1;
+static int hf_map_last = -1;
+static int hf_map_unused = -1;
+static int hf_pdu_type = -1;
+static int hf_no_pdus = -1;
+static int hf_seq_no = -1;
+static int hf_unused8 = -1;
+static int hf_unused16 = -1;
+static int hf_checksum = -1;
+static int hf_source_id_ack = -1;
+static int hf_source_id = -1;
+static int hf_message_id = -1;
+static int hf_expiry_time = -1;
+static int hf_mc_group = -1;
+static int hf_ann_mc_group = -1;
+static int hf_count_of_dest = -1;
+static int hf_length_of_res = -1;
+static int hf_ack_count = -1;
+static int hf_ack_entry = -1;
+static int hf_ack_length = -1;
+static int hf_miss_seq_no = -1;
+static int hf_dest_entry = -1;
+static int hf_dest_id = -1;
+static int hf_msg_seq_no = -1;
+static int hf_sym_key = -1;
+static int hf_fragment = -1;
+static int hf_error = -1;
+
+static gint ett_p_mul = -1;
+static gint ett_pdu_type = -1;
+static gint ett_entry = -1;
+
+/* User definable port numbers to use for dissection */
+static guint global_p_mul_tport = P_MUL_TPORT;
+static guint global_p_mul_rport = P_MUL_RPORT;
+static guint global_p_mul_dport = P_MUL_DPORT;
+static guint global_p_mul_aport = P_MUL_APORT;
+static guint p_mul_tport = 0;
+static guint p_mul_rport = 0;
+static guint p_mul_dport = 0;
+static guint p_mul_aport = 0;
+
+static const value_string pdu_vals[] = {
+ { Data_PDU, "Data PDU" },
+ { Ack_PDU, "Ack PDU" },
+ { Address_PDU, "Address PDU" },
+ { Discard_Message_PDU, "Discard Message PDU" },
+ { Announce_PDU, "Announce PDU" },
+ { Request_PDU, "Request PDU" },
+ { Reject_PDU, "Reject PDU" },
+ { Release_PDU, "Release PDU" },
+ { 0, NULL } };
+
+static const true_false_string yes_no = {
+ "No", "Yes"
+};
+
+static const gchar *get_type (guint8 value)
+{
+ return val_to_str (value, pdu_vals, "Unknown");
+}
+
+/*Function checksum, found in ACP142 annex B-3 */
+static guint16 checksum (guint8 *buffer, gint len, gint offset)
+{
+ guint16 c0 = 0, c1 = 0, ret, ctmp;
+ gint16 cs;
+ guint8 *hpp, *pls;
+
+ buffer[offset] = 0;
+ buffer[offset+1] = 0;
+ ctmp = len - offset - 1;
+
+ pls = buffer + len;
+ hpp = buffer;
+
+ while (hpp < pls) {
+ if ((c0 += *hpp++) > 254) { c0 -= 255; }
+ if ((c1 += c0) > 254) { c1 -= 255; }
+ }
+
+ if ((cs = ((ctmp * c0) - c1) % 255L) < 0) { cs += 255; }
+ ret = cs << 8;
+ if ((cs = (c1 - ((ctmp + 1L) * c0)) % 255L) < 0) { cs += 255; }
+ ret |= cs;
+
+ return ret;
+}
+
+static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree *p_mul_tree = NULL, *field_tree = NULL;
+ proto_item *ti = NULL, *en = NULL;
+ guint32 message_id = 0, no_pdus = 0, seq_no = 0;
+ guint16 no_dest = 0, count = 0, len = 0, checksum1, checksum2;
+ guint8 pdu_type = 0, *value = NULL, map = 0;
+ gint i, no_missing = 0, offset = 0;
+ nstime_t ts;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "P_MUL");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* First fetch PDU Type */
+ pdu_type = tvb_get_guint8 (tvb, offset + 3) & 0x3F;
+
+ proto_item_append_text (ti, ", %s", get_type (pdu_type));
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", get_type (pdu_type));
+ }
+
+ ti = proto_tree_add_item (tree, proto_p_mul, tvb, offset, -1, FALSE);
+ p_mul_tree = proto_item_add_subtree (ti, ett_p_mul);
+
+ /* Length of PDU */
+ proto_tree_add_item (p_mul_tree, hf_length, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ switch (pdu_type) {
+
+ case Data_PDU:
+ case Ack_PDU:
+ case Address_PDU:
+ case Discard_Message_PDU:
+ /* Priority */
+ proto_tree_add_item (p_mul_tree, hf_priority, tvb, offset, 1, FALSE);
+ break;
+
+ default:
+ /* Unused */
+ proto_tree_add_item (p_mul_tree, hf_unused8, tvb, offset, 1, FALSE);
+ }
+ offset += 1;
+
+ /* MAP / PDU_Type */
+ en = proto_tree_add_uint_format (p_mul_tree, hf_pdu_type, tvb, offset, 1,
+ pdu_type, "PDU Type: %s (0x%02x)",
+ get_type (pdu_type), pdu_type);
+ field_tree = proto_item_add_subtree (en, ett_pdu_type);
+
+ switch (pdu_type) {
+
+ case Address_PDU:
+ case Announce_PDU:
+ map = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (field_tree, hf_map_first, tvb, offset, 1, FALSE);
+ proto_tree_add_item (field_tree, hf_map_last, tvb, offset, 1, FALSE);
+ if ((map & 0x80) || (map & 0x40)) {
+ proto_item_append_text (en, ", %s / %s",
+ (map & 0x80) ? "Not first" : "First",
+ (map & 0x40) ? "Not last" : "Last");
+ } else {
+ proto_item_append_text (en, ", Only one PDU");
+ }
+ break;
+
+ default:
+ proto_tree_add_item (field_tree, hf_map_unused, tvb, offset, 1, FALSE);
+ break;
+ }
+ proto_tree_add_item (field_tree, hf_pdu_type, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ switch (pdu_type) {
+
+ case Address_PDU:
+ /* Total Number of PDUs */
+ no_pdus = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_item (p_mul_tree, hf_no_pdus, tvb, offset, 2, FALSE);
+ break;
+
+ case Data_PDU:
+ /* Sequence Number of PDUs */
+ seq_no = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_item (p_mul_tree, hf_seq_no, tvb, offset, 2, FALSE);
+ break;
+
+ case Announce_PDU:
+ /* Count of Destination Entries */
+ count = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_item (p_mul_tree, hf_count_of_dest, tvb, offset, 2,FALSE);
+ break;
+
+ default:
+ /* Unused */
+ proto_tree_add_item (p_mul_tree, hf_unused16, tvb, offset, 2, FALSE);
+ break;
+ }
+ offset += 2;
+
+ /* Checksum */
+ len = tvb_length (tvb);
+ value = tvb_get_string (tvb, 0, len);
+ checksum1 = checksum (value, len, offset);
+ checksum2 = tvb_get_ntohs (tvb, offset);
+ g_free (value);
+ en = proto_tree_add_item (p_mul_tree, hf_checksum, tvb, offset, 2, FALSE);
+ if (checksum1 == checksum2) {
+ proto_item_append_text (en, " (correct)");
+ } else {
+ proto_item_append_text (en, " (incorrect, should be 0x%04x)", checksum1);
+ }
+ offset += 2;
+
+ if (pdu_type == Ack_PDU) {
+ /* Source ID of Ack Sender */
+ proto_tree_add_item (p_mul_tree, hf_source_id_ack, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Count of Ack Info Entries */
+ count = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_item (p_mul_tree, hf_ack_count, tvb, offset, 2, FALSE);
+ offset += 2;
+ } else {
+ /* Source Id */
+ proto_tree_add_item (p_mul_tree, hf_source_id, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Message Id */
+ message_id = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_item (p_mul_tree, hf_message_id, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+
+ if (pdu_type == Address_PDU || pdu_type == Announce_PDU) {
+ /* Expiry Time */
+ ts.secs = tvb_get_ntohl (tvb, offset);
+ ts.nsecs = 0;
+ proto_tree_add_time (p_mul_tree, hf_expiry_time, tvb, offset, 4, &ts);
+ offset += 4;
+ }
+
+ switch (pdu_type) {
+
+ case Address_PDU:
+ /* Count of Destination Entries */
+ no_dest = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_item (p_mul_tree, hf_count_of_dest, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Length of Reserved Field */
+ len = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_item (p_mul_tree, hf_length_of_res, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ for (i = 0; i < no_dest; i++) {
+ /* Destination Entry */
+ en = proto_tree_add_none_format (p_mul_tree, hf_dest_entry, tvb,
+ offset, no_dest * (8 + len),
+ "Destination Entry #%d", i + 1);
+ field_tree = proto_item_add_subtree (en, ett_entry);
+
+ /* Destination Id */
+ proto_tree_add_item (field_tree, hf_dest_id, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Message Sequence Number */
+ proto_tree_add_item (field_tree, hf_msg_seq_no, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ if (len > 0) {
+ /* Reserved Field (variable length) */
+ proto_tree_add_none_format (field_tree, hf_sym_key, tvb, offset,
+ len, "Symmetric Key (%d byte%s)",
+ len, plurality (len, "", "s"));
+ offset += len;
+ }
+ }
+ break;
+
+ case Data_PDU:
+ /* Fragment of Data (variable length) */
+ len = tvb_length_remaining (tvb, offset);
+ if (len > 0) {
+ proto_tree_add_none_format (tree, hf_fragment, tvb, offset,
+ len, "Fragment of Data (%d byte%s)",
+ len, plurality (len, "", "s"));
+ proto_item_set_len (ti, offset);
+ }
+ offset += len;
+ break;
+
+ case Ack_PDU:
+ for (i = 0; i < count; i++) {
+ /* Ack Info Entry */
+ len = tvb_get_ntohs (tvb, offset);
+
+ en = proto_tree_add_none_format (p_mul_tree, hf_ack_entry, tvb,
+ offset, count * len,
+ "Ack Info Entry #%d", i + 1);
+ field_tree = proto_item_add_subtree (en, ett_entry);
+
+ /* Length of Ack Info Entry */
+ proto_tree_add_item (field_tree, hf_ack_length, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Source Id */
+ proto_tree_add_item (field_tree, hf_source_id, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Message Id */
+ proto_tree_add_item (field_tree, hf_message_id, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ for (no_missing = 0; no_missing < (len - 10) / 2; no_missing++) {
+ /* Missing Data PDU Seq Number */
+ proto_tree_add_item (field_tree, hf_miss_seq_no, tvb,offset, 2, FALSE);
+ offset += 2;
+ }
+ }
+ break;
+
+ case Announce_PDU:
+ /* Announced Multicast Group */
+ proto_tree_add_item (p_mul_tree, hf_ann_mc_group, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ for (i = 0; i < count; i++) {
+ /* Destination Id */
+ proto_tree_add_item (p_mul_tree, hf_dest_id, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ break;
+
+ case Request_PDU:
+ case Reject_PDU:
+ case Release_PDU:
+ /* Multicast Group */
+ proto_tree_add_item (p_mul_tree, hf_mc_group, tvb, offset, 4, FALSE);
+ offset += 4;
+ break;
+
+ default:
+ /* Nothing */
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (seq_no) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", Seq no: %u", seq_no);
+ } else if (no_pdus) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", No PDUs: %u", no_pdus);
+ }
+ if (no_missing) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", Missing seq numbers: %u",
+ no_missing);
+ } else if (pdu_type == Address_PDU) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", Count of Dest: %u",
+ no_dest);
+ }
+ if (message_id) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", MSID: %u", message_id);
+ }
+ }
+}
+
+void proto_register_p_mul (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_length,
+ { "Length of PDU", "p_mul.length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of PDU", HFILL } },
+ { &hf_priority,
+ { "Priority", "p_mul.priority", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Priority", HFILL } },
+ { &hf_map_first,
+ { "First", "p_mul.first", FT_BOOLEAN, 8,
+ TFS (&yes_no), 0x80, "First", HFILL } },
+ { &hf_map_last,
+ { "Last", "p_mul.last", FT_BOOLEAN, 8,
+ TFS (&yes_no), 0x40, "Last", HFILL } },
+ { &hf_map_unused,
+ { "MAP unused", "p_mul.unused", FT_UINT8, BASE_DEC,
+ NULL, 0xC0, "MAP unused", HFILL } },
+ { &hf_pdu_type,
+ { "PDU Type", "p_mul.pdu_type", FT_UINT8, BASE_DEC,
+ VALS (pdu_vals), 0x3F, "PDU Type", HFILL } },
+ { &hf_no_pdus,
+ { "Total Number of PDUs", "p_mul.no_pdus", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Total Number of PDUs", HFILL } },
+ { &hf_seq_no,
+ { "Sequence Number of PDUs", "p_mul.seq_no", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Sequence Number of PDUs", HFILL } },
+ { &hf_unused8,
+ { "Unused", "p_mul.unused", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Unused", HFILL } },
+ { &hf_unused16,
+ { "Unused", "p_mul.unused", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Unused", HFILL } },
+ { &hf_checksum,
+ { "Checksum", "p_mul.checksum", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Checksum", HFILL } },
+ { &hf_source_id_ack,
+ { "Source ID of Ack Sender", "p_mul.source_id_ack", FT_IPv4, BASE_DEC,
+ NULL, 0x0, "Source ID of Ack Sender", HFILL } },
+ { &hf_source_id,
+ { "Source ID", "p_mul.source_id", FT_IPv4, BASE_DEC,
+ NULL, 0x0, "Source ID", HFILL } },
+ { &hf_message_id,
+ { "Message ID (MSID)", "p_mul.message_id", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Message ID", HFILL } },
+ { &hf_expiry_time,
+ { "Expiry Time", "p_mul.expiry_time", FT_ABSOLUTE_TIME, BASE_DEC,
+ NULL, 0x0, "Expiry Time", HFILL } },
+ { &hf_mc_group,
+ { "Multicast Group", "p_mul.mc_group", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Multicast Group", HFILL } },
+ { &hf_ann_mc_group,
+ { "Announced Multicast Group", "p_mul.ann_mc_group", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Announced Multicast Group", HFILL } },
+ { &hf_count_of_dest,
+ { "Count of Destination Entries", "p_mul.dest_count", FT_UINT16,BASE_DEC,
+ NULL, 0x0, "Count of Destination Entries", HFILL } },
+ { &hf_length_of_res,
+ { "Length of Reserved Field", "p_mul.reserved_length",FT_UINT16,BASE_DEC,
+ NULL, 0x0, "Length of Reserved Field", HFILL } },
+ { &hf_ack_count,
+ { "Count of Ack Info Entries", "p_mul.ack_count", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Count of Ack Info Entries", HFILL } },
+ { &hf_ack_entry,
+ { "Ack Info Entry", "p_mul.ack_info_entry", FT_NONE, BASE_NONE,
+ NULL, 0x0, "Ack Info Entry", HFILL } },
+ { &hf_ack_length,
+ { "Length of Ack Info Entry", "p_mul.ack_length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of Ack Info Entry", HFILL } },
+ { &hf_miss_seq_no,
+ { "Missing Data PDU Seq Number", "p_mul.missing_seq_no", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "Missing Data PDU Seq Number", HFILL } },
+ { &hf_dest_entry,
+ { "Destination Entry", "p_mul.dest_entry", FT_NONE, BASE_NONE,
+ NULL, 0x0, "Destination Entry", HFILL } },
+ { &hf_dest_id,
+ { "Destination ID", "p_mul.dest_id", FT_IPv4, BASE_DEC,
+ NULL, 0x0, "Destination ID", HFILL } },
+ { &hf_msg_seq_no,
+ { "Message Sequence Number", "p_mul.msg_seq_no", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Message Sequence Number", HFILL } },
+ { &hf_sym_key,
+ { "Symmetric Key", "p_mul.sym_key", FT_NONE, BASE_NONE,
+ NULL, 0x0, "Symmetric Key", HFILL } },
+ { &hf_fragment,
+ { "Fragment of Data", "p_mul.fragment", FT_NONE, BASE_NONE,
+ NULL, 0x0, "Fragment of Data", HFILL } },
+ { &hf_error,
+ { "Error reading data", "p_mul.error", FT_NONE, BASE_NONE,
+ NULL, 0x0, "Error reading data", HFILL } },
+ };
+
+ static gint *ett[] = {
+ &ett_p_mul,
+ &ett_pdu_type,
+ &ett_entry
+ };
+
+ module_t *p_mul_module;
+
+ proto_p_mul = proto_register_protocol ("P_Mul (ACP142)", "P_MUL", "p_mul");
+
+ proto_register_field_array (proto_p_mul, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+
+ /* Register our configuration options */
+ p_mul_module = prefs_register_protocol (proto_p_mul,
+ proto_reg_handoff_p_mul);
+
+ prefs_register_uint_preference (p_mul_module, "tport", "TPORT",
+ "Used for transmission of Request_PDUs, "
+ "Reject_PDUs and Release_PDUs between"
+ "the transmitters",
+ 10, &global_p_mul_tport);
+ prefs_register_uint_preference (p_mul_module, "rport", "RPORT",
+ "Used for transmission of Announce_PDUs "
+ "to inform the receiver(s)",
+ 10, &global_p_mul_rport);
+ prefs_register_uint_preference (p_mul_module, "dport", "DPORT",
+ "Used for the data traffic from the "
+ "transmitters to the receiver(s)",
+ 10, &global_p_mul_dport);
+ prefs_register_uint_preference (p_mul_module, "aport", "APORT",
+ "Used for the data traffic from the "
+ "receiver(s) to the transmitter",
+ 10, &global_p_mul_aport);
+}
+
+void proto_reg_handoff_p_mul (void)
+{
+ static int p_mul_prefs_initialized = FALSE;
+ static dissector_handle_t p_mul_handle;
+
+ if (!p_mul_prefs_initialized) {
+ p_mul_handle = create_dissector_handle (dissect_p_mul, proto_p_mul);
+ p_mul_prefs_initialized = TRUE;
+ } else {
+ dissector_delete ("udp.port", p_mul_tport, p_mul_handle);
+ dissector_delete ("udp.port", p_mul_rport, p_mul_handle);
+ dissector_delete ("udp.port", p_mul_dport, p_mul_handle);
+ dissector_delete ("udp.port", p_mul_aport, p_mul_handle);
+ }
+
+ /* Save port numbers for later deletion */
+ p_mul_tport = global_p_mul_tport;
+ p_mul_rport = global_p_mul_rport;
+ p_mul_dport = global_p_mul_dport;
+ p_mul_aport = global_p_mul_aport;
+
+ /* We convert all P_Mul ports */
+ dissector_add ("udp.port", global_p_mul_tport, p_mul_handle);
+ dissector_add ("udp.port", global_p_mul_rport, p_mul_handle);
+ dissector_add ("udp.port", global_p_mul_dport, p_mul_handle);
+ dissector_add ("udp.port", global_p_mul_aport, p_mul_handle);
+}