diff options
author | Michael Mann <mmann78@netscape.net> | 2013-02-01 01:29:58 +0000 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2013-02-01 01:29:58 +0000 |
commit | 73d339a5a469b18c7d222a93c252c1f1568e4f19 (patch) | |
tree | 0ad3315f66a3a78900f6764df7c3b213e50b89a5 /epan/dissectors/packet-nat-pmp.c | |
parent | 52baba10a2393440c2f2af7fb7814def8ced2cbf (diff) |
Add Port Control Protocol dissector and convert NAT-PMP dissector to "new" style.
The Port Control Protocol overtakes the NAT-PMP IANA UDP ports, but is backwards compatible enough to trigger off of the version number (NAT-PMP is version 0). NAT-PMP can still use Decode As.
Left the two dissectors with their own unique display filters despite a few overlapping fields. Didn't want it to turn into a BOOTP/DHCP situation.
svn path=/trunk/; revision=47405
Diffstat (limited to 'epan/dissectors/packet-nat-pmp.c')
-rw-r--r-- | epan/dissectors/packet-nat-pmp.c | 503 |
1 files changed, 488 insertions, 15 deletions
diff --git a/epan/dissectors/packet-nat-pmp.c b/epan/dissectors/packet-nat-pmp.c index ed435a96c7..473446e0b8 100644 --- a/epan/dissectors/packet-nat-pmp.c +++ b/epan/dissectors/packet-nat-pmp.c @@ -5,6 +5,14 @@ * * Copyright 2009, Stig Bjorlykke <stig@bjorlykke.org> * + * Routines for Port Control Protocol packet disassembly + * (backwards compatible with NAT Port Mapping protocol) + * http://tools.ietf.org/html/draft-ietf-pcp-base-24 + * http://tools.ietf.org/html/draft-ietf-pcp-base-29 + * + * Copyright 2012, Michael Mann + * + * * $Id$ * * Wireshark - Network traffic analyzer @@ -31,14 +39,10 @@ #include <epan/packet.h> #include <epan/expert.h> -#define PNAME "NAT Port Mapping Protocol" -#define PSNAME "NAT-PMP" -#define PFNAME "nat-pmp" - -#define NAT_PMP_STATUS_PORT 5350 -#define NAT_PMP_PORT 5351 +#define PCP_STATUS_PORT 5350 +#define PCP_PORT 5351 -/* opcodes */ +/* NAT Port opcodes */ #define EXTERNAL_ADDRESS_REQUEST 0 #define MAP_UDP_REQUEST 1 #define MAP_TCP_REQUEST 2 @@ -46,7 +50,21 @@ #define MAP_UDP_RESPONSE 129 #define MAP_TCP_RESPONSE 130 +/* Port Control opcodes */ +#define ANNOUNCE_REQUEST 0 +#define MAP_REQUEST 1 +#define PEER_REQUEST 2 +#define ANNOUNCE_RESPONSE 128 +#define MAP_RESPONSE 129 +#define PEER_RESPONSE 130 + +/* Port Control options */ +#define OPT_THIRD_PARTY 1 +#define OPT_PREFER_FAILURE 2 +#define OPT_FILTER 3 + static int proto_nat_pmp = -1; +static int proto_pcp = -1; static int hf_version = -1; static int hf_opcode = -1; @@ -62,6 +80,53 @@ static int hf_pmlis = -1; static gint ett_nat_pmp = -1; +/* Port Control Protocol */ +static int hf_pcp_version = -1; +static int hf_request = -1; +static int hf_response = -1; +static int hf_pcp_opcode = -1; +static int hf_pcp_result_code = -1; +static int hf_reserved1 = -1; +static int hf_reserved2 = -1; +static int hf_reserved8 = -1; +static int hf_req_lifetime = -1; +static int hf_rsp_lifetime = -1; +static int hf_client_ip = -1; +static int hf_epoch_time = -1; +static int hf_map_nonce = -1; +static int hf_map_protocol = -1; +static int hf_map_reserved1 = -1; +static int hf_map_internal_port = -1; +static int hf_map_req_sug_external_port = -1; +static int hf_map_req_sug_ext_ip = -1; +static int hf_map_rsp_assigned_external_port = -1; +static int hf_map_rsp_assigned_ext_ip = -1; +static int hf_peer_nonce = -1; +static int hf_peer_protocol = -1; +static int hf_peer_reserved1 = -1; +static int hf_peer_internal_port = -1; +static int hf_peer_req_sug_external_port = -1; +static int hf_peer_req_sug_ext_ip = -1; +static int hf_peer_remote_peer_port = -1; +static int hf_peer_reserved2 = -1; +static int hf_peer_remote_peer_ip = -1; +static int hf_peer_rsp_assigned_external_port = -1; +static int hf_peer_rsp_assigned_ext_ip = -1; +static int hf_option_code = -1; +static int hf_option_reserved = -1; +static int hf_option_length = -1; +static int hf_option_third_party_internal_ip = -1; +static int hf_option_filter_reserved = -1; +static int hf_option_filter_prefix_length = -1; +static int hf_option_filter_remote_peer_port = -1; +static int hf_option_filter_remote_peer_ip = -1; + +static gint ett_pcp = -1; +static gint ett_opcode = -1; +static gint ett_option = -1; +static gint ett_suboption = -1; + + static const value_string opcode_vals[] = { { EXTERNAL_ADDRESS_REQUEST, "External Address Request" }, { EXTERNAL_ADDRESS_RESPONSE, "External Address Response" }, @@ -82,16 +147,54 @@ static const value_string result_vals[] = { { 0, NULL } }; -static void dissect_nat_pmp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static const value_string pcp_opcode_vals[] = { + { ANNOUNCE_REQUEST, "Announce Request" }, + { MAP_REQUEST, "Map Request" }, + { PEER_REQUEST, "Peer Request" }, + { ANNOUNCE_RESPONSE, "Announce Response" }, + { MAP_RESPONSE, "Map Response" }, + { PEER_RESPONSE, "Peer Response" }, + { 0, NULL } +}; + +static const value_string pcp_result_vals[] = { + { 0, "Success" }, + { 1, "Unsupported Version" }, + { 2, "Not Authorized/Refused" }, + { 3, "Malformed Request" }, + { 4, "Unsupported opcode" }, + { 5, "Unsupported option" }, + { 6, "Malformed option" }, + { 7, "Network failure" }, + { 8, "No resources" }, + { 9, "Unsupported protocol" }, + { 10, "User exceeds quota" }, + { 11, "Cannot provide external port" }, + { 12, "Address mismatch" }, + { 13, "Excessive remote peers" }, + { 0, NULL } +}; + +static const value_string pcp_option_vals[] = { + { 0, "Reserved" }, + { OPT_THIRD_PARTY, "Third Party" }, + { OPT_PREFER_FAILURE, "Prefer Failure" }, + { OPT_FILTER, "Filter" }, + { 0, NULL } +}; + +static int +dissect_nat_pmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { proto_tree *nat_pmp_tree; proto_item *ti, *op_ti; - gint offset = 0; + gint start_offset, offset = 0; guint8 opcode; - col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME); + col_set_str (pinfo->cinfo, COL_PROTOCOL, "NAT-PMP"); col_clear (pinfo->cinfo, COL_INFO); + start_offset = offset; ti = proto_tree_add_item (tree, proto_nat_pmp, tvb, offset, -1, ENC_NA); nat_pmp_tree = proto_item_add_subtree (ti, ett_nat_pmp); @@ -160,6 +263,235 @@ static void dissect_nat_pmp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree expert_add_info_format (pinfo, op_ti, PI_RESPONSE_CODE, PI_WARN, "Unknown opcode: %d", opcode); break; } + + return (offset-start_offset); +} + +static int +dissect_portcontrol_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 version) +{ + proto_tree *pcp_tree, *opcode_tree = NULL, *option_tree, *option_sub_tree; + proto_item *ti, *opcode_ti, *option_ti, *suboption_ti; + gint offset = 0, start_offset, start_opcode_offset, start_option_offset; + guint8 opcode, option; + guint16 option_length; + gboolean is_response; + const gchar* op_str; + + if (version == 1) + col_set_str (pinfo->cinfo, COL_PROTOCOL, "PCP v1"); + else + col_set_str (pinfo->cinfo, COL_PROTOCOL, "PCP v2"); + col_clear (pinfo->cinfo, COL_INFO); + + start_offset = offset; + ti = proto_tree_add_item (tree, proto_pcp, tvb, offset, -1, ENC_NA); + pcp_tree = proto_item_add_subtree (ti, ett_pcp); + + proto_tree_add_item (pcp_tree, hf_pcp_version, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + opcode = tvb_get_guint8 (tvb, offset); + is_response = opcode & 0x80; + op_str = val_to_str (opcode, opcode_vals, "Unknown opcode: %d"); + proto_item_append_text (ti, ", %s", op_str); + opcode_ti = proto_tree_add_item (pcp_tree, hf_pcp_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + col_add_str (pinfo->cinfo, COL_INFO, op_str); + + if (!is_response) + { + ti = proto_tree_add_boolean(pcp_tree, hf_request, tvb, offset-1, 1, is_response == FALSE); + PROTO_ITEM_SET_HIDDEN(ti); + + proto_tree_add_item (pcp_tree, hf_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + proto_tree_add_item (pcp_tree, hf_req_lifetime, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + proto_tree_add_item (pcp_tree, hf_client_ip, tvb, offset, 16, ENC_NA); + offset+=16; + } + else + { + ti = proto_tree_add_boolean(pcp_tree, hf_response, tvb, offset-1, 1, is_response == TRUE); + PROTO_ITEM_SET_HIDDEN(ti); + + proto_tree_add_item (pcp_tree, hf_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item (pcp_tree, hf_pcp_result_code, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item (pcp_tree, hf_rsp_lifetime, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + proto_tree_add_item (pcp_tree, hf_epoch_time, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + proto_tree_add_item (pcp_tree, hf_reserved8, tvb, offset, 8, ENC_NA); + offset+=8; + } + + start_opcode_offset = offset; + if (match_strval(opcode, opcode_vals) != NULL) + { + opcode_ti = proto_tree_add_text(pcp_tree, tvb, offset, 0, op_str); + opcode_tree = proto_item_add_subtree (opcode_ti, ett_opcode); + } + + switch(opcode) { + + case ANNOUNCE_REQUEST: + case ANNOUNCE_RESPONSE: + /* No data */ + break; + case MAP_REQUEST: + case MAP_RESPONSE: + if (version > 1) + { + proto_tree_add_item (opcode_tree, hf_map_nonce, tvb, offset, 12, ENC_NA); + offset+=12; + } + + proto_tree_add_item (opcode_tree, hf_map_protocol, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item (opcode_tree, hf_map_reserved1, tvb, offset, 3, ENC_BIG_ENDIAN); + offset+=3; + proto_tree_add_item (opcode_tree, hf_map_internal_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + if (opcode == MAP_REQUEST) + { + proto_tree_add_item (opcode_tree, hf_map_req_sug_external_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item (opcode_tree, hf_map_req_sug_ext_ip, tvb, offset, 16, ENC_NA); + offset+=16; + } + else + { + proto_tree_add_item (opcode_tree, hf_map_rsp_assigned_external_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item (opcode_tree, hf_map_rsp_assigned_ext_ip, tvb, offset, 16, ENC_NA); + offset+=16; + } + break; + case PEER_REQUEST: + case PEER_RESPONSE: + if (version > 1) + { + proto_tree_add_item (opcode_tree, hf_peer_nonce, tvb, offset, 12, ENC_NA); + offset+=12; + } + + proto_tree_add_item (opcode_tree, hf_peer_protocol, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item (opcode_tree, hf_peer_reserved1, tvb, offset, 3, ENC_BIG_ENDIAN); + offset+=3; + proto_tree_add_item (opcode_tree, hf_peer_internal_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + if (opcode == PEER_REQUEST) + { + proto_tree_add_item (opcode_tree, hf_peer_req_sug_external_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item (opcode_tree, hf_peer_req_sug_ext_ip, tvb, offset, 16, ENC_NA); + offset+=16; + } + else + { + proto_tree_add_item (opcode_tree, hf_peer_rsp_assigned_external_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item (opcode_tree, hf_peer_rsp_assigned_ext_ip, tvb, offset, 16, ENC_NA); + offset+=16; + } + + proto_tree_add_item (opcode_tree, hf_peer_remote_peer_port, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item (opcode_tree, hf_peer_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item (opcode_tree, hf_peer_remote_peer_ip, tvb, offset, 16, ENC_NA); + offset+=16; + break; + default: + /* Unknown OP */ + expert_add_info_format (pinfo, opcode_ti, PI_RESPONSE_CODE, PI_WARN, "Unknown opcode: %d", opcode); + break; + } + + /* Now see if there are any options for the supported opcodes */ + if ((tvb_reported_length_remaining(tvb, offset) > 0) && + (match_strval(opcode, opcode_vals) != NULL)) + { + start_option_offset = offset; + option_ti = proto_tree_add_text(opcode_tree, tvb, offset, 0, "Options"); + option_tree = proto_item_add_subtree (option_ti, ett_option); + + while (tvb_reported_length_remaining(tvb, offset) > 0) + { + option = tvb_get_guint8(tvb, offset); + suboption_ti = proto_tree_add_item (option_tree, hf_option_code, tvb, offset, 1, ENC_BIG_ENDIAN); + option_sub_tree = proto_item_add_subtree (suboption_ti, ett_suboption); + offset++; + proto_tree_add_item (option_sub_tree, hf_option_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + option_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item (option_sub_tree, hf_option_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + proto_item_set_len(suboption_ti, option_length+4); + + if (option_length > 0) + { + switch(option) { + + case OPT_THIRD_PARTY: + proto_tree_add_item (option_sub_tree, hf_option_third_party_internal_ip, tvb, offset, 16, ENC_NA); + break; + + case OPT_PREFER_FAILURE: + /* No data */ + break; + + case OPT_FILTER: + proto_tree_add_item (option_sub_tree, hf_option_filter_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item (option_sub_tree, hf_option_filter_prefix_length, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item (option_sub_tree, hf_option_filter_remote_peer_port, tvb, offset+2, 2, ENC_BIG_ENDIAN); + proto_tree_add_item (option_sub_tree, hf_option_filter_remote_peer_ip, tvb, offset+4, 16, ENC_BIG_ENDIAN); + break; + + default: + /* Unknown option */ + expert_add_info_format (pinfo, option_ti, PI_RESPONSE_CODE, PI_WARN, "Unknown option: %d", option); + break; + } + } + + offset+=option_length; + } + + proto_item_set_len(option_ti, offset-start_option_offset); + } + + proto_item_set_len(opcode_ti, offset-start_opcode_offset); + + return (offset-start_offset); +} + +static int +dissect_portcontrol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + guint8 version = tvb_get_guint8 (tvb, 0); + + switch(version) + { + case 0: + /* NAT-PMP protocol */ + return dissect_nat_pmp(tvb, pinfo, tree, data); + case 1: + case 2: + return dissect_portcontrol_pdu(tvb, pinfo, tree, version); + } + + return 0; } void proto_register_nat_pmp (void) @@ -200,24 +532,165 @@ void proto_register_nat_pmp (void) NULL, 0x0, "Port Mapping Lifetime in Seconds", HFILL } }, }; + static hf_register_info pcp_hf[] = { + { &hf_pcp_version, + { "Version", "portcontrol.version", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_request, + { "Request", "portcontrol.request", FT_BOOLEAN, 8, + NULL, 0x01, NULL, HFILL } }, + { &hf_response, + { "Response", "portcontrol.response", FT_BOOLEAN, 8, + NULL, 0x01, NULL, HFILL } }, + { &hf_pcp_opcode, + { "Opcode", "portcontrol.opcode", FT_UINT8, BASE_DEC, + VALS(pcp_opcode_vals), 0x0, NULL, HFILL } }, + { &hf_pcp_result_code, + { "Result Code", "portcontrol.result_code", FT_UINT16, BASE_DEC, + VALS(pcp_result_vals), 0x0, NULL, HFILL } }, + { &hf_reserved1, + { "Reserved", "portcontrol.reserved", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_reserved2, + { "Reserved", "portcontrol.reserved", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_reserved8, + { "Reserved", "portcontrol.rsp_reserved", FT_BYTES, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_req_lifetime, + { "Requested Lifetime", "portcontrol.lifetime_req", FT_UINT32, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_rsp_lifetime, + { "Lifetime", "portcontrol.lifetime_rsp", FT_UINT32, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_client_ip, + { "Client IP Address", "portcontrol.client_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_epoch_time, + { "Epoch Time", "portcontrol.epoch_time", FT_UINT32, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_nonce, + { "Mapping Nonce", "portcontrol.map.nonce", FT_BYTES, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_protocol, + { "Protocol", "portcontrol.map.protocol", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_reserved1, + { "Reserved", "portcontrol.map.reserved", FT_UINT24, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_internal_port, + { "Internal Port", "portcontrol.map.internal_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_req_sug_external_port, + { "Suggested External Port", "portcontrol.map.req_sug_external_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_req_sug_ext_ip, + { "Suggested External IP Address", "portcontrol.map.req_sug_external_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_rsp_assigned_external_port, + { "Assigned External Port", "portcontrol.map.rsp_assigned_external_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_map_rsp_assigned_ext_ip, + { "Assigned External IP Address", "portcontrol.map.rsp_assigned_ext_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_nonce, + { "Mapping Nonce", "portcontrol.peer.nonce", FT_BYTES, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_protocol, + { "Protocol", "portcontrol.peer.protocol", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_reserved1, + { "Reserved", "portcontrol.peer.reserved", FT_UINT24, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_internal_port, + { "Internal Port", "portcontrol.peer.internal_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_req_sug_external_port, + { "Suggested External Port", "portcontrol.peer.req_sug_external_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_req_sug_ext_ip, + { "Suggested External IP Address", "portcontrol.peer.req_sug_external_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_remote_peer_port, + { "Remote Peer Port", "portcontrol.peer.remote_peer_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_reserved2, + { "Reserved", "portcontrol.peer.reserved", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_remote_peer_ip, + { "Remote Peer IP Address", "portcontrol.peer.remote_peer_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_rsp_assigned_external_port, + { "Assigned External Port", "portcontrol.peer.rsp_assigned_external_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_peer_rsp_assigned_ext_ip, + { "Assigned External IP Address", "portcontrol.peer.rsp_assigned_ext_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_option_code, + { "Option", "portcontrol.option", FT_UINT8, BASE_DEC, + VALS(pcp_option_vals), 0x0, NULL, HFILL } }, + { &hf_option_reserved, + { "Reserved", "portcontrol.option.reserved", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_option_length, + { "Option Length", "portcontrol.option.length", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_option_third_party_internal_ip, + { "Internal IP Address", "portcontrol.option.third_party.internal_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + { &hf_option_filter_reserved, + { "Reserved", "portcontrol.option.filter.reserved", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_option_filter_prefix_length, + { "Prefix Length", "portcontrol.option.filter.prefix_length", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_option_filter_remote_peer_port, + { "Remote Peer Port", "portcontrol.option.filter.remote_peer_port", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL } }, + { &hf_option_filter_remote_peer_ip, + { "Remote Peer IP Address", "portcontrol.option.filter.remote_peer_ip", FT_IPv6, BASE_NONE, + NULL, 0x0, NULL, HFILL } }, + }; + + static gint *pcp_ett[] = { + &ett_pcp, + &ett_opcode, + &ett_option, + &ett_suboption + }; + static gint *ett[] = { &ett_nat_pmp, }; - proto_nat_pmp = proto_register_protocol (PNAME, PSNAME, PFNAME); - register_dissector (PFNAME, dissect_nat_pmp, proto_nat_pmp); + proto_nat_pmp = proto_register_protocol ("NAT Port Mapping Protocol", "NAT-PMP", "nat-pmp"); proto_register_field_array (proto_nat_pmp, hf, array_length (hf)); proto_register_subtree_array (ett, array_length (ett)); + + proto_pcp = proto_register_protocol ("Port Control Protocol", "Port Control", "portcontrol"); + + proto_register_field_array (proto_pcp, pcp_hf, array_length (pcp_hf)); + proto_register_subtree_array (pcp_ett, array_length (pcp_ett)); + } void proto_reg_handoff_nat_pmp (void) { dissector_handle_t nat_pmp_handle; + dissector_handle_t pcp_handle; + + + pcp_handle = new_create_dissector_handle(dissect_portcontrol, proto_pcp); + dissector_add_uint ("udp.port", PCP_STATUS_PORT, pcp_handle); + dissector_add_uint ("udp.port", PCP_PORT, pcp_handle); - nat_pmp_handle = find_dissector (PFNAME); - dissector_add_uint ("udp.port", NAT_PMP_STATUS_PORT, nat_pmp_handle); - dissector_add_uint ("udp.port", NAT_PMP_PORT, nat_pmp_handle); + nat_pmp_handle = new_create_dissector_handle(dissect_nat_pmp, proto_nat_pmp); + /* Port Control Protocol (packet-portcontrol.c) shares the same UDP ports as + NAT-PMP, but it backwards compatible. However, still let NAT-PMP + use Decode As + */ + dissector_add_handle("udp.port", nat_pmp_handle); } /* |