epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-enrp.c
blob156f283cc1ac13e33b7f33a587a2d65ad04989a3
1 /* packet-enrp.c
2 * Routines for Endpoint Handlespace Redundancy Protocol (ENRP)
3 * It is hopefully (needs testing) compliant to
4 * RFC 5353
5 * RFC 5354
6 * RFC 5356
7 * https://tools.ietf.org/html/draft-dreibholz-rserpool-enrp-takeover-21
9 * Copyright 2008-2021 Thomas Dreibholz <dreibh [AT] iem.uni-due.de>
10 * Copyright 2004-2007 Michael Tüxen <tuexen [AT] fh-muenster.de>
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * Copied from README.developer
18 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include "config.h"
23 #include <epan/packet.h>
24 #include <epan/to_str.h>
25 #include <epan/sctpppids.h>
26 #include <epan/stat_tap_ui.h>
27 #include <epan/expert.h>
28 #include <epan/proto_data.h>
29 #include <epan/tfs.h>
30 #include <epan/unit_strings.h>
32 #include <wsutil/str_util.h>
33 #include <wsutil/ws_roundup.h>
34 #include <wsutil/array.h>
36 #include "packet-asap+enrp-common.h"
38 void proto_register_enrp(void);
39 void proto_reg_handoff_enrp(void);
41 static dissector_handle_t enrp_handle;
43 /* Initialize the protocol and registered fields */
44 static int enrp_tap;
45 static int proto_enrp;
46 static int hf_cause_code;
47 static int hf_cause_length;
48 static int hf_cause_info;
49 static int hf_cause_padding;
50 static int hf_message_type;
51 static int hf_message_flags;
52 static int hf_message_length;
53 static int hf_message_value;
54 static int hf_parameter_type;
55 static int hf_parameter_length;
56 static int hf_parameter_value;
57 static int hf_parameter_padding;
58 static int hf_parameter_ipv4_address;
59 static int hf_parameter_ipv6_address;
60 static int hf_dccp_port;
61 static int hf_dccp_reserved;
62 static int hf_dccp_service_code;
63 static int hf_sctp_port;
64 static int hf_transport_use;
65 static int hf_tcp_port;
66 static int hf_udp_port;
67 static int hf_udp_reserved;
68 static int hf_udp_lite_port;
69 static int hf_udp_lite_reserved;
70 static int hf_policy_type;
71 static int hf_policy_value;
72 static int hf_policy_weight;
73 static int hf_policy_priority;
74 static int hf_policy_load;
75 static int hf_policy_degradation;
76 static int hf_policy_loaddpf;
77 static int hf_policy_weightdpf;
78 static int hf_policy_distance;
79 static int hf_pool_handle;
80 static int hf_pe_pe_identifier;
81 static int hf_home_enrp_id;
82 static int hf_reg_life;
83 static int hf_server_identifier;
84 static int hf_cookie;
85 static int hf_pe_identifier;
86 static int hf_pe_checksum;
87 static int hf_sender_servers_id;
88 static int hf_receiver_servers_id;
89 static int hf_target_servers_id;
90 static int hf_update_action;
91 static int hf_pmu_reserved;
92 static int hf_reply_required_bit;
93 static int hf_own_children_only_bit;
94 static int hf_more_to_send_bit;
95 static int hf_reject_bit;
96 static int hf_tos_bit;
98 /* Initialize the subtree pointers */
99 static int ett_enrp;
100 static int ett_enrp_parameter;
101 static int ett_enrp_cause;
102 static int ett_enrp_flags;
104 static uint64_t enrp_total_msgs;
105 static uint64_t enrp_total_bytes;
107 static expert_field ei_enrp_max_recursion_depth_reached;
108 static expert_field ei_enrp_invalid_length;
110 static void
111 dissect_parameters(tvbuff_t *, packet_info *, proto_tree *);
112 static void
113 dissect_parameter(tvbuff_t *, packet_info *, proto_tree *);
114 static void
115 dissect_enrp_main(tvbuff_t *, packet_info *, proto_tree *);
116 static int
117 dissect_enrp(tvbuff_t *, packet_info *, proto_tree *, void*);
119 #define ENRP_UDP_PORT 9901
120 #define ENRP_SCTP_PORT 9901
121 #define ENRP_MAX_RECURSION_DEPTH 10
123 typedef struct _enrp_tap_rec_t {
124 uint8_t type;
125 uint16_t size;
126 const char* type_string;
127 } enrp_tap_rec_t;
129 /* Dissectors for error causes. This is common for ASAP and ENRP. */
131 static void
132 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
134 uint16_t code, length, cause_info_length;
136 code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
137 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
138 cause_info_length = length - CAUSE_HEADER_LENGTH;
139 if (cause_info_length > 0)
140 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, ENC_NA);
141 proto_item_append_text(cause_item, " (code %u and %u byte%s information)", code, cause_info_length, plurality(cause_info_length, "", "s"));
144 static void
145 // NOLINTNEXTLINE(misc-no-recursion)
146 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *parameter_tree)
148 uint16_t code, length, padding_length;
149 proto_item *cause_item;
150 proto_tree *cause_tree;
151 tvbuff_t *parameter_tvb, *message_tvb;
153 code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
154 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
155 padding_length = tvb_captured_length(cause_tvb) - length;
157 cause_tree = proto_tree_add_subtree(parameter_tree, cause_tvb, CAUSE_HEADER_OFFSET, -1,
158 ett_enrp_cause, &cause_item, val_to_str_const(code, cause_code_values, "Unknown error cause"));
160 proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, ENC_BIG_ENDIAN);
161 proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, ENC_BIG_ENDIAN);
163 switch(code) {
164 case UNRECOGNIZED_PARAMETER_CAUSE_CODE:
165 parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET);
166 dissect_parameter(parameter_tvb, pinfo, cause_tree);
167 break;
168 case UNRECONGNIZED_MESSAGE_CAUSE_CODE:
169 message_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET);
170 dissect_enrp_main(message_tvb, pinfo, cause_tree);
171 break;
172 case INVALID_VALUES:
173 parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET);
174 dissect_parameter(parameter_tvb, pinfo, cause_tree);
175 break;
176 case NON_UNIQUE_PE_IDENTIFIER:
177 break;
178 case POOLING_POLICY_INCONSISTENT_CAUSE_CODE:
179 parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET);
180 dissect_parameter(parameter_tvb, pinfo, cause_tree);
181 break;
182 case LACK_OF_RESOURCES_CAUSE_CODE:
183 break;
184 case INCONSISTENT_TRANSPORT_TYPE_CAUSE_CODE:
185 parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET);
186 dissect_parameter(parameter_tvb, pinfo, cause_tree);
187 break;
188 case INCONSISTENT_DATA_CONTROL_CONFIGURATION_CAUSE_CODE:
189 break;
190 case UNKNOWN_POOL_HANDLE:
191 break;
192 case REJECTION_DUE_TO_SECURITY_CAUSE_CODE:
193 break;
194 default:
195 dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
196 break;
198 if (padding_length > 0)
199 proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, ENC_NA);
202 static void
203 // NOLINTNEXTLINE(misc-no-recursion)
204 dissect_error_causes(tvbuff_t *error_causes_tvb, packet_info *pinfo, proto_tree *parameter_tree)
206 uint16_t length, total_length;
207 int offset;
208 tvbuff_t *error_cause_tvb;
210 offset = 0;
211 while(tvb_reported_length_remaining(error_causes_tvb, offset) > 0) {
212 length = tvb_get_ntohs(error_causes_tvb, offset + CAUSE_LENGTH_OFFSET);
213 if (length < 4) {
214 proto_tree_add_expert_format(parameter_tree, pinfo, &ei_enrp_invalid_length,
215 error_causes_tvb, offset + CAUSE_LENGTH_OFFSET, 2,
216 "Error cause length must be at least 4 bytes");
217 return;
219 total_length = WS_ROUNDUP_4(length);
220 error_cause_tvb = tvb_new_subset_length(error_causes_tvb, offset, total_length);
221 dissect_error_cause(error_cause_tvb, pinfo, parameter_tree);
222 offset += total_length;
226 /* Dissectors for parameters. This is common for ASAP and ENRP. */
228 static void
229 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
231 proto_tree_add_item(parameter_tree, hf_parameter_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
232 proto_item_append_text(parameter_item, " (%s)", tvb_ip_to_str(pinfo->pool, parameter_tvb, IPV4_ADDRESS_OFFSET));
235 static void
236 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
238 proto_tree_add_item(parameter_tree, hf_parameter_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, ENC_NA);
239 proto_item_append_text(parameter_item, " (%s)", tvb_ip6_to_str(pinfo->pool, parameter_tvb, IPV6_ADDRESS_OFFSET));
242 static void
243 // NOLINTNEXTLINE(misc-no-recursion)
244 dissect_dccp_transport_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
246 tvbuff_t *parameters_tvb;
248 proto_tree_add_item(parameter_tree, hf_dccp_port, parameter_tvb, DCCP_PORT_OFFSET, DCCP_PORT_LENGTH, ENC_BIG_ENDIAN);
249 proto_tree_add_item(parameter_tree, hf_dccp_reserved, parameter_tvb, DCCP_RESERVED_OFFSET, DCCP_RESERVED_LENGTH, ENC_BIG_ENDIAN);
250 proto_tree_add_item(parameter_tree, hf_dccp_service_code, parameter_tvb, DCCP_SERVICE_CODE_OFFSET, DCCP_SERVICE_CODE_LENGTH, ENC_BIG_ENDIAN);
252 parameters_tvb = tvb_new_subset_remaining(parameter_tvb, DCCP_ADDRESS_OFFSET);
253 dissect_parameters(parameters_tvb, pinfo, parameter_tree);
256 static void
257 // NOLINTNEXTLINE(misc-no-recursion)
258 dissect_sctp_transport_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
260 tvbuff_t *parameters_tvb;
262 proto_tree_add_item(parameter_tree, hf_sctp_port, parameter_tvb, SCTP_PORT_OFFSET, SCTP_PORT_LENGTH, ENC_BIG_ENDIAN);
263 proto_tree_add_item(parameter_tree, hf_transport_use, parameter_tvb, SCTP_TRANSPORT_USE_OFFSET, SCTP_TRANSPORT_USE_LENGTH, ENC_BIG_ENDIAN);
265 parameters_tvb = tvb_new_subset_remaining(parameter_tvb, SCTP_ADDRESS_OFFSET);
266 dissect_parameters(parameters_tvb, pinfo, parameter_tree);
269 static void
270 // NOLINTNEXTLINE(misc-no-recursion)
271 dissect_tcp_transport_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
273 tvbuff_t *parameters_tvb;
275 proto_tree_add_item(parameter_tree, hf_tcp_port, parameter_tvb, TCP_PORT_OFFSET, TCP_PORT_LENGTH, ENC_BIG_ENDIAN);
276 proto_tree_add_item(parameter_tree, hf_transport_use, parameter_tvb, TCP_TRANSPORT_USE_OFFSET, TCP_TRANSPORT_USE_LENGTH, ENC_BIG_ENDIAN);
278 parameters_tvb = tvb_new_subset_remaining(parameter_tvb, TCP_ADDRESS_OFFSET);
279 dissect_parameters(parameters_tvb, pinfo, parameter_tree);
282 static void
283 // NOLINTNEXTLINE(misc-no-recursion)
284 dissect_udp_transport_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
286 tvbuff_t *parameters_tvb;
288 proto_tree_add_item(parameter_tree, hf_udp_port, parameter_tvb, UDP_PORT_OFFSET, UDP_PORT_LENGTH, ENC_BIG_ENDIAN);
289 proto_tree_add_item(parameter_tree, hf_udp_reserved, parameter_tvb, UDP_RESERVED_OFFSET, UDP_RESERVED_LENGTH, ENC_BIG_ENDIAN);
291 parameters_tvb = tvb_new_subset_remaining(parameter_tvb, UDP_ADDRESS_OFFSET);
292 dissect_parameters(parameters_tvb, pinfo, parameter_tree);
295 static void
296 // NOLINTNEXTLINE(misc-no-recursion)
297 dissect_udp_lite_transport_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
299 tvbuff_t *parameters_tvb;
301 proto_tree_add_item(parameter_tree, hf_udp_lite_port, parameter_tvb, UDP_LITE_PORT_OFFSET, UDP_LITE_PORT_LENGTH, ENC_BIG_ENDIAN);
302 proto_tree_add_item(parameter_tree, hf_udp_lite_reserved, parameter_tvb, UDP_LITE_RESERVED_OFFSET, UDP_LITE_RESERVED_LENGTH, ENC_BIG_ENDIAN);
304 parameters_tvb = tvb_new_subset_remaining(parameter_tvb, UDP_LITE_ADDRESS_OFFSET);
305 dissect_parameters(parameters_tvb, pinfo, parameter_tree);
308 static void
309 dissect_pool_member_selection_policy_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
311 uint32_t type;
312 unsigned length;
314 proto_tree_add_item(parameter_tree, hf_policy_type, parameter_tvb, POLICY_TYPE_OFFSET, POLICY_TYPE_LENGTH, ENC_BIG_ENDIAN);
315 type = tvb_get_ntohl(parameter_tvb, POLICY_TYPE_OFFSET);
316 switch (type) {
317 case RANDOM_POLICY:
318 case ROUND_ROBIN_POLICY:
319 break;
320 case WEIGHTED_RANDOM_POLICY:
321 case WEIGHTED_ROUND_ROBIN_POLICY:
322 proto_tree_add_item(parameter_tree, hf_policy_weight, parameter_tvb, POLICY_WEIGHT_OFFSET, POLICY_WEIGHT_LENGTH, ENC_BIG_ENDIAN);
323 break;
324 case PRIORITY_POLICY:
325 proto_tree_add_item(parameter_tree, hf_policy_priority, parameter_tvb, POLICY_PRIORITY_OFFSET, POLICY_PRIORITY_LENGTH, ENC_BIG_ENDIAN);
326 break;
327 case LEAST_USED_POLICY:
328 case RANDOMIZED_LEAST_USED_POLICY:
329 proto_tree_add_double_format_value(parameter_tree, hf_policy_load, parameter_tvb, POLICY_LOAD_OFFSET, POLICY_LOAD_LENGTH,
330 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_LOAD_OFFSET) / (double)0xffffffff, "%1.2f%%",
331 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_LOAD_OFFSET) / (double)0xffffffff);
332 break;
333 case LEAST_USED_WITH_DEG_POLICY:
334 case PRIORITY_LEAST_USED_POLICY:
335 proto_tree_add_double_format_value(parameter_tree, hf_policy_load, parameter_tvb, POLICY_LOAD_OFFSET, POLICY_LOAD_LENGTH,
336 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_LOAD_OFFSET) / (double)0xffffffff, "%1.2f%%",
337 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_LOAD_OFFSET) / (double)0xffffffff);
338 proto_tree_add_double_format_value(parameter_tree, hf_policy_degradation, parameter_tvb, POLICY_DEGRADATION_OFFSET, POLICY_DEGRADATION_LENGTH,
339 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_DEGRADATION_OFFSET) / (double)0xffffffff, "%1.2f%%",
340 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_DEGRADATION_OFFSET) / (double)0xffffffff);
341 break;
342 case LEAST_USED_DPF_POLICY:
343 proto_tree_add_double_format_value(parameter_tree, hf_policy_load, parameter_tvb, POLICY_LOAD_OFFSET, POLICY_LOAD_LENGTH,
344 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_LOAD_OFFSET) / (double)0xffffffff, "%1.2f%%",
345 100.0 * tvb_get_ntohl(parameter_tvb, POLICY_LOAD_OFFSET) / (double)0xffffffff);
346 proto_tree_add_double_format_value(parameter_tree, hf_policy_loaddpf, parameter_tvb, POLICY_LUDPF_LOADDPF_OFFSET, POLICY_LUDPF_LOADDPF_LENGTH,
347 tvb_get_ntohl(parameter_tvb, POLICY_LUDPF_LOADDPF_OFFSET) / (double)0xffffffff, "%1.5f",
348 tvb_get_ntohl(parameter_tvb, POLICY_LUDPF_LOADDPF_OFFSET) / (double)0xffffffff);
349 proto_tree_add_item(parameter_tree, hf_policy_distance, parameter_tvb, POLICY_LUDPF_DISTANCE_OFFSET, POLICY_LUDPF_DISTANCE_LENGTH, ENC_BIG_ENDIAN);
350 break;
351 case WEIGHTED_RANDOM_DPF_POLICY:
352 proto_tree_add_item(parameter_tree, hf_policy_weight, parameter_tvb, POLICY_WEIGHT_OFFSET, POLICY_WEIGHT_LENGTH, ENC_BIG_ENDIAN);
353 proto_tree_add_double_format_value(parameter_tree, hf_policy_weightdpf, parameter_tvb, POLICY_WRANDDPF_WEIGHTDPF_OFFSET, POLICY_WRANDDPF_WEIGHTDPF_LENGTH,
354 tvb_get_ntohl(parameter_tvb, POLICY_WRANDDPF_WEIGHTDPF_OFFSET) / (double)0xffffffff, "%1.5f",
355 tvb_get_ntohl(parameter_tvb, POLICY_WRANDDPF_WEIGHTDPF_OFFSET) / (double)0xffffffff);
356 proto_tree_add_item(parameter_tree, hf_policy_distance, parameter_tvb, POLICY_WRANDDPF_DISTANCE_OFFSET, POLICY_WRANDDPF_DISTANCE_LENGTH, ENC_BIG_ENDIAN);
357 break;
358 default:
359 length = tvb_reported_length(parameter_tvb) - POLICY_VALUE_OFFSET;
360 if (length > 0) {
361 proto_tree_add_item(parameter_tree, hf_policy_value, parameter_tvb, POLICY_VALUE_OFFSET, length, ENC_NA);
363 break;
367 static void
368 dissect_pool_handle_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
370 uint16_t handle_length;
371 proto_item* pi;
373 handle_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
374 pi = proto_tree_add_item(parameter_tree, hf_pool_handle, parameter_tvb, POOL_HANDLE_OFFSET, handle_length, ENC_NA);
376 proto_item_append_text(pi, " (%s)",
377 tvb_format_text(pinfo->pool, parameter_tvb, POOL_HANDLE_OFFSET, handle_length) );
380 static void
381 // NOLINTNEXTLINE(misc-no-recursion)
382 dissect_pool_element_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
384 tvbuff_t* parameters_tvb;
386 proto_tree_add_item(parameter_tree, hf_pe_pe_identifier, parameter_tvb, PE_PE_IDENTIFIER_OFFSET, PE_PE_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
387 proto_tree_add_item(parameter_tree, hf_home_enrp_id, parameter_tvb, HOME_ENRP_INDENTIFIER_OFFSET, HOME_ENRP_INDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
388 proto_tree_add_item(parameter_tree, hf_reg_life, parameter_tvb, REGISTRATION_LIFE_OFFSET, REGISTRATION_LIFE_LENGTH, ENC_BIG_ENDIAN);
390 parameters_tvb = tvb_new_subset_remaining(parameter_tvb, USER_TRANSPORT_PARAMETER_OFFSET);
391 dissect_parameters(parameters_tvb, pinfo, parameter_tree);
394 static void
395 // NOLINTNEXTLINE(misc-no-recursion)
396 dissect_server_information_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
398 tvbuff_t *parameters_tvb;
400 proto_tree_add_item(parameter_tree, hf_server_identifier, parameter_tvb, SERVER_ID_OFFSET, SERVER_ID_LENGTH, ENC_BIG_ENDIAN);
402 parameters_tvb = tvb_new_subset_remaining(parameter_tvb, SERVER_TRANSPORT_OFFSET);
403 dissect_parameters(parameters_tvb, pinfo, parameter_tree);
406 static void
407 // NOLINTNEXTLINE(misc-no-recursion)
408 dissect_operation_error_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
410 tvbuff_t *error_causes_tvb;
412 error_causes_tvb = tvb_new_subset_remaining(parameter_tvb, ERROR_CAUSES_OFFSET);
413 dissect_error_causes(error_causes_tvb, pinfo, parameter_tree);
416 static void
417 dissect_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
419 uint16_t cookie_length;
421 cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
422 if (cookie_length > 0)
423 proto_tree_add_item(parameter_tree, hf_cookie, parameter_tvb, COOKIE_OFFSET, cookie_length, ENC_NA);
424 proto_item_append_text(parameter_item, " (%u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
427 static void
428 dissect_pe_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
430 proto_tree_add_item(parameter_tree, hf_pe_identifier, parameter_tvb, PE_IDENTIFIER_OFFSET, PE_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
431 proto_item_append_text(parameter_item, " (0x%x)", tvb_get_ntohl(parameter_tvb, PE_IDENTIFIER_OFFSET));
434 static void
435 dissect_pe_checksum_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
437 proto_tree_add_item(parameter_tree, hf_pe_checksum, parameter_tvb, PE_CHECKSUM_OFFSET, PE_CHECKSUM_LENGTH, ENC_BIG_ENDIAN);
438 proto_item_append_text(parameter_item, " (0x%x)", tvb_get_ntohs(parameter_tvb, PE_CHECKSUM_OFFSET));
441 static void
442 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
444 uint16_t type, parameter_value_length;
446 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
447 parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
449 if (parameter_value_length > 0)
450 proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, ENC_NA);
452 proto_item_append_text(parameter_item, " (type %u and %u byte%s value)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
455 static void
456 // NOLINTNEXTLINE(misc-no-recursion)
457 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *enrp_tree)
459 uint16_t type, length, padding_length;
460 proto_tree *parameter_item;
461 proto_tree *parameter_tree;
463 unsigned recursion_depth = p_get_proto_depth(pinfo, proto_enrp);
465 if (recursion_depth > ENRP_MAX_RECURSION_DEPTH) {
466 proto_tree_add_expert(enrp_tree, pinfo, &ei_enrp_max_recursion_depth_reached,
467 parameter_tvb, 0, 0);
468 return;
470 p_set_proto_depth(pinfo, proto_enrp, recursion_depth + 1);
472 /* extract tag and length from the parameter */
473 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
474 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
475 padding_length = tvb_captured_length(parameter_tvb) - length;
477 /* create proto_tree stuff */
478 parameter_tree = proto_tree_add_subtree(enrp_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, -1,
479 ett_enrp_parameter, &parameter_item, val_to_str_const(type, parameter_type_values, "Unknown Parameter"));
481 /* add tag and length to the enrp tree */
482 proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, ENC_BIG_ENDIAN);
483 proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN);
485 switch(type) {
486 case IPV4_ADDRESS_PARAMETER_TYPE:
487 dissect_ipv4_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
488 break;
489 case IPV6_ADDRESS_PARAMETER_TYPE:
490 dissect_ipv6_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
491 break;
492 case DCCP_TRANSPORT_PARAMETER_TYPE:
493 dissect_dccp_transport_parameter(parameter_tvb, pinfo, parameter_tree);
494 break;
495 case SCTP_TRANSPORT_PARAMETER_TYPE:
496 dissect_sctp_transport_parameter(parameter_tvb, pinfo, parameter_tree);
497 break;
498 case TCP_TRANSPORT_PARAMETER_TYPE:
499 dissect_tcp_transport_parameter(parameter_tvb, pinfo, parameter_tree);
500 break;
501 case UDP_TRANSPORT_PARAMETER_TYPE:
502 dissect_udp_transport_parameter(parameter_tvb, pinfo, parameter_tree);
503 break;
504 case UDP_LITE_TRANSPORT_PARAMETER_TYPE:
505 dissect_udp_lite_transport_parameter(parameter_tvb, pinfo, parameter_tree);
506 break;
507 case POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE:
508 dissect_pool_member_selection_policy_parameter(parameter_tvb, parameter_tree);
509 break;
510 case POOL_HANDLE_PARAMETER_TYPE:
511 dissect_pool_handle_parameter(parameter_tvb, pinfo, parameter_tree);
512 break;
513 case POOL_ELEMENT_PARAMETER_TYPE:
514 dissect_pool_element_parameter(parameter_tvb, pinfo, parameter_tree);
515 break;
516 case SERVER_INFORMATION_PARAMETER_TYPE:
517 dissect_server_information_parameter(parameter_tvb, pinfo, parameter_tree);
518 break;
519 case OPERATION_ERROR_PARAMETER_TYPE:
520 dissect_operation_error_parameter(parameter_tvb, pinfo, parameter_tree);
521 break;
522 case COOKIE_PARAMETER_TYPE:
523 dissect_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
524 break;
525 case PE_IDENTIFIER_PARAMETER_TYPE:
526 dissect_pe_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
527 break;
528 case PE_CHECKSUM_PARAMETER_TYPE:
529 dissect_pe_checksum_parameter(parameter_tvb, parameter_tree, parameter_item);
530 break;
531 default:
532 dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
533 break;
536 if (padding_length > 0)
537 proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_NA);
539 p_set_proto_depth(pinfo, proto_enrp, recursion_depth);
542 static void
543 // NOLINTNEXTLINE(misc-no-recursion)
544 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree)
546 int offset, length, total_length, remaining_length;
547 tvbuff_t *parameter_tvb;
549 offset = 0;
550 while((remaining_length = tvb_reported_length_remaining(parameters_tvb, offset)) > 0) {
551 length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
552 if (length < 4) {
553 proto_tree_add_expert(tree, pinfo, &ei_enrp_invalid_length,
554 parameters_tvb, offset + PARAMETER_LENGTH_OFFSET, 2);
555 return;
557 total_length = WS_ROUNDUP_4(length);
558 if (remaining_length >= length)
559 total_length = MIN(total_length, remaining_length);
560 /* create a tvb for the parameter including the padding bytes */
561 parameter_tvb = tvb_new_subset_length(parameters_tvb, offset, total_length);
562 dissect_parameter(parameter_tvb, pinfo, tree);
563 /* get rid of the handled parameter */
564 offset += total_length;
568 /* Dissectors for messages. This is specific to ENRP */
570 #define SENDER_SERVERS_ID_LENGTH 4
571 #define RECEIVER_SERVERS_ID_LENGTH 4
573 #define SENDER_SERVERS_ID_OFFSET MESSAGE_VALUE_OFFSET
574 #define RECEIVER_SERVERS_ID_OFFSET (SENDER_SERVERS_ID_OFFSET + SENDER_SERVERS_ID_LENGTH)
575 #define MESSAGE_PARAMETERS_OFFSET (RECEIVER_SERVERS_ID_OFFSET + RECEIVER_SERVERS_ID_LENGTH)
577 #define REPLY_REQUIRED_BIT_MASK 0x01
579 static const true_false_string reply_required_bit_value = {
580 "Reply required",
581 "Reply not required"
584 static void
585 // NOLINTNEXTLINE(misc-no-recursion)
586 dissect_enrp_presence_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *message_tree, proto_tree *flags_tree)
588 tvbuff_t *parameters_tvb;
590 proto_tree_add_item(flags_tree, hf_reply_required_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
591 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
592 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
593 parameters_tvb = tvb_new_subset_remaining(message_tvb, MESSAGE_PARAMETERS_OFFSET);
594 dissect_parameters(parameters_tvb, pinfo, message_tree);
597 #define OWN_CHILDREN_ONLY_BIT_MASK 0x01
599 static const true_false_string own_children_only_bit_value = {
600 "Only information for own PEs",
601 "Information for all PEs"
605 static void
606 dissect_enrp_handle_table_request_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree)
608 /* FIXME: ensure that the length is 12 bytes. */
609 proto_tree_add_item(flags_tree, hf_own_children_only_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
610 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
611 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
614 #define REJECT_BIT_MASK 0x01
615 #define MORE_TO_SEND_BIT_MASK 0x02
617 static const true_false_string reject_bit_value = {
618 "Rejected",
619 "Accepted"
622 static const true_false_string more_to_send_bit_value = {
623 "More information available",
624 "All information included"
627 static void
628 // NOLINTNEXTLINE(misc-no-recursion)
629 dissect_enrp_handle_table_response_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *message_tree, proto_tree *flags_tree)
631 tvbuff_t *parameters_tvb;
633 proto_tree_add_item(flags_tree, hf_more_to_send_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
634 proto_tree_add_item(flags_tree, hf_reject_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
635 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
636 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
637 parameters_tvb = tvb_new_subset_remaining(message_tvb, MESSAGE_PARAMETERS_OFFSET);
638 dissect_parameters(parameters_tvb, pinfo, message_tree);
641 #define UPDATE_ACTION_LENGTH 2
642 #define PNU_RESERVED_LENGTH 2
644 #define UPDATE_ACTION_OFFSET (MESSAGE_VALUE_OFFSET + SENDER_SERVERS_ID_LENGTH + RECEIVER_SERVERS_ID_LENGTH)
645 #define PNU_RESERVED_OFFSET (UPDATE_ACTION_OFFSET + UPDATE_ACTION_LENGTH)
646 #define PNU_MESSAGE_PARAMETERS_OFFSET (PNU_RESERVED_OFFSET + PNU_RESERVED_LENGTH)
648 static const value_string update_action_values[] = {
649 { 0, "Add pool element" },
650 { 1, "Delete pool element" },
651 { 0, NULL } };
653 #define TOS_BIT_MASK 0x01
655 static const true_false_string tos_bit_value = {
656 "Takeover suggested",
657 "Takeover not suggested"
660 static void
661 // NOLINTNEXTLINE(misc-no-recursion)
662 dissect_enrp_handle_update_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *message_tree, proto_tree *flags_tree)
664 tvbuff_t *parameters_tvb;
666 proto_tree_add_item(flags_tree, hf_tos_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
667 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
668 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
669 proto_tree_add_item(message_tree, hf_update_action, message_tvb, UPDATE_ACTION_OFFSET, UPDATE_ACTION_LENGTH, ENC_BIG_ENDIAN);
670 proto_tree_add_item(message_tree, hf_pmu_reserved, message_tvb, PNU_RESERVED_OFFSET, PNU_RESERVED_LENGTH, ENC_BIG_ENDIAN);
671 parameters_tvb = tvb_new_subset_remaining(message_tvb, PNU_MESSAGE_PARAMETERS_OFFSET);
672 dissect_parameters(parameters_tvb, pinfo, message_tree);
675 static void
676 dissect_enrp_list_request_message(tvbuff_t *message_tvb, packet_info *pinfo _U_, proto_tree *message_tree, proto_tree *flags_tree _U_)
678 /* FIXME: ensure that the length is 12 bytes. */
679 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
680 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
683 static void
684 // NOLINTNEXTLINE(misc-no-recursion)
685 dissect_enrp_list_response_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *message_tree, proto_tree *flags_tree)
687 tvbuff_t *parameters_tvb;
689 proto_tree_add_item(flags_tree, hf_reject_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
690 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
691 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
692 parameters_tvb = tvb_new_subset_remaining(message_tvb, MESSAGE_PARAMETERS_OFFSET);
693 dissect_parameters(parameters_tvb, pinfo, message_tree);
696 #define TARGET_SERVERS_ID_LENGTH 4
697 #define TARGET_SERVERS_ID_OFFSET (RECEIVER_SERVERS_ID_OFFSET + RECEIVER_SERVERS_ID_LENGTH)
699 static void
700 dissect_enrp_init_takeover_message(tvbuff_t *message_tvb, packet_info *pinfo _U_, proto_tree *message_tree, proto_tree *flags_tree _U_)
702 /* FIXME: ensure that the length is 16 bytes. */
703 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
704 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
705 proto_tree_add_item(message_tree, hf_target_servers_id, message_tvb, TARGET_SERVERS_ID_OFFSET, TARGET_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
708 static void
709 dissect_enrp_init_takeover_ack_message(tvbuff_t *message_tvb, packet_info *pinfo _U_, proto_tree *message_tree, proto_tree *flags_tree _U_)
711 /* FIXME: ensure that the length is 16 bytes. */
712 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
713 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
714 proto_tree_add_item(message_tree, hf_target_servers_id, message_tvb, TARGET_SERVERS_ID_OFFSET, TARGET_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
717 static void
718 dissect_enrp_init_takeover_server_message(tvbuff_t *message_tvb, packet_info *pinfo _U_, proto_tree *message_tree, proto_tree *flags_tree _U_)
720 /* FIXME: ensure that the length is 16 bytes. */
721 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
722 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
723 proto_tree_add_item(message_tree, hf_target_servers_id, message_tvb, TARGET_SERVERS_ID_OFFSET, TARGET_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
726 static void
727 // NOLINTNEXTLINE(misc-no-recursion)
728 dissect_enrp_error_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *message_tree, proto_tree *flags_tree _U_)
730 tvbuff_t *parameters_tvb;
732 proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
733 proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, ENC_BIG_ENDIAN);
734 parameters_tvb = tvb_new_subset_remaining(message_tvb, MESSAGE_PARAMETERS_OFFSET);
735 dissect_parameters(parameters_tvb, pinfo, message_tree);
738 static void
739 dissect_unknown_message(tvbuff_t *message_tvb, packet_info *pinfo _U_, proto_tree *message_tree, proto_tree *flags_tree _U_)
741 proto_tree_add_item(message_tree, hf_message_value, message_tvb, MESSAGE_VALUE_OFFSET, tvb_captured_length(message_tvb) - MESSAGE_HEADER_LENGTH, ENC_NA);
744 #define ENRP_PRESENCE_MESSAGE_TYPE 0x01
745 #define ENRP_HANDLE_TABLE_REQUEST_MESSAGE_TYPE 0x02
746 #define ENRP_HANDLE_TABLE_RESPONSE_MESSAGE_TYPE 0x03
747 #define ENRP_HANDLE_UPDATE_MESSAGE_TYPE 0x04
748 #define ENRP_LIST_REQUEST_MESSAGE_TYPE 0x05
749 #define ENRP_LIST_RESPONSE_MESSAGE_TYPE 0x06
750 #define ENRP_INIT_TAKEOVER_MESSAGE_TYPE 0x07
751 #define ENRP_INIT_TAKEOVER_ACK_MESSAGE_TYPE 0x08
752 #define ENRP_TAKEOVER_SERVER_MESSAGE_TYPE 0x09
753 #define ENRP_ERROR_MESSAGE_TYPE 0x0a
755 static const value_string message_type_values[] = {
756 { ENRP_PRESENCE_MESSAGE_TYPE, "ENRP Presence" },
757 { ENRP_HANDLE_TABLE_REQUEST_MESSAGE_TYPE, "ENRP Handle Table Request" },
758 { ENRP_HANDLE_TABLE_RESPONSE_MESSAGE_TYPE, "ENRP Handle Table Response" },
759 { ENRP_HANDLE_UPDATE_MESSAGE_TYPE, "ENRP Handle Update" },
760 { ENRP_LIST_REQUEST_MESSAGE_TYPE, "ENRP List Request" },
761 { ENRP_LIST_RESPONSE_MESSAGE_TYPE, "ENRP List Response" },
762 { ENRP_INIT_TAKEOVER_MESSAGE_TYPE, "ENRP Init Takeover" },
763 { ENRP_INIT_TAKEOVER_ACK_MESSAGE_TYPE, "ENRP Init Takeover Ack" },
764 { ENRP_TAKEOVER_SERVER_MESSAGE_TYPE, "ENRP Takeover Server" },
765 { ENRP_ERROR_MESSAGE_TYPE, "ENRP Error" },
766 { 0, NULL } };
768 static void
769 // NOLINTNEXTLINE(misc-no-recursion)
770 dissect_enrp_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *enrp_tree)
772 enrp_tap_rec_t *tap_rec;
773 proto_item *flags_item;
774 proto_tree *flags_tree;
775 uint8_t type;
777 type = tvb_get_uint8(message_tvb, MESSAGE_TYPE_OFFSET);
778 if (p_get_proto_depth(pinfo, proto_enrp) == 1) {
779 tap_rec = wmem_new0(pinfo->pool, enrp_tap_rec_t);
780 tap_rec->type = type;
781 tap_rec->size = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET);
782 tap_rec->type_string = val_to_str_const(tap_rec->type, message_type_values, "Unknown ENRP type");
783 tap_queue_packet(enrp_tap, pinfo, tap_rec);
785 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(type, message_type_values, "Unknown ENRP Type"));
788 if (enrp_tree) {
789 proto_tree_add_item(enrp_tree, hf_message_type, message_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, ENC_BIG_ENDIAN);
790 flags_item = proto_tree_add_item(enrp_tree, hf_message_flags, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
791 flags_tree = proto_item_add_subtree(flags_item, ett_enrp_flags);
792 proto_tree_add_item(enrp_tree, hf_message_length, message_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, ENC_BIG_ENDIAN);
793 switch (type) {
794 case ENRP_PRESENCE_MESSAGE_TYPE:
795 dissect_enrp_presence_message(message_tvb, pinfo, enrp_tree, flags_tree);
796 break;
797 case ENRP_HANDLE_TABLE_REQUEST_MESSAGE_TYPE:
798 dissect_enrp_handle_table_request_message(message_tvb, enrp_tree, flags_tree);
799 break;
800 case ENRP_HANDLE_TABLE_RESPONSE_MESSAGE_TYPE:
801 dissect_enrp_handle_table_response_message(message_tvb, pinfo, enrp_tree, flags_tree);
802 break;
803 case ENRP_HANDLE_UPDATE_MESSAGE_TYPE:
804 dissect_enrp_handle_update_message(message_tvb, pinfo, enrp_tree, flags_tree);
805 break;
806 case ENRP_LIST_REQUEST_MESSAGE_TYPE:
807 dissect_enrp_list_request_message(message_tvb, pinfo, enrp_tree, flags_tree);
808 break;
809 case ENRP_LIST_RESPONSE_MESSAGE_TYPE:
810 dissect_enrp_list_response_message(message_tvb, pinfo, enrp_tree, flags_tree);
811 break;
812 case ENRP_INIT_TAKEOVER_MESSAGE_TYPE:
813 dissect_enrp_init_takeover_message(message_tvb, pinfo, enrp_tree, flags_tree);
814 break;
815 case ENRP_INIT_TAKEOVER_ACK_MESSAGE_TYPE:
816 dissect_enrp_init_takeover_ack_message(message_tvb, pinfo, enrp_tree, flags_tree);
817 break;
818 case ENRP_TAKEOVER_SERVER_MESSAGE_TYPE:
819 dissect_enrp_init_takeover_server_message(message_tvb, pinfo, enrp_tree, flags_tree);
820 break;
821 case ENRP_ERROR_MESSAGE_TYPE:
822 dissect_enrp_error_message(message_tvb, pinfo, enrp_tree, flags_tree);
823 break;
824 default:
825 dissect_unknown_message(message_tvb, pinfo, enrp_tree, flags_tree);
826 break;
831 static void
832 // NOLINTNEXTLINE(misc-no-recursion)
833 dissect_enrp_main(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
835 proto_item *enrp_item;
836 proto_tree *enrp_tree;
837 unsigned recursion_depth = p_get_proto_depth(pinfo, proto_enrp);
839 if (recursion_depth > ENRP_MAX_RECURSION_DEPTH) {
840 proto_tree_add_expert(tree, pinfo, &ei_enrp_max_recursion_depth_reached,
841 message_tvb, 0, 0);
842 return;
844 p_set_proto_depth(pinfo, proto_enrp, recursion_depth + 1);
846 /* create the enrp protocol tree */
847 enrp_item = proto_tree_add_item(tree, proto_enrp, message_tvb, 0, -1, ENC_NA);
848 enrp_tree = proto_item_add_subtree(enrp_item, ett_enrp);
850 /* dissect the message */
851 dissect_enrp_message(message_tvb, pinfo, enrp_tree);
854 static int
855 dissect_enrp(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
857 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENRP");
859 dissect_enrp_main(message_tvb, pinfo, tree);
860 return tvb_captured_length(message_tvb);
863 /* TAP STAT INFO */
864 typedef enum
866 MESSAGE_TYPE_COLUMN = 0,
867 MESSAGES_COLUMN,
868 MESSAGES_SHARE_COLUMN,
869 BYTES_COLUMN,
870 BYTES_SHARE_COLUMN,
871 FIRST_SEEN_COLUMN,
872 LAST_SEEN_COLUMN,
873 INTERVAL_COLUMN,
874 MESSAGE_RATE_COLUMN,
875 BYTE_RATE_COLUMN
876 } enrp_stat_columns;
878 static stat_tap_table_item enrp_stat_fields[] = {
879 { TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "NetPerfMeter Message Type", "%-25s" },
880 { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Messages ", "%u" },
881 { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Messages Share (%)" , "%1.3f %%" },
882 { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Bytes (B)", "%u" },
883 { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Bytes Share (%) ", "%1.3f %%" },
884 { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "First Seen (s)", "%1.6f" },
885 { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Last Seen (s)", "%1.6f" },
886 { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Interval (s)", "%1.6f" },
887 { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Message Rate (Msg/s)", "%1.2f" },
888 { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Byte Rate (B/s)", "%1.2f" }
891 static void enrp_stat_init(stat_tap_table_ui* new_stat)
893 const char *table_name = "NetPerfMeter Statistics";
894 int num_fields = array_length(enrp_stat_fields);
895 stat_tap_table *table;
896 int i = 0;
897 stat_tap_table_item_type items[array_length(enrp_stat_fields)];
899 table = stat_tap_find_table(new_stat, table_name);
900 if (table) {
901 if (new_stat->stat_tap_reset_table_cb) {
902 new_stat->stat_tap_reset_table_cb(table);
904 return;
907 table = stat_tap_init_table(table_name, num_fields, 0, NULL);
908 stat_tap_add_table(new_stat, table);
910 memset(items, 0x0, sizeof(items));
911 /* Add a row for each value type */
912 while (message_type_values[i].strptr) {
913 items[MESSAGE_TYPE_COLUMN].type = TABLE_ITEM_STRING;
914 items[MESSAGE_TYPE_COLUMN].value.string_value = message_type_values[i].strptr;
915 items[MESSAGES_COLUMN].type = TABLE_ITEM_UINT;
916 items[MESSAGES_COLUMN].value.uint_value = 0;
917 items[MESSAGES_SHARE_COLUMN].type = TABLE_ITEM_NONE;
918 items[MESSAGES_SHARE_COLUMN].value.float_value = -1.0;
919 items[BYTES_COLUMN].type = TABLE_ITEM_UINT;
920 items[BYTES_COLUMN].value.uint_value = 0;
921 items[BYTES_SHARE_COLUMN].type = TABLE_ITEM_NONE;
922 items[BYTES_SHARE_COLUMN].value.float_value = -1.0;
923 items[FIRST_SEEN_COLUMN].type = TABLE_ITEM_NONE;
924 items[FIRST_SEEN_COLUMN].value.float_value = DBL_MAX;
925 items[LAST_SEEN_COLUMN].type = TABLE_ITEM_NONE;
926 items[LAST_SEEN_COLUMN].value.float_value = DBL_MIN;
927 items[INTERVAL_COLUMN].type = TABLE_ITEM_NONE;
928 items[INTERVAL_COLUMN].value.float_value = -1.0;
929 items[MESSAGE_RATE_COLUMN].type = TABLE_ITEM_NONE;
930 items[MESSAGE_RATE_COLUMN].value.float_value = -1.0;
931 items[BYTE_RATE_COLUMN].type = TABLE_ITEM_NONE;
932 items[BYTE_RATE_COLUMN].value.float_value = -1.0;
933 stat_tap_init_table_row(table, i, num_fields, items);
934 i++;
938 static tap_packet_status
939 enrp_stat_packet(void* tapdata, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* data, tap_flags_t flags _U_)
941 stat_data_t* stat_data = (stat_data_t*)tapdata;
942 const enrp_tap_rec_t* tap_rec = (const enrp_tap_rec_t*)data;
943 stat_tap_table* table;
944 stat_tap_table_item_type* msg_data;
945 int idx;
946 uint64_t messages;
947 uint64_t bytes;
948 int i = 0;
949 double firstSeen = -1.0;
950 double lastSeen = -1.0;
952 idx = str_to_val_idx(tap_rec->type_string, message_type_values);
953 if (idx < 0)
954 return TAP_PACKET_DONT_REDRAW;
956 table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0);
958 /* Update packets counter */
959 enrp_total_msgs++;
960 msg_data = stat_tap_get_field_data(table, idx, MESSAGES_COLUMN);
961 msg_data->value.uint_value++;
962 messages = msg_data->value.uint_value;
963 stat_tap_set_field_data(table, idx, MESSAGES_COLUMN, msg_data);
965 /* Update bytes counter */
966 enrp_total_bytes += tap_rec->size;
967 msg_data = stat_tap_get_field_data(table, idx, BYTES_COLUMN);
968 msg_data->value.uint_value += tap_rec->size;
969 bytes = msg_data->value.uint_value;
970 stat_tap_set_field_data(table, idx, BYTES_COLUMN, msg_data);
972 /* Update messages and bytes share */
973 while (message_type_values[i].strptr) {
974 msg_data = stat_tap_get_field_data(table, i, MESSAGES_COLUMN);
975 const unsigned m = msg_data->value.uint_value;
976 msg_data = stat_tap_get_field_data(table, i, BYTES_COLUMN);
977 const unsigned b = msg_data->value.uint_value;
979 msg_data = stat_tap_get_field_data(table, i, MESSAGES_SHARE_COLUMN);
980 msg_data->type = TABLE_ITEM_FLOAT;
981 msg_data->value.float_value = 100.0 * m / (double)enrp_total_msgs;
982 stat_tap_set_field_data(table, i, MESSAGES_SHARE_COLUMN, msg_data);
984 msg_data = stat_tap_get_field_data(table, i, BYTES_SHARE_COLUMN);
985 msg_data->type = TABLE_ITEM_FLOAT;
986 msg_data->value.float_value = 100.0 * b / (double)enrp_total_bytes;
987 stat_tap_set_field_data(table, i, BYTES_SHARE_COLUMN, msg_data);
988 i++;
991 /* Update first seen time */
992 if (pinfo->presence_flags & PINFO_HAS_TS) {
993 msg_data = stat_tap_get_field_data(table, idx, FIRST_SEEN_COLUMN);
994 msg_data->type = TABLE_ITEM_FLOAT;
995 msg_data->value.float_value = MIN(msg_data->value.float_value, nstime_to_sec(&pinfo->rel_ts));
996 firstSeen = msg_data->value.float_value;
997 stat_tap_set_field_data(table, idx, FIRST_SEEN_COLUMN, msg_data);
1000 /* Update last seen time */
1001 if (pinfo->presence_flags & PINFO_HAS_TS) {
1002 msg_data = stat_tap_get_field_data(table, idx, LAST_SEEN_COLUMN);
1003 msg_data->type = TABLE_ITEM_FLOAT;
1004 msg_data->value.float_value = MAX(msg_data->value.float_value, nstime_to_sec(&pinfo->rel_ts));
1005 lastSeen = msg_data->value.float_value;
1006 stat_tap_set_field_data(table, idx, LAST_SEEN_COLUMN, msg_data);
1009 if ((lastSeen - firstSeen) > 0.0) {
1010 /* Update interval */
1011 msg_data = stat_tap_get_field_data(table, idx, INTERVAL_COLUMN);
1012 msg_data->type = TABLE_ITEM_FLOAT;
1013 msg_data->value.float_value = lastSeen - firstSeen;
1014 stat_tap_set_field_data(table, idx, INTERVAL_COLUMN, msg_data);
1016 /* Update message rate */
1017 msg_data = stat_tap_get_field_data(table, idx, MESSAGE_RATE_COLUMN);
1018 msg_data->type = TABLE_ITEM_FLOAT;
1019 msg_data->value.float_value = messages / (lastSeen - firstSeen);
1020 stat_tap_set_field_data(table, idx, MESSAGE_RATE_COLUMN, msg_data);
1022 /* Update byte rate */
1023 msg_data = stat_tap_get_field_data(table, idx, BYTE_RATE_COLUMN);
1024 msg_data->type = TABLE_ITEM_FLOAT;
1025 msg_data->value.float_value = bytes / (lastSeen - firstSeen);
1026 stat_tap_set_field_data(table, idx, BYTE_RATE_COLUMN, msg_data);
1029 return TAP_PACKET_REDRAW;
1032 static void
1033 enrp_stat_reset(stat_tap_table* table)
1035 unsigned element;
1036 stat_tap_table_item_type* item_data;
1038 for (element = 0; element < table->num_elements; element++) {
1039 item_data = stat_tap_get_field_data(table, element, MESSAGES_COLUMN);
1040 item_data->value.uint_value = 0;
1041 stat_tap_set_field_data(table, element, MESSAGES_COLUMN, item_data);
1043 item_data = stat_tap_get_field_data(table, element, MESSAGES_SHARE_COLUMN);
1044 item_data->type = TABLE_ITEM_NONE;
1045 item_data->value.float_value = -1.0;
1046 stat_tap_set_field_data(table, element, MESSAGES_SHARE_COLUMN, item_data);
1048 item_data = stat_tap_get_field_data(table, element, BYTES_COLUMN);
1049 item_data->value.uint_value = 0;
1050 stat_tap_set_field_data(table, element, BYTES_COLUMN, item_data);
1052 item_data = stat_tap_get_field_data(table, element, BYTES_SHARE_COLUMN);
1053 item_data->type = TABLE_ITEM_NONE;
1054 item_data->value.float_value = -1.0;
1055 stat_tap_set_field_data(table, element, BYTES_SHARE_COLUMN, item_data);
1057 item_data = stat_tap_get_field_data(table, element, FIRST_SEEN_COLUMN);
1058 item_data->type = TABLE_ITEM_NONE;
1059 item_data->value.float_value = DBL_MAX;
1060 stat_tap_set_field_data(table, element, FIRST_SEEN_COLUMN, item_data);
1062 item_data = stat_tap_get_field_data(table, element, LAST_SEEN_COLUMN);
1063 item_data->type = TABLE_ITEM_NONE;
1064 item_data->value.float_value = DBL_MIN;
1065 stat_tap_set_field_data(table, element, LAST_SEEN_COLUMN, item_data);
1067 item_data = stat_tap_get_field_data(table, element, INTERVAL_COLUMN);
1068 item_data->type = TABLE_ITEM_NONE;
1069 item_data->value.float_value = -1.0;
1070 stat_tap_set_field_data(table, element, INTERVAL_COLUMN, item_data);
1072 item_data = stat_tap_get_field_data(table, element, MESSAGE_RATE_COLUMN);
1073 item_data->type = TABLE_ITEM_NONE;
1074 item_data->value.float_value = -1.0;
1075 stat_tap_set_field_data(table, element, MESSAGE_RATE_COLUMN, item_data);
1077 item_data = stat_tap_get_field_data(table, element, BYTE_RATE_COLUMN);
1078 item_data->type = TABLE_ITEM_NONE;
1079 item_data->value.float_value = -1.0;
1080 stat_tap_set_field_data(table, element, BYTE_RATE_COLUMN, item_data);
1082 enrp_total_msgs = 0;
1083 enrp_total_bytes = 0;
1086 /* Register the protocol with Wireshark */
1087 void
1088 proto_register_enrp(void)
1091 /* Setup list of header fields */
1092 static hf_register_info hf[] = {
1093 { &hf_message_type, { "Type", "enrp.message_type", FT_UINT8, BASE_DEC, VALS(message_type_values), 0x0, NULL, HFILL } },
1094 { &hf_message_flags, { "Flags", "enrp.message_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1095 { &hf_message_length, { "Length", "enrp.message_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1096 { &hf_message_value, { "Value", "enrp.message_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1097 { &hf_cause_code, { "Cause Code", "enrp.cause_code", FT_UINT16, BASE_HEX, VALS(cause_code_values), 0x0, NULL, HFILL } },
1098 { &hf_cause_length, { "Cause Length", "enrp.cause_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1099 { &hf_cause_info, { "Cause Info", "enrp.cause_info", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1100 { &hf_cause_padding, { "Padding", "enrp.cause_padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1101 { &hf_parameter_type, { "Parameter Type", "enrp.parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_type_values), 0x0, NULL, HFILL } },
1102 { &hf_parameter_length, { "Parameter Length", "enrp.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1103 { &hf_parameter_value, { "Parameter Value", "enrp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1104 { &hf_parameter_padding, { "Padding", "enrp.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1105 { &hf_parameter_ipv4_address, { "IP Version 4 Address", "enrp.ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1106 { &hf_parameter_ipv6_address, { "IP Version 6 Address", "enrp.ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1107 { &hf_dccp_port, { "Port", "enrp.dccp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1108 { &hf_dccp_reserved, { "Reserved", "enrp.dccp_transport_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1109 { &hf_dccp_service_code, { "Service Code", "enrp.dccp_transport_service_code", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1110 { &hf_sctp_port, { "Port", "enrp.sctp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1111 { &hf_transport_use, { "Transport Use", "enrp.transport_use", FT_UINT16, BASE_DEC, VALS(transport_use_values), 0x0, NULL, HFILL } },
1112 { &hf_tcp_port, { "Port", "enrp.tcp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1113 { &hf_udp_port, { "Port", "enrp.udp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1114 { &hf_udp_reserved, { "Reserved", "enrp.udp_transport_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1115 { &hf_udp_lite_port, { "Port", "enrp.udp_lite_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1116 { &hf_udp_lite_reserved, { "Reserved", "enrp.udp_lite_transport_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1117 { &hf_policy_type, { "Policy Type", "enrp.pool_member_selection_policy_type", FT_UINT32, BASE_HEX, VALS(policy_type_values), 0x0, NULL, HFILL } },
1118 { &hf_policy_weight, { "Policy Weight", "enrp.pool_member_selection_policy_weight", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1119 { &hf_policy_priority, { "Policy Priority", "enrp.pool_member_selection_policy_priority", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1120 { &hf_policy_load, { "Policy Load", "enrp.pool_member_selection_policy_load", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1121 { &hf_policy_degradation, { "Policy Degradation", "enrp.pool_member_selection_policy_degradation", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1122 { &hf_policy_loaddpf, { "Policy Load DPF", "enrp.pool_member_selection_policy_load_dpf", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1123 { &hf_policy_weightdpf, { "Policy Weight DPF", "enrp.pool_member_selection_policy_weight_dpf", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1124 { &hf_policy_distance, { "Policy Distance", "enrp.pool_member_selection_policy_distance", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1125 { &hf_policy_value, { "Policy Value", "enrp.pool_member_selection_policy_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1126 { &hf_pool_handle, { "Pool Handle", "enrp.pool_handle_pool_handle", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1127 { &hf_pe_pe_identifier, { "PE Identifier", "enrp.pool_element_pe_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1128 { &hf_home_enrp_id, { "Home ENRP Server Identifier", "enrp.pool_element_home_enrp_server_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1129 { &hf_reg_life, { "Registration Life", "enrp.pool_element_registration_life", FT_INT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_milliseconds), 0x0, NULL, HFILL } },
1130 { &hf_server_identifier, { "Server Identifier", "enrp.server_information_server_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1131 { &hf_cookie, { "Cookie", "enrp.cookie", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1132 { &hf_pe_identifier, { "PE Identifier", "enrp.pe_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1133 { &hf_pe_checksum, { "PE Checksum", "enrp.pe_checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1134 { &hf_sender_servers_id, { "Sender Server's ID", "enrp.sender_servers_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1135 { &hf_receiver_servers_id, { "Receiver Server's ID", "enrp.receiver_servers_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1136 { &hf_target_servers_id, { "Target Server's ID", "enrp.target_servers_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1137 { &hf_update_action, { "Update Action", "enrp.update_action", FT_UINT16, BASE_DEC, VALS(update_action_values), 0x0, NULL, HFILL } },
1138 { &hf_pmu_reserved, { "Reserved", "enrp.reserved", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1139 { &hf_reply_required_bit, { "R Bit", "enrp.r_bit", FT_BOOLEAN, 8, TFS(&reply_required_bit_value), REPLY_REQUIRED_BIT_MASK, NULL, HFILL } },
1140 { &hf_own_children_only_bit, { "W Bit", "enrp.w_bit", FT_BOOLEAN, 8, TFS(&own_children_only_bit_value), OWN_CHILDREN_ONLY_BIT_MASK, NULL, HFILL } },
1141 { &hf_more_to_send_bit, { "M Bit", "enrp.m_bit", FT_BOOLEAN, 8, TFS(&more_to_send_bit_value), MORE_TO_SEND_BIT_MASK, NULL, HFILL } },
1142 { &hf_reject_bit, { "R Bit", "enrp.r_bit", FT_BOOLEAN, 8, TFS(&reject_bit_value), REJECT_BIT_MASK, NULL, HFILL } },
1143 { &hf_tos_bit, { "T Bit", "enrp.t_bit", FT_BOOLEAN, 8, TFS(&tos_bit_value), TOS_BIT_MASK, NULL, HFILL } },
1146 /* Setup protocol subtree array */
1147 static int *ett[] = {
1148 &ett_enrp,
1149 &ett_enrp_parameter,
1150 &ett_enrp_cause,
1151 &ett_enrp_flags,
1154 expert_module_t *expert_enrp;
1156 static ei_register_info ei[] = {
1157 { &ei_enrp_max_recursion_depth_reached, { "enrp.max_recursion_depth_reached",
1158 PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached - stop decoding", EXPFILL }},
1159 { &ei_enrp_invalid_length, { "enrp.invalid_length",
1160 PI_MALFORMED, PI_ERROR, "Parameter length must be at least 4 bytes", EXPFILL }}
1163 static tap_param enrp_stat_params[] = {
1164 { PARAM_FILTER, "filter", "Filter", NULL, true }
1167 static stat_tap_table_ui enrp_stat_table = {
1168 REGISTER_STAT_GROUP_RSERPOOL,
1169 "ENRP Statistics",
1170 "enrp",
1171 "enrp,stat",
1172 enrp_stat_init,
1173 enrp_stat_packet,
1174 enrp_stat_reset,
1175 NULL,
1176 NULL,
1177 array_length(enrp_stat_fields), enrp_stat_fields,
1178 array_length(enrp_stat_params), enrp_stat_params,
1179 NULL,
1183 /* Register the protocol name and description */
1184 proto_enrp = proto_register_protocol("Endpoint Handlespace Redundancy Protocol", "ENRP", "enrp");
1186 expert_enrp = expert_register_protocol(proto_enrp);
1187 expert_register_field_array(expert_enrp, ei, array_length(ei));
1189 /* Required function calls to register the header fields and subtrees used */
1190 proto_register_field_array(proto_enrp, hf, array_length(hf));
1191 proto_register_subtree_array(ett, array_length(ett));
1192 enrp_tap = register_tap("enrp");
1194 enrp_handle = register_dissector("enrp", dissect_enrp, proto_enrp);
1195 register_stat_tap_table_ui(&enrp_stat_table);
1198 void
1199 proto_reg_handoff_enrp(void)
1201 dissector_add_uint("sctp.ppi", ENRP_PAYLOAD_PROTOCOL_ID, enrp_handle);
1202 dissector_add_uint("sctp.port", ENRP_SCTP_PORT, enrp_handle);
1203 dissector_add_uint_with_preference("udp.port", ENRP_UDP_PORT, enrp_handle);
1207 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1209 * Local Variables:
1210 * c-basic-offset: 2
1211 * tab-width: 8
1212 * indent-tabs-mode: nil
1213 * End:
1215 * ex: set shiftwidth=2 tabstop=8 expandtab:
1216 * :indentSize=2:tabSize=8:noTabs=true: