2 * Routines for NAT Port Mapping Protocol packet disassembly.
5 * Copyright 2009, Stig Bjorlykke <stig@bjorlykke.org>
7 * Routines for Port Control Protocol packet disassembly
8 * (backwards compatible with NAT Port Mapping protocol)
9 * RFC6887: Port Control Protocol (PCP) https://tools.ietf.org/html/rfc6887
11 * Copyright 2012, Michael Mann
13 * Description Option for the Port Control Protocol
15 * Discovering NAT64 IPv6 Prefixes Using the Port Control Protocol (PCP)
20 * Wireshark - Network traffic analyzer
21 * By Gerald Combs <gerald@wireshark.org>
22 * Copyright 1998 Gerald Combs
24 * SPDX-License-Identifier: GPL-2.0-or-later
29 #include <epan/packet.h>
30 #include <epan/expert.h>
32 #include <wsutil/array.h>
34 void proto_register_nat_pmp(void);
35 void proto_reg_handoff_nat_pmp(void);
37 static dissector_handle_t nat_pmp_handle
;
38 static dissector_handle_t pcp_handle
;
40 #define PCP_PORT_RANGE "5350-5351"
42 /* NAT Port opcodes */
43 #define EXTERNAL_ADDRESS_REQUEST 0
44 #define MAP_UDP_REQUEST 1
45 #define MAP_TCP_REQUEST 2
46 #define EXTERNAL_ADDRESS_RESPONSE 128
47 #define MAP_UDP_RESPONSE 129
48 #define MAP_TCP_RESPONSE 130
50 /* Port Control opcodes */
51 #define ANNOUNCE_REQUEST 0
53 #define PEER_REQUEST 2
54 #define ANNOUNCE_RESPONSE 128
55 #define MAP_RESPONSE 129
56 #define PEER_RESPONSE 130
58 /* Port Control options */
59 #define OPT_THIRD_PARTY 1
60 #define OPT_PREFER_FAILURE 2
62 #define OPT_DESCRIPTION 128
63 #define OPT_PREFIX64 129
64 #define OPT_PORT_SET 130
66 static int proto_nat_pmp
;
69 static int hf_version
;
71 static int hf_result_code
;
73 static int hf_external_ip
;
74 static int hf_reserved
;
75 static int hf_internal_port
;
76 static int hf_external_port_requested
;
77 static int hf_external_port_mapped
;
81 static int ett_nat_pmp
;
83 /* Port Control Protocol */
84 static int hf_pcp_version
;
85 static int hf_request
;
86 static int hf_response
;
88 static int hf_pcp_opcode
;
89 static int hf_pcp_result_code
;
90 static int hf_reserved1
;
91 static int hf_reserved2
;
92 static int hf_reserved12
;
93 static int hf_req_lifetime
;
94 static int hf_rsp_lifetime
;
95 static int hf_client_ip
;
96 static int hf_epoch_time
;
97 static int hf_map_nonce
;
98 static int hf_map_protocol
;
99 static int hf_map_reserved1
;
100 static int hf_map_internal_port
;
101 static int hf_map_req_sug_external_port
;
102 static int hf_map_req_sug_ext_ip
;
103 static int hf_map_rsp_assigned_external_port
;
104 static int hf_map_rsp_assigned_ext_ip
;
105 static int hf_peer_nonce
;
106 static int hf_peer_protocol
;
107 static int hf_peer_reserved
;
108 static int hf_peer_internal_port
;
109 static int hf_peer_req_sug_external_port
;
110 static int hf_peer_req_sug_ext_ip
;
111 static int hf_peer_remote_peer_port
;
112 static int hf_peer_remote_peer_ip
;
113 static int hf_peer_rsp_assigned_external_port
;
114 static int hf_peer_rsp_assigned_ext_ip
;
115 static int hf_options
;
116 static int hf_option
;
117 static int hf_option_code
;
118 static int hf_option_reserved
;
119 static int hf_option_length
;
120 static int hf_option_third_party_internal_ip
;
121 static int hf_option_filter_reserved
;
122 static int hf_option_filter_prefix_length
;
123 static int hf_option_filter_remote_peer_port
;
124 static int hf_option_filter_remote_peer_ip
;
125 static int hf_option_description
;
126 static int hf_option_p64_length
;
127 static int hf_option_p64_prefix64
;
128 static int hf_option_p64_suffix
;
129 static int hf_option_p64_ipv4_prefix_count
;
130 static int hf_option_p64_ipv4_prefix_length
;
131 static int hf_option_p64_ipv4_address
;
132 static int hf_option_portset_size
;
133 static int hf_option_portset_first_suggested_port
;
134 static int hf_option_portset_first_assigned_port
;
135 static int hf_option_portset_reserved
;
136 static int hf_option_portset_parity
;
137 static int hf_option_padding
;
140 static int ett_opcode
;
141 static int ett_option
;
142 static int ett_suboption
;
144 static expert_field ei_natpmp_opcode_unknown
;
145 static expert_field ei_pcp_opcode_unknown
;
146 static expert_field ei_pcp_option_unknown
;
148 static const value_string opcode_vals
[] = {
149 { EXTERNAL_ADDRESS_REQUEST
, "External Address Request" },
150 { EXTERNAL_ADDRESS_RESPONSE
, "External Address Response" },
151 { MAP_UDP_REQUEST
, "Map UDP Request" },
152 { MAP_UDP_RESPONSE
, "Map UDP Response" },
153 { MAP_TCP_REQUEST
, "Map TCP Request" },
154 { MAP_TCP_RESPONSE
, "Map TCP Response" },
158 static const value_string result_vals
[] = {
160 { 1, "Unsupported Version" },
161 { 2, "Not Authorized/Refused" },
162 { 3, "Network Failure" },
163 { 4, "Out of resources" },
164 { 5, "Unsupported opcode" },
168 static const value_string pcp_opcode_vals
[] = {
175 static const value_string pcp_ropcode_vals
[] = {
176 { ANNOUNCE_REQUEST
, "Announce Request" },
177 { MAP_REQUEST
, "Map Request" },
178 { PEER_REQUEST
, "Peer Request" },
179 { ANNOUNCE_RESPONSE
, "Announce Response" },
180 { MAP_RESPONSE
, "Map Response" },
181 { PEER_RESPONSE
, "Peer Response" },
185 static const value_string pcp_result_vals
[] = {
187 { 1, "Unsupported Version" },
188 { 2, "Not Authorized/Refused" },
189 { 3, "Malformed Request" },
190 { 4, "Unsupported opcode" },
191 { 5, "Unsupported option" },
192 { 6, "Malformed option" },
193 { 7, "Network failure" },
194 { 8, "No resources" },
195 { 9, "Unsupported protocol" },
196 { 10, "User exceeds quota" },
197 { 11, "Cannot provide external port" },
198 { 12, "Address mismatch" },
199 { 13, "Excessive remote peers" },
203 static const value_string pcp_option_vals
[] = {
205 { OPT_THIRD_PARTY
, "Third Party" },
206 { OPT_PREFER_FAILURE
, "Prefer Failure" },
207 { OPT_FILTER
, "Filter" },
208 { OPT_DESCRIPTION
, "Description" },
209 { OPT_PREFIX64
, "Prefix64" },
210 { OPT_PORT_SET
, "Port Set" },
214 static const value_string pcp_protocol_vals
[] = {
215 {0, "All Protocols"},
222 dissect_nat_pmp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
224 proto_tree
*nat_pmp_tree
;
225 proto_item
*ti
, *op_ti
;
226 int start_offset
, offset
= 0;
229 col_set_str (pinfo
->cinfo
, COL_PROTOCOL
, "NAT-PMP");
230 col_clear (pinfo
->cinfo
, COL_INFO
);
232 start_offset
= offset
;
233 ti
= proto_tree_add_item(tree
, proto_nat_pmp
, tvb
, offset
, -1, ENC_NA
);
234 nat_pmp_tree
= proto_item_add_subtree(ti
, ett_nat_pmp
);
236 proto_tree_add_item(nat_pmp_tree
, hf_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
239 opcode
= tvb_get_uint8 (tvb
, offset
);
240 proto_item_append_text (ti
, ", %s", val_to_str(opcode
, opcode_vals
, "Unknown opcode: %d"));
241 op_ti
= proto_tree_add_item(nat_pmp_tree
, hf_opcode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
244 col_add_str (pinfo
->cinfo
, COL_INFO
, val_to_str(opcode
, opcode_vals
, "Unknown opcode: %d"));
248 case EXTERNAL_ADDRESS_REQUEST
:
252 case EXTERNAL_ADDRESS_RESPONSE
:
253 proto_tree_add_item(nat_pmp_tree
, hf_result_code
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
256 proto_tree_add_item(nat_pmp_tree
, hf_sssoe
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
259 proto_tree_add_item(nat_pmp_tree
, hf_external_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
263 case MAP_UDP_REQUEST
:
264 case MAP_TCP_REQUEST
:
265 proto_tree_add_item(nat_pmp_tree
, hf_reserved
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
268 proto_tree_add_item(nat_pmp_tree
, hf_internal_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
271 proto_tree_add_item(nat_pmp_tree
, hf_external_port_requested
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
274 proto_tree_add_item(nat_pmp_tree
, hf_rpmlis
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
278 case MAP_UDP_RESPONSE
:
279 case MAP_TCP_RESPONSE
:
280 proto_tree_add_item(nat_pmp_tree
, hf_result_code
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
283 proto_tree_add_item(nat_pmp_tree
, hf_sssoe
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
286 proto_tree_add_item(nat_pmp_tree
, hf_internal_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
289 proto_tree_add_item(nat_pmp_tree
, hf_external_port_mapped
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
292 proto_tree_add_item(nat_pmp_tree
, hf_pmlis
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
298 expert_add_info_format(pinfo
, op_ti
, &ei_natpmp_opcode_unknown
, "Unknown opcode: %d", opcode
);
302 return (offset
-start_offset
);
306 dissect_portcontrol_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint8_t version
)
308 proto_tree
*pcp_tree
, *opcode_tree
= NULL
, *option_tree
, *option_sub_tree
;
309 proto_item
*ti
, *opcode_ti
, *option_ti
, *suboption_ti
;
310 int offset
= 0, start_offset
, start_opcode_offset
, start_option_offset
;
311 uint8_t ropcode
, option
;
312 uint16_t option_length
;
313 int mod_option_length
= 0;
314 int option_padding_length
= 0;
319 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PCP v1");
321 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PCP v2");
322 col_clear(pinfo
->cinfo
, COL_INFO
);
324 start_offset
= offset
;
325 ti
= proto_tree_add_item(tree
, proto_pcp
, tvb
, offset
, -1, ENC_NA
);
326 pcp_tree
= proto_item_add_subtree(ti
, ett_pcp
);
328 proto_tree_add_item(pcp_tree
, hf_pcp_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
331 ropcode
= tvb_get_uint8(tvb
, offset
);
332 is_response
= ropcode
& 0x80;
333 op_str
= val_to_str(ropcode
, pcp_ropcode_vals
, "Unknown opcode: %d");
334 proto_item_append_text(ti
, ", %s", op_str
);
335 proto_tree_add_item(pcp_tree
, hf_pcp_r
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
336 opcode_ti
= proto_tree_add_item(pcp_tree
, hf_pcp_opcode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
338 col_add_str(pinfo
->cinfo
, COL_INFO
, op_str
);
342 ti
= proto_tree_add_boolean(pcp_tree
, hf_request
, tvb
, offset
-1, 1, is_response
== false);
343 proto_item_set_hidden(ti
);
345 proto_tree_add_item(pcp_tree
, hf_reserved2
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
348 proto_tree_add_item(pcp_tree
, hf_req_lifetime
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
351 proto_tree_add_item(pcp_tree
, hf_client_ip
, tvb
, offset
, 16, ENC_NA
);
356 ti
= proto_tree_add_boolean(pcp_tree
, hf_response
, tvb
, offset
-1, 1, is_response
== true);
357 proto_item_set_hidden(ti
);
359 proto_tree_add_item(pcp_tree
, hf_reserved1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
362 proto_tree_add_item(pcp_tree
, hf_pcp_result_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
365 proto_tree_add_item(pcp_tree
, hf_rsp_lifetime
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
368 proto_tree_add_item(pcp_tree
, hf_epoch_time
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
371 proto_tree_add_item(pcp_tree
, hf_reserved12
, tvb
, offset
, 12, ENC_NA
);
375 start_opcode_offset
= offset
;
376 if(try_val_to_str(ropcode
, pcp_ropcode_vals
) != NULL
)
378 opcode_tree
= proto_tree_add_subtree(pcp_tree
, tvb
, offset
, 0, ett_opcode
, &opcode_ti
, op_str
);
381 uint32_t protocol
= 0;
382 uint32_t internal_port
= 0;
383 uint32_t external_port
= 0;
384 uint32_t port_set_size
= 0;
388 case ANNOUNCE_REQUEST
:
389 case ANNOUNCE_RESPONSE
:
396 proto_tree_add_item(opcode_tree
, hf_map_nonce
, tvb
, offset
, 12, ENC_NA
);
400 proto_tree_add_item_ret_uint(opcode_tree
, hf_map_protocol
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &protocol
);
402 proto_tree_add_item(opcode_tree
, hf_map_reserved1
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
404 proto_tree_add_item_ret_uint(opcode_tree
, hf_map_internal_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &internal_port
);
407 if (ropcode
== MAP_REQUEST
) {
408 proto_tree_add_item_ret_uint(opcode_tree
, hf_map_req_sug_external_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &external_port
);
410 proto_tree_add_item(opcode_tree
, hf_map_req_sug_ext_ip
, tvb
, offset
, 16, ENC_NA
);
413 proto_tree_add_item_ret_uint(opcode_tree
, hf_map_rsp_assigned_external_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &external_port
);
415 proto_tree_add_item(opcode_tree
, hf_map_rsp_assigned_ext_ip
, tvb
, offset
, 16, ENC_NA
);
425 proto_tree_add_item(opcode_tree
, hf_peer_nonce
, tvb
, offset
, 12, ENC_NA
);
429 proto_tree_add_item(opcode_tree
, hf_peer_protocol
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
431 proto_tree_add_item(opcode_tree
, hf_peer_reserved
, tvb
, offset
, 3, ENC_NA
);
433 proto_tree_add_item(opcode_tree
, hf_peer_internal_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
435 if(ropcode
== PEER_REQUEST
)
437 proto_tree_add_item(opcode_tree
, hf_peer_req_sug_external_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
439 proto_tree_add_item(opcode_tree
, hf_peer_req_sug_ext_ip
, tvb
, offset
, 16, ENC_NA
);
444 proto_tree_add_item(opcode_tree
, hf_peer_rsp_assigned_external_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
446 proto_tree_add_item(opcode_tree
, hf_peer_rsp_assigned_ext_ip
, tvb
, offset
, 16, ENC_NA
);
450 proto_tree_add_item(opcode_tree
, hf_peer_remote_peer_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
452 proto_tree_add_item(opcode_tree
, hf_peer_reserved
, tvb
, offset
, 2, ENC_NA
);
454 proto_tree_add_item(opcode_tree
, hf_peer_remote_peer_ip
, tvb
, offset
, 16, ENC_NA
);
459 expert_add_info_format(pinfo
, opcode_ti
, &ei_pcp_opcode_unknown
, "Unknown opcode: %d", ropcode
);
463 /* Now see if there are any options for the supported opcodes */
464 if((tvb_reported_length_remaining(tvb
, offset
) > 0) &&
465 (try_val_to_str(ropcode
, pcp_ropcode_vals
) != NULL
))
467 start_option_offset
= offset
;
468 option_ti
= proto_tree_add_item(opcode_tree
, hf_options
, tvb
, offset
, 0, ENC_NA
);
469 option_tree
= proto_item_add_subtree(option_ti
, ett_option
);
471 while(tvb_reported_length_remaining(tvb
, offset
) > 0)
473 suboption_ti
= proto_tree_add_item(option_tree
, hf_option
, tvb
, offset
, 1, ENC_NA
);
474 option_sub_tree
= proto_item_add_subtree(suboption_ti
, ett_suboption
);
476 proto_tree_add_item(option_sub_tree
, hf_option_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
477 option
= tvb_get_uint8(tvb
, offset
);
478 proto_item_append_text(suboption_ti
, ": %s", val_to_str(option
, pcp_option_vals
, "Unknown option: %d"));
481 proto_tree_add_item(option_sub_tree
, hf_option_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
484 proto_tree_add_item(option_sub_tree
, hf_option_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
485 option_length
= tvb_get_ntohs(tvb
, offset
);
488 mod_option_length
= option_length
% 4;
489 if( mod_option_length
!= 0 )
491 option_padding_length
= 4 - mod_option_length
;
494 proto_item_set_len(suboption_ti
, option_length
+4+option_padding_length
);
496 if(option_length
> 0)
500 case OPT_THIRD_PARTY
:
501 proto_tree_add_item(option_sub_tree
, hf_option_third_party_internal_ip
, tvb
, offset
, 16, ENC_NA
);
504 case OPT_PREFER_FAILURE
:
509 proto_tree_add_item(option_sub_tree
, hf_option_filter_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
510 proto_tree_add_item(option_sub_tree
, hf_option_filter_prefix_length
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
511 proto_tree_add_item(option_sub_tree
, hf_option_filter_remote_peer_port
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
512 proto_tree_add_item(option_sub_tree
, hf_option_filter_remote_peer_ip
, tvb
, offset
+4, 16, ENC_NA
);
515 case OPT_DESCRIPTION
:
516 proto_tree_add_item(option_sub_tree
, hf_option_description
, tvb
, offset
, option_length
, ENC_UTF_8
);
524 if(option_length
-optoffset
< 2)
526 /*TODO: report an error here*/
529 proto_tree_add_item_ret_uint(option_sub_tree
, hf_option_p64_length
, tvb
, offset
+optoffset
, 2, ENC_BIG_ENDIAN
, &p64_length
);
531 if(option_length
-optoffset
< 12)
533 /*TODO: report an error here*/
538 /*TODO: Fix display of Prefix64 and Suffix*/
539 proto_tree_add_item(option_sub_tree
, hf_option_p64_prefix64
, tvb
, offset
+optoffset
, p64_length
, ENC_NA
);
540 optoffset
+= p64_length
;
542 proto_tree_add_item(option_sub_tree
, hf_option_p64_suffix
, tvb
, offset
+optoffset
, 12-p64_length
, ENC_NA
);
543 optoffset
+= (12-p64_length
);
545 /*TODO: report an error here*/
549 if(option_length
-optoffset
> 0)
551 uint32_t ipv4_prefix_count
;
553 if(option_length
-optoffset
< 2)
555 /*TODO: report an error here*/
558 proto_tree_add_item_ret_uint(option_sub_tree
, hf_option_p64_ipv4_prefix_count
, tvb
, offset
+optoffset
, 2, ENC_BIG_ENDIAN
, &ipv4_prefix_count
);
561 while(ipv4_prefix_count
)
563 if(option_length
-optoffset
< 2)
565 /*TODO: report an error here*/
568 proto_tree_add_item(option_sub_tree
, hf_option_p64_ipv4_prefix_length
, tvb
, offset
+optoffset
, 2, ENC_BIG_ENDIAN
);
570 if(option_length
-optoffset
< 4)
572 /*TODO: report an error here*/
575 proto_tree_add_item(option_sub_tree
, hf_option_p64_ipv4_address
, tvb
, offset
+optoffset
, 4, ENC_BIG_ENDIAN
);
584 proto_tree_add_item_ret_uint(option_sub_tree
, hf_option_portset_size
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &port_set_size
);
586 proto_tree_add_item_ret_uint(option_sub_tree
, hf_option_portset_first_suggested_port
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
, &external_port
);
588 proto_tree_add_item_ret_uint(option_sub_tree
, hf_option_portset_first_assigned_port
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
, &external_port
);
590 proto_tree_add_item(option_sub_tree
, hf_option_portset_reserved
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
591 proto_tree_add_item(option_sub_tree
, hf_option_portset_parity
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
596 expert_add_info_format(pinfo
, option_ti
, &ei_pcp_option_unknown
, "Unknown option: %d", option
);
601 offset
+=option_length
;
603 if( option_padding_length
> 0 )
605 proto_tree_add_item(option_sub_tree
, hf_option_padding
, tvb
, offset
, option_padding_length
, ENC_NA
);
606 offset
+=option_padding_length
;
610 proto_item_set_len(option_ti
, offset
-start_option_offset
);
613 proto_item_set_len(opcode_ti
, offset
-start_opcode_offset
);
615 bool is_map_opcode
= (ropcode
== MAP_REQUEST
|| ropcode
== MAP_RESPONSE
);
616 if (is_map_opcode
&& port_set_size
!= 0) {
620 "%s: %d-%d -> %d-%d [%s]",
623 internal_port
+ port_set_size
,
625 external_port
+ port_set_size
,
626 val_to_str(protocol
, pcp_protocol_vals
, "Unknown Protocol %d")
628 } else if (is_map_opcode
) {
636 val_to_str(protocol
, pcp_protocol_vals
, "Unknown Protocol %d")
640 return (offset
-start_offset
);
644 dissect_portcontrol(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
646 uint8_t version
= tvb_get_uint8(tvb
, 0);
651 /* NAT-PMP protocol */
652 return dissect_nat_pmp(tvb
, pinfo
, tree
, data
);
655 return dissect_portcontrol_pdu(tvb
, pinfo
, tree
, version
);
661 void proto_register_nat_pmp(void)
663 static hf_register_info hf
[] = {
665 { "Version", "nat-pmp.version", FT_UINT8
, BASE_DEC
,
666 NULL
, 0x0, NULL
, HFILL
} },
668 { "Opcode", "nat-pmp.opcode", FT_UINT8
, BASE_DEC
,
669 VALS(opcode_vals
), 0x0, NULL
, HFILL
} },
671 { "Result Code", "nat-pmp.result_code", FT_UINT16
, BASE_DEC
,
672 VALS(result_vals
), 0x0, NULL
, HFILL
} },
674 { "Seconds Since Start of Epoch", "nat-pmp.sssoe", FT_UINT32
, BASE_DEC
,
675 NULL
, 0x0, NULL
, HFILL
} },
677 { "External IP Address", "nat-pmp.external_ip", FT_IPv4
, BASE_NONE
,
678 NULL
, 0x0, NULL
, HFILL
} },
680 { "Reserved", "nat-pmp.reserved", FT_UINT16
, BASE_DEC
,
681 NULL
, 0x0, "Reserved (must be zero)", HFILL
} },
683 { "Internal Port", "nat-pmp.internal_port", FT_UINT16
, BASE_DEC
,
684 NULL
, 0x0, NULL
, HFILL
} },
685 { &hf_external_port_requested
,
686 { "Requested External Port", "nat-pmp.external_port", FT_UINT16
, BASE_DEC
,
687 NULL
, 0x0, NULL
, HFILL
} },
688 { &hf_external_port_mapped
,
689 { "Mapped External Port", "nat-pmp.external_port", FT_UINT16
, BASE_DEC
,
690 NULL
, 0x0, NULL
, HFILL
} },
692 { "Requested Port Mapping Lifetime", "nat-pmp.pml", FT_UINT32
, BASE_DEC
,
693 NULL
, 0x0, "Requested Port Mapping Lifetime in Seconds", HFILL
} },
695 { "Port Mapping Lifetime", "nat-pmp.pml", FT_UINT32
, BASE_DEC
,
696 NULL
, 0x0, "Port Mapping Lifetime in Seconds", HFILL
} },
699 static hf_register_info pcp_hf
[] = {
701 { "Version", "portcontrol.version", FT_UINT8
, BASE_DEC
,
702 NULL
, 0x0, NULL
, HFILL
} },
704 { "Request", "portcontrol.request", FT_BOOLEAN
, 8,
705 NULL
, 0x01, NULL
, HFILL
} },
707 { "Response", "portcontrol.response", FT_BOOLEAN
, 8,
708 NULL
, 0x01, NULL
, HFILL
} },
710 { "R", "portcontrol.r", FT_BOOLEAN
, 8,
711 TFS(&tfs_response_request
), 0x80, "Indicates Request (0) or Response (1)", HFILL
} },
713 { "Opcode", "portcontrol.opcode", FT_UINT8
, BASE_DEC
,
714 VALS(pcp_opcode_vals
), 0x7F, NULL
, HFILL
} },
715 { &hf_pcp_result_code
,
716 { "Result Code", "portcontrol.result_code", FT_UINT16
, BASE_DEC
,
717 VALS(pcp_result_vals
), 0x0, NULL
, HFILL
} },
719 { "Reserved", "portcontrol.reserved", FT_UINT8
, BASE_DEC
,
720 NULL
, 0x0, NULL
, HFILL
} },
722 { "Reserved", "portcontrol.reserved", FT_UINT16
, BASE_DEC
,
723 NULL
, 0x0, NULL
, HFILL
} },
725 { "Reserved", "portcontrol.rsp_reserved", FT_BYTES
, BASE_NONE
,
726 NULL
, 0x0, NULL
, HFILL
} },
728 { "Requested Lifetime", "portcontrol.lifetime_req", FT_UINT32
, BASE_DEC
,
729 NULL
, 0x0, NULL
, HFILL
} },
731 { "Lifetime", "portcontrol.lifetime_rsp", FT_UINT32
, BASE_DEC
,
732 NULL
, 0x0, NULL
, HFILL
} },
734 { "Client IP Address", "portcontrol.client_ip", FT_IPv6
, BASE_NONE
,
735 NULL
, 0x0, NULL
, HFILL
} },
737 { "Epoch Time", "portcontrol.epoch_time", FT_UINT32
, BASE_DEC
,
738 NULL
, 0x0, NULL
, HFILL
} },
740 { "Mapping Nonce", "portcontrol.map.nonce", FT_BYTES
, BASE_NONE
,
741 NULL
, 0x0, NULL
, HFILL
} },
743 { "Protocol", "portcontrol.map.protocol", FT_UINT8
, BASE_DEC
,
744 NULL
, 0x0, NULL
, HFILL
} },
746 { "Reserved", "portcontrol.map.reserved", FT_UINT24
, BASE_DEC
,
747 NULL
, 0x0, NULL
, HFILL
} },
748 { &hf_map_internal_port
,
749 { "Internal Port", "portcontrol.map.internal_port", FT_UINT16
, BASE_DEC
,
750 NULL
, 0x0, NULL
, HFILL
} },
751 { &hf_map_req_sug_external_port
,
752 { "Suggested External Port", "portcontrol.map.req_sug_external_port", FT_UINT16
, BASE_DEC
,
753 NULL
, 0x0, NULL
, HFILL
} },
754 { &hf_map_req_sug_ext_ip
,
755 { "Suggested External IP Address", "portcontrol.map.req_sug_external_ip", FT_IPv6
, BASE_NONE
,
756 NULL
, 0x0, NULL
, HFILL
} },
757 { &hf_map_rsp_assigned_external_port
,
758 { "Assigned External Port", "portcontrol.map.rsp_assigned_external_port", FT_UINT16
, BASE_DEC
,
759 NULL
, 0x0, NULL
, HFILL
} },
760 { &hf_map_rsp_assigned_ext_ip
,
761 { "Assigned External IP Address", "portcontrol.map.rsp_assigned_ext_ip", FT_IPv6
, BASE_NONE
,
762 NULL
, 0x0, NULL
, HFILL
} },
764 { "Mapping Nonce", "portcontrol.peer.nonce", FT_BYTES
, BASE_NONE
,
765 NULL
, 0x0, NULL
, HFILL
} },
767 { "Protocol", "portcontrol.peer.protocol", FT_UINT8
, BASE_DEC
,
768 NULL
, 0x0, NULL
, HFILL
} },
770 { "Reserved", "portcontrol.peer.reserved", FT_BYTES
, BASE_NONE
,
771 NULL
, 0x0, NULL
, HFILL
} },
772 { &hf_peer_internal_port
,
773 { "Internal Port", "portcontrol.peer.internal_port", FT_UINT16
, BASE_DEC
,
774 NULL
, 0x0, NULL
, HFILL
} },
775 { &hf_peer_req_sug_external_port
,
776 { "Suggested External Port", "portcontrol.peer.req_sug_external_port", FT_UINT16
, BASE_DEC
,
777 NULL
, 0x0, NULL
, HFILL
} },
778 { &hf_peer_req_sug_ext_ip
,
779 { "Suggested External IP Address", "portcontrol.peer.req_sug_external_ip", FT_IPv6
, BASE_NONE
,
780 NULL
, 0x0, NULL
, HFILL
} },
781 { &hf_peer_remote_peer_port
,
782 { "Remote Peer Port", "portcontrol.peer.remote_peer_port", FT_UINT16
, BASE_DEC
,
783 NULL
, 0x0, NULL
, HFILL
} },
784 { &hf_peer_remote_peer_ip
,
785 { "Remote Peer IP Address", "portcontrol.peer.remote_peer_ip", FT_IPv6
, BASE_NONE
,
786 NULL
, 0x0, NULL
, HFILL
} },
787 { &hf_peer_rsp_assigned_external_port
,
788 { "Assigned External Port", "portcontrol.peer.rsp_assigned_external_port", FT_UINT16
, BASE_DEC
,
789 NULL
, 0x0, NULL
, HFILL
} },
790 { &hf_peer_rsp_assigned_ext_ip
,
791 { "Assigned External IP Address", "portcontrol.peer.rsp_assigned_ext_ip", FT_IPv6
, BASE_NONE
,
792 NULL
, 0x0, NULL
, HFILL
} },
794 { "Options", "portcontrol.options", FT_NONE
, BASE_NONE
,
795 NULL
, 0x0, NULL
, HFILL
} },
797 { "Option", "portcontrol.option", FT_NONE
, BASE_NONE
,
798 NULL
, 0x0, NULL
, HFILL
} },
800 { "Option", "portcontrol.option.code", FT_UINT8
, BASE_DEC
,
801 VALS(pcp_option_vals
), 0x0, NULL
, HFILL
} },
802 { &hf_option_reserved
,
803 { "Reserved", "portcontrol.option.reserved", FT_UINT8
, BASE_DEC
,
804 NULL
, 0x0, NULL
, HFILL
} },
806 { "Option Length", "portcontrol.option.length", FT_UINT16
, BASE_DEC
,
807 NULL
, 0x0, NULL
, HFILL
} },
808 { &hf_option_third_party_internal_ip
,
809 { "Internal IP Address", "portcontrol.option.third_party.internal_ip", FT_IPv6
, BASE_NONE
,
810 NULL
, 0x0, NULL
, HFILL
} },
811 { &hf_option_filter_reserved
,
812 { "Reserved", "portcontrol.option.filter.reserved", FT_UINT8
, BASE_DEC
,
813 NULL
, 0x0, NULL
, HFILL
} },
814 { &hf_option_filter_prefix_length
,
815 { "Prefix Length", "portcontrol.option.filter.prefix_length", FT_UINT8
, BASE_DEC
,
816 NULL
, 0x0, NULL
, HFILL
} },
817 { &hf_option_filter_remote_peer_port
,
818 { "Remote Peer Port", "portcontrol.option.filter.remote_peer_port", FT_UINT16
, BASE_DEC
,
819 NULL
, 0x0, NULL
, HFILL
} },
820 { &hf_option_filter_remote_peer_ip
,
821 { "Remote Peer IP Address", "portcontrol.option.filter.remote_peer_ip", FT_IPv6
, BASE_NONE
,
822 NULL
, 0x0, NULL
, HFILL
} },
823 { &hf_option_description
,
824 { "Description", "portcontrol.option.description", FT_STRING
, BASE_NONE
,
825 NULL
, 0x0, NULL
, HFILL
} },
826 { &hf_option_p64_length
,
827 { "Length", "portcontrol.option.p64.length", FT_UINT16
, BASE_DEC
,
828 NULL
, 0x0, NULL
, HFILL
} },
829 { &hf_option_p64_prefix64
,
830 { "Prefix64", "portcontrol.option.p64.prefix64", FT_BYTES
, BASE_NONE
,
831 NULL
, 0x0, NULL
, HFILL
} },
832 { &hf_option_p64_suffix
,
833 { "Suffix", "portcontrol.option.p64.suffix", FT_BYTES
, BASE_NONE
,
834 NULL
, 0x0, NULL
, HFILL
} },
835 { &hf_option_p64_ipv4_prefix_count
,
836 { "IPv4 Prefix Count", "portcontrol.option.p64.ipv4_prefix_count", FT_UINT16
, BASE_DEC
,
837 NULL
, 0x0, NULL
, HFILL
} },
838 { &hf_option_p64_ipv4_prefix_length
,
839 { "IPv4 Prefix Length", "portcontrol.option.p64.ipv4_prefix_length", FT_UINT16
, BASE_DEC
,
840 NULL
, 0x0, NULL
, HFILL
} },
841 { &hf_option_p64_ipv4_address
,
842 { "IPv4 Address", "portcontrol.option.p64.ipv4_address", FT_IPv4
, BASE_NONE
,
843 NULL
, 0x0, NULL
, HFILL
} },
844 { &hf_option_portset_size
,
845 { "Port Set Size", "portcontrol.option.portset.size", FT_UINT16
, BASE_DEC
,
846 NULL
, 0x0, NULL
, HFILL
} },
847 { &hf_option_portset_first_suggested_port
,
848 { "Suggested First Port", "portcontrol.option.portset.req_sug_first_external_port", FT_UINT16
, BASE_DEC
,
849 NULL
, 0x0, NULL
, HFILL
} },
850 { &hf_option_portset_first_assigned_port
,
851 { "Assigned First Port", "portcontrol.option.portset.rsp_assigned_first_external_port", FT_UINT16
, BASE_DEC
,
852 NULL
, 0x0, NULL
, HFILL
} },
853 { &hf_option_portset_reserved
,
854 { "Reserved", "portcontrol.option.portset.reserved", FT_UINT8
, BASE_HEX
,
855 NULL
, 0xFE, NULL
, HFILL
} },
856 { &hf_option_portset_parity
,
857 { "Parity Requested", "portcontrol.option.portset.parity", FT_BOOLEAN
, 8,
858 NULL
, 0x01, NULL
, HFILL
} },
859 { &hf_option_padding
,
860 { "Padding", "portcontrol.option.padding", FT_BYTES
, BASE_NONE
,
861 NULL
, 0x0, NULL
, HFILL
} },
864 static int *pcp_ett
[] = {
871 static int *ett
[] = {
875 static ei_register_info natpmp_ei
[] = {
876 { &ei_natpmp_opcode_unknown
, { "nat-pmp.opcode.unknown", PI_RESPONSE_CODE
, PI_WARN
, "Unknown opcode", EXPFILL
}},
879 static ei_register_info pcp_ei
[] = {
880 { &ei_pcp_opcode_unknown
, { "portcontrol.opcode.unknown", PI_RESPONSE_CODE
, PI_WARN
, "Unknown opcode", EXPFILL
}},
881 { &ei_pcp_option_unknown
, { "portcontrol.option.unknown", PI_RESPONSE_CODE
, PI_WARN
, "Unknown option", EXPFILL
}},
884 expert_module_t
* expert_nat_pmp
;
885 expert_module_t
* expert_pcp
;
887 proto_nat_pmp
= proto_register_protocol("NAT Port Mapping Protocol", "NAT-PMP", "nat-pmp");
889 proto_register_field_array(proto_nat_pmp
, hf
, array_length(hf
));
890 proto_register_subtree_array(ett
, array_length(ett
));
891 expert_nat_pmp
= expert_register_protocol(proto_nat_pmp
);
892 expert_register_field_array(expert_nat_pmp
, natpmp_ei
, array_length(natpmp_ei
));
894 nat_pmp_handle
= register_dissector("nat-pmp", dissect_nat_pmp
, proto_nat_pmp
);
896 proto_pcp
= proto_register_protocol("Port Control Protocol", "Port Control", "portcontrol");
898 proto_register_field_array(proto_pcp
, pcp_hf
, array_length(pcp_hf
));
899 proto_register_subtree_array(pcp_ett
, array_length(pcp_ett
));
900 expert_pcp
= expert_register_protocol(proto_pcp
);
901 expert_register_field_array(expert_pcp
, pcp_ei
, array_length(pcp_ei
));
903 pcp_handle
= register_dissector("portcontrol", dissect_portcontrol
, proto_pcp
);
906 void proto_reg_handoff_nat_pmp(void)
908 dissector_add_uint_range_with_preference("udp.port", PCP_PORT_RANGE
, pcp_handle
);
910 /* Port Control Protocol (packet-portcontrol.c) shares the same UDP ports as
911 NAT-PMP, but it backwards compatible. However, still let NAT-PMP
914 dissector_add_for_decode_as_with_preference("udp.port", nat_pmp_handle
);
923 * indent-tabs-mode: nil
926 * ex: set shiftwidth=2 tabstop=8 expandtab:
927 * :indentSize=2:tabSize=8:noTabs=true: