3 * Routines for dissecting IETF ForCES protocol layer messages.Now support the following TML types:TCP+UDP,SCTP.
4 * Copyright 2009, NDSC & Zhejiang Gongshang University,Fenggen Jia <fgjia@mail.zjgsu.edu.cn or fenggen.jia@gmail.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/unit_strings.h>
20 void proto_register_forces(void);
21 void proto_reg_handoff_forces(void);
23 static dissector_handle_t forces_handle_tcp
, forces_handle
;
25 static dissector_handle_t ip_handle
;
27 /* Initialize the ForCES protocol and registered fields */
28 static int proto_forces
;
31 static int hf_forces_version
;
32 static int hf_forces_rsvd
;
33 static int hf_forces_messagetype
;
34 static int hf_forces_sid
;
35 static int hf_forces_did
;
36 static int hf_forces_correlator
;
37 static int hf_forces_length
;
39 static int hf_forces_flags
;
40 static int hf_forces_flags_ack
;
41 static int hf_forces_flags_pri
;
42 static int hf_forces_flags_rsrvd
;
43 static int hf_forces_flags_em
;
44 static int hf_forces_flags_at
;
45 static int hf_forces_flags_tp
;
46 static int hf_forces_flags_reserved
;
48 static int hf_forces_tlv_type
;
49 static int hf_forces_tlv_length
;
51 /*Initiation of LFBSelect TLV*/
52 static int hf_forces_lfbselect_tlv_type_lfb_classid
;
53 static int hf_forces_lfbselect_tlv_type_lfb_instanceid
;
55 /*Initiation of Operation TLV*/
56 static int hf_forces_lfbselect_tlv_type_operation_type
;
57 static int hf_forces_lfbselect_tlv_type_operation_length
;
58 static int hf_forces_lfbselect_tlv_type_operation_path_type
;
59 static int hf_forces_lfbselect_tlv_type_operation_path_length
;
60 static int hf_forces_lfbselect_tlv_type_operation_path_flags
;
61 static int hf_forces_lfbselect_tlv_type_operation_path_flags_selector
;
62 static int hf_forces_lfbselect_tlv_type_operation_path_flags_reserved
;
63 static int hf_forces_lfbselect_tlv_type_operation_path_IDcount
;
64 static int hf_forces_lfbselect_tlv_type_operation_path_IDs
;
65 static int hf_forces_lfbselect_tlv_type_operation_path_data
;
67 /*Initiation of Redirect TLV*/
68 static int hf_forces_redirect_tlv_meta_data_tlv_type
;
69 static int hf_forces_redirect_tlv_meta_data_tlv_length
;
70 static int hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv
;
71 static int hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_id
;
72 static int hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_length
;
73 static int hf_forces_redirect_tlv_redirect_data_tlv_type
;
74 static int hf_forces_redirect_tlv_redirect_data_tlv_length
;
76 /*Initiation of ASResult TLV*/
77 static int hf_forces_asresult_association_setup_result
;
79 /*Initiation of ASTreason TLV*/
80 static int hf_forces_astreason_tlv_teardown_reason
;
82 /*Main TLV may be unknown*/
83 static int hf_forces_unknown_tlv
;
86 #define AssociationSetup 0x01
87 #define AssociationTeardown 0x02
90 #define EventNotification 0x05
91 #define PacketRedirect 0x06
92 #define Heartbeat 0x0F
93 #define AssociationSetupResponse 0x11
94 #define ConfigResponse 0x13
95 #define QueryResponse 0x14
98 #define Reserved 0x0000
99 #define REDIRECT_TLV 0x0001
100 #define ASResult_TLV 0x0010
101 #define ASTreason_TLV 0x0011
102 #define LFBselect_TLV 0x1000
103 #define PATH_DATA_TLV 0x0110
104 #define KEYINFO_TLV 0x0111
105 #define FULLDATA_TLV 0x0112
106 #define SPARSEDATA_TLV 0x0113
107 #define RESULT_TLV 0x0114
108 #define METADATA_TLV 0x0115
109 #define REDIRECTDATA_TLV 0x0116
112 #define Reserved 0x0000
114 #define SET_PROP 0x0002
115 #define SET_RESPONSE 0x0003
116 #define SET_PROP_RESPONSE 0x0004
118 #define DEL_RESPONSE 0x0006
120 #define GET_PROP 0x0008
121 #define GET_RESPONSE 0x0009
122 #define GET_PROP_RESPONSE 0x000A
123 #define REPORT 0x000B
124 #define COMMIT 0x000C
125 #define COMMIT_RESPONSE 0x000D
126 #define TRCOMP 0x000E
128 #define FLAG_SELECTOR 0x8000
130 #define ForCES_HEADER_LENGTH 24
131 #define TLV_TL_LENGTH 4 /*Type+length*/
132 #define MIN_IP_HEADER_LENGTH 20
134 /*For TCP+UDP TML. There are two bytes added to the ForCES PL message, not strictly combine to the ForCES protocol.
135 For other type TMLs,no need to add these 2 bytes.*/
136 #define TCP_UDP_TML_FOCES_MESSAGE_OFFSET_TCP 2
139 static unsigned forces_alternate_sctp_high_prio_channel_port
;
140 static unsigned forces_alternate_sctp_med_prio_channel_port
;
141 static unsigned forces_alternate_sctp_low_prio_channel_port
;
143 /*Initialize the subtree pointers*/
144 static int ett_forces
;
145 static int ett_forces_main_header
;
146 static int ett_forces_flags
;
147 static int ett_forces_tlv
;
148 static int ett_forces_lfbselect_tlv_type
;
150 /*Operation TLV subtree*/
151 static int ett_forces_lfbselect_tlv_type_operation
;
152 static int ett_forces_lfbselect_tlv_type_operation_path
;
153 static int ett_forces_lfbselect_tlv_type_operation_path_data
;
154 static int ett_forces_lfbselect_tlv_type_operation_path_data_path
;
155 static int ett_forces_path_data_tlv
;
156 static int ett_forces_path_data_tlv_flags
;
159 static int ett_forces_lfbselect_tlv_type_operation_path_selector
;
161 /*Redirect TLV subtree*/
162 static int ett_forces_redirect_tlv_type
;
163 static int ett_forces_redirect_tlv_meta_data_tlv
;
164 static int ett_forces_redirect_tlv_meta_data_tlv_meta_data_ilv
;
165 static int ett_forces_redirect_tlv_redirect_data_tlv
;
167 /*ASResult TLV subtree*/
168 static int ett_forces_asresult_tlv
;
171 static int ett_forces_astreason_tlv
;
173 /*Main_TLV unknown subtree*/
174 static int ett_forces_unknown_tlv
;
177 static expert_field ei_forces_length
;
178 static expert_field ei_forces_tlv_type
;
179 static expert_field ei_forces_tlv_length
;
180 static expert_field ei_forces_lfbselect_tlv_type_operation_path_length
;
181 static expert_field ei_forces_lfbselect_tlv_type_operation_type
;
182 static expert_field ei_forces_redirect_tlv_redirect_data_tlv_length
;
184 /*ACK values and the strings to be displayed*/
185 static const value_string main_header_flags_ack_vals
[] = {
187 { 0x1, "SuccessACK" },
188 { 0x2, "FailureACK" },
189 { 0x3, "AlwaysACK" },
193 /*Execution mode(EM) values and the strings to be displayed*/
194 static const value_string main_header_flags_em_vals
[] = {
196 { 0x1, "Execute-all-or-none" },
197 { 0x2, "Execute-until-failure" },
198 { 0x3, "Continue-execute-on-failure" },
202 /*Transaction Phase values and the strings to be displayed*/
203 static const value_string main_header_flags_tp_vals
[] = {
204 { 0x0, "SOT (Start of Transaction)" },
205 { 0x1, "MOT (Middle of Transaction)" },
206 { 0x2, "EOT (End of Transaction)" },
207 { 0x3, "ABT (Abort)" },
211 /*Atomic Transaction(AT) values and the strings to be displayed*/
212 static const value_string main_header_flags_at_vals
[] = {
213 { 0x0, "Stand-alone Message"},
214 { 0x1, "2PC Transaction Message"},
218 /*Association Setup Result*/
219 static const value_string association_setup_result_at_vals
[] = {
221 { 0x1, "FE ID invalid"},
222 { 0x2, "permission denied"},
227 static const value_string teardown_reason_at_vals
[] = {
228 { 0x0, "normal-teardown by administrator"},
229 { 0x1, "error - loss of heartbeats"},
230 { 0x2, "error - out of bandwidth"},
231 { 0x3, "error - out of memory"},
232 { 0x4, "error - application crash"},
233 { 0x255, "error - other or unspecified"},
237 static const value_string message_type_vals
[] = {
238 { AssociationSetup
, "AssociationSetup" },
239 { AssociationTeardown
, "AssociationTeardown" },
240 { Config
, "Config" },
242 { EventNotification
, "EventNotification" },
243 { PacketRedirect
, "PacketRedirect" },
244 { Heartbeat
, "Heartbeat" },
245 { AssociationSetupResponse
, "AssociationSetupResponse" },
246 { ConfigResponse
, "ConfigResponse" },
247 { QueryResponse
, "QueryResponse" },
251 static const value_string tlv_type_vals
[] = {
252 { REDIRECT_TLV
, "REDIRECT-TLV" },
253 { ASResult_TLV
, "ASResult-TLV" },
254 { ASTreason_TLV
, "ASTreason-TLV" },
255 { LFBselect_TLV
, "LFBselect-TLV" },
256 { PATH_DATA_TLV
, "PATH DATA-TLV" },
257 { KEYINFO_TLV
, "KEYINFO-TLV" },
258 { FULLDATA_TLV
, "FULLDATA-TLV" },
259 { SPARSEDATA_TLV
, "SPARSEDATA-TLV" },
260 { RESULT_TLV
, "RESULT-TLV" },
261 { METADATA_TLV
, "METADATA-TLV" },
262 { REDIRECTDATA_TLV
, "REDIRECTDATA-TLV" },
266 static const value_string operation_type_vals
[] = {
267 { Reserved
, "Reserved" },
269 { SET_PROP
, "SET-PROP" },
270 { SET_RESPONSE
, "SET-RESPONSE" },
271 { SET_PROP_RESPONSE
, "SET-PROP-RESPONSE" },
273 { DEL_RESPONSE
, "DEL-RESPONSE" },
275 { GET_PROP
, "GET-PROP" },
276 { GET_RESPONSE
, "GET-RESPONSE" },
277 { GET_PROP_RESPONSE
, "GET-PROP-RESPONSE" },
278 { REPORT
, "REPORT" },
279 { COMMIT
, "COMMIT" },
280 { COMMIT_RESPONSE
, "COMMIT-RESPONSE" },
281 { TRCOMP
, "TRCOMP" },
286 dissect_path_data_tlv(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
288 proto_item
*ti
, *flag_item
;
289 unsigned length_TLV
, IDcount
, i
;
291 proto_tree
*tlv_tree
, *path_data_tree
, *flag_tree
;
293 while (tvb_reported_length_remaining(tvb
, offset
) >= TLV_TL_LENGTH
)
295 tlv_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, TLV_TL_LENGTH
, ett_forces_path_data_tlv
, &ti
, "TLV");
297 type
= tvb_get_ntohs(tvb
, offset
);
298 proto_tree_add_item(tlv_tree
, hf_forces_lfbselect_tlv_type_operation_path_type
,
299 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
300 length_TLV
= tvb_get_ntohs(tvb
, offset
+2);
301 proto_tree_add_item(tlv_tree
, hf_forces_lfbselect_tlv_type_operation_path_length
,
302 tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
303 if (length_TLV
< TLV_TL_LENGTH
)
305 expert_add_info_format(pinfo
, ti
, &ei_forces_lfbselect_tlv_type_operation_path_length
, "Bogus TLV length: %u", length_TLV
);
308 proto_item_set_len(ti
, length_TLV
);
310 if (type
== PATH_DATA_TLV
)
312 path_data_tree
= proto_tree_add_subtree(tree
, tvb
, offset
+TLV_TL_LENGTH
, length_TLV
-TLV_TL_LENGTH
,
313 ett_forces_path_data_tlv
, NULL
, "Path Data TLV");
315 flag
= tvb_get_ntohs(tvb
, offset
+TLV_TL_LENGTH
);
316 flag_item
= proto_tree_add_item(path_data_tree
, hf_forces_lfbselect_tlv_type_operation_path_flags
,
317 tvb
, offset
+TLV_TL_LENGTH
, 2, ENC_BIG_ENDIAN
);
318 flag_tree
= proto_item_add_subtree(flag_item
, ett_forces_path_data_tlv_flags
);
319 proto_tree_add_item(flag_tree
, hf_forces_lfbselect_tlv_type_operation_path_flags_selector
,
320 tvb
, offset
+TLV_TL_LENGTH
, 2, ENC_BIG_ENDIAN
);
321 proto_tree_add_item(flag_tree
, hf_forces_lfbselect_tlv_type_operation_path_flags_reserved
,
322 tvb
, offset
+TLV_TL_LENGTH
, 2, ENC_BIG_ENDIAN
);
324 IDcount
= tvb_get_ntohs(tvb
, offset
+ TLV_TL_LENGTH
+ 2);
325 proto_tree_add_item(path_data_tree
, hf_forces_lfbselect_tlv_type_operation_path_IDcount
,
326 tvb
, offset
+TLV_TL_LENGTH
+2, 2, ENC_BIG_ENDIAN
);
328 for (i
= 0; i
< IDcount
; i
++)
329 proto_tree_add_item(path_data_tree
, hf_forces_lfbselect_tlv_type_operation_path_IDs
,
330 tvb
, offset
+TLV_TL_LENGTH
+2+(i
*4), 4, ENC_BIG_ENDIAN
);
335 proto_tree_add_item(tree
, hf_forces_lfbselect_tlv_type_operation_path_data
,
336 tvb
, offset
+TLV_TL_LENGTH
, length_TLV
-TLV_TL_LENGTH
, ENC_NA
);
339 if ((flag
& FLAG_SELECTOR
) == 0)
342 offset
+= length_TLV
;
347 dissect_operation_tlv(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, int length_count
)
350 proto_tree
*oper_tree
;
351 unsigned type
, length
;
353 while (tvb_reported_length_remaining(tvb
, offset
) >= TLV_TL_LENGTH
)
355 oper_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, length_count
,
356 ett_forces_lfbselect_tlv_type_operation
, &ti
, "Operation TLV");
358 type
= tvb_get_ntohs(tvb
,offset
);
359 ti
= proto_tree_add_item(oper_tree
, hf_forces_lfbselect_tlv_type_operation_type
,
360 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
361 if (try_val_to_str(type
, operation_type_vals
) == NULL
)
362 expert_add_info_format(pinfo
, ti
, &ei_forces_lfbselect_tlv_type_operation_type
,
363 "Bogus: ForCES Operation TLV (Type:0x%04x) is not supported", type
);
365 proto_tree_add_item_ret_uint(oper_tree
, hf_forces_lfbselect_tlv_type_operation_length
,
366 tvb
, offset
+2, 2, ENC_BIG_ENDIAN
, &length
);
368 dissect_path_data_tlv(tvb
, pinfo
, oper_tree
, offset
+TLV_TL_LENGTH
);
376 dissect_lfbselecttlv(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, int length_count
)
380 proto_tree_add_item(tree
, hf_forces_lfbselect_tlv_type_lfb_classid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
381 proto_tree_add_item(tree
, hf_forces_lfbselect_tlv_type_lfb_instanceid
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
384 while ((tvb_reported_length_remaining(tvb
, offset
) > TLV_TL_LENGTH
) && (length_count
> 12))
386 tlv_length
= tvb_get_ntohs(tvb
, offset
+2);
387 dissect_operation_tlv(tvb
, pinfo
, tree
, offset
, tlv_length
);
390 offset
+= tlv_length
;
395 dissect_redirecttlv(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
397 proto_tree
*meta_data_tree
, *meta_data_ilv_tree
, *redirect_data_tree
;
399 int length_meta
, length_ilv
, length_redirect
;
401 address src_addr
, src_net_addr
;
402 address dst_addr
, dst_net_addr
;
404 copy_address_shallow(&src_addr
, &pinfo
->src
);
405 copy_address_shallow(&src_net_addr
, &pinfo
->net_src
);
406 copy_address_shallow(&dst_addr
, &pinfo
->dst
);
407 copy_address_shallow(&dst_net_addr
, &pinfo
->net_dst
);
409 meta_data_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, TLV_TL_LENGTH
,
410 ett_forces_redirect_tlv_meta_data_tlv
, &ti
, "Meta Data TLV");
411 proto_tree_add_item(meta_data_tree
, hf_forces_redirect_tlv_meta_data_tlv_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
413 length_meta
= tvb_get_ntohs(tvb
, offset
+2);
414 proto_tree_add_uint(meta_data_tree
, hf_forces_redirect_tlv_meta_data_tlv_length
, tvb
, offset
+2, 2, length_meta
);
415 proto_item_set_len(ti
, length_meta
);
417 start_offset
= offset
;
418 while ((tvb_reported_length_remaining(tvb
, offset
) >= 8) && (start_offset
+length_meta
> offset
))
420 meta_data_ilv_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, TLV_TL_LENGTH
,
421 ett_forces_redirect_tlv_meta_data_tlv_meta_data_ilv
, &ti
, "Meta Data ILV");
423 proto_tree_add_item(meta_data_ilv_tree
, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_id
,
424 tvb
, offset
+8, 4, ENC_BIG_ENDIAN
);
425 length_ilv
= tvb_get_ntohl(tvb
, offset
+12);
426 proto_tree_add_uint(meta_data_ilv_tree
, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_length
,
427 tvb
, offset
+12, 4, length_ilv
);
429 if (length_ilv
> 0) {
430 proto_tree_add_item(meta_data_ilv_tree
, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv
,
431 tvb
, offset
, length_ilv
, ENC_NA
);
433 if (offset
+ length_ilv
> offset
) {
434 offset
+= length_ilv
;
438 proto_item_set_len(ti
, length_ilv
+ 8);
441 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
443 redirect_data_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, TLV_TL_LENGTH
,
444 ett_forces_redirect_tlv_redirect_data_tlv
, &ti
, "Redirect Data TLV");
446 proto_tree_add_item(redirect_data_tree
, hf_forces_redirect_tlv_redirect_data_tlv_type
,
447 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
448 length_redirect
= tvb_get_ntohs(tvb
, offset
+2);
449 proto_tree_add_uint(redirect_data_tree
, hf_forces_redirect_tlv_redirect_data_tlv_length
,
450 tvb
, offset
+2, 2, length_redirect
);
452 if (tvb_reported_length_remaining(tvb
, offset
) < length_redirect
)
454 expert_add_info_format(pinfo
, ti
, &ei_forces_redirect_tlv_redirect_data_tlv_length
, "Bogus: Redirect Data TLV length (%u bytes) is wrong", length_redirect
);
456 else if (length_redirect
< TLV_TL_LENGTH
+ MIN_IP_HEADER_LENGTH
)
458 expert_add_info_format(pinfo
, ti
, &ei_forces_redirect_tlv_redirect_data_tlv_length
, "Bogus: Redirect Data TLV length (%u bytes) not big enough for IP layer", length_redirect
);
464 next_tvb
= tvb_new_subset_length(tvb
, offset
+4, length_redirect
-TLV_TL_LENGTH
);
465 call_dissector(ip_handle
, next_tvb
, pinfo
, redirect_data_tree
);
467 /* Restore IP info */
468 copy_address_shallow(&pinfo
->src
, &src_addr
);
469 copy_address_shallow(&pinfo
->net_src
, &src_net_addr
);
470 copy_address_shallow(&pinfo
->dst
, &dst_addr
);
471 copy_address_shallow(&pinfo
->net_dst
, &dst_net_addr
);
477 dissect_forces(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint32_t offset
)
479 /* Set up structures needed to add the protocol subtree and manage it */
480 proto_item
*ti
, *tlv_item
;
481 proto_tree
*forces_tree
, *forces_flags_tree
;
482 proto_tree
*forces_main_header_tree
, *forces_tlv_tree
, *tlv_tree
;
485 uint8_t message_type
;
488 /* Make entries in Protocol column and Info column on summary display */
489 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ForCES");
490 col_clear(pinfo
->cinfo
, COL_INFO
);
492 ti
= proto_tree_add_item(tree
, proto_forces
, tvb
, 0, -1, ENC_NA
);
493 forces_tree
= proto_item_add_subtree(ti
, ett_forces
);
495 forces_main_header_tree
= proto_tree_add_subtree(forces_tree
, tvb
, 0, ForCES_HEADER_LENGTH
,
496 ett_forces_main_header
, NULL
, "Common Header");
498 proto_tree_add_item(forces_main_header_tree
, hf_forces_version
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
499 proto_tree_add_item(forces_main_header_tree
, hf_forces_rsvd
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
501 message_type
= tvb_get_uint8(tvb
, offset
+1);
502 proto_tree_add_item( forces_main_header_tree
, hf_forces_messagetype
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
504 length_count
= tvb_get_ntohs(tvb
, offset
+2) * 4; /*multiply 4 DWORD*/
505 ti
= proto_tree_add_uint_format( forces_main_header_tree
, hf_forces_length
,
506 tvb
, offset
+2, 2, length_count
, "Length: %u Bytes", length_count
);
507 if (length_count
!= tvb_reported_length_remaining(tvb
, offset
))
508 expert_add_info_format(pinfo
, ti
, &ei_forces_length
, "Bogus: ForCES Header length (%u bytes) is wrong),should be (%u bytes)",
509 length_count
, tvb_reported_length_remaining(tvb
, offset
));
510 if (length_count
< 24)
511 expert_add_info_format(pinfo
, ti
, &ei_forces_length
, "Bogus: ForCES Header length (%u bytes) is less than 24bytes)", length_count
);
513 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Message Type: %s, Total Length: %u Bytes",
514 val_to_str(message_type
, message_type_vals
, "Unknown messagetype 0x%x"), length_count
);
516 proto_tree_add_item( forces_main_header_tree
, hf_forces_sid
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
517 proto_tree_add_item( forces_main_header_tree
, hf_forces_did
, tvb
, offset
+8, 4, ENC_BIG_ENDIAN
);
518 proto_tree_add_item( forces_main_header_tree
, hf_forces_correlator
, tvb
, offset
+12, 8, ENC_BIG_ENDIAN
);
521 ti
= proto_tree_add_item(forces_main_header_tree
, hf_forces_flags
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
522 forces_flags_tree
= proto_item_add_subtree(ti
, ett_forces_flags
);
524 proto_tree_add_item(forces_flags_tree
, hf_forces_flags_ack
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
525 proto_tree_add_item(forces_flags_tree
, hf_forces_flags_at
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
526 proto_tree_add_item(forces_flags_tree
, hf_forces_flags_em
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
527 proto_tree_add_item(forces_flags_tree
, hf_forces_flags_pri
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
528 proto_tree_add_item(forces_flags_tree
, hf_forces_flags_reserved
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
529 proto_tree_add_item(forces_flags_tree
, hf_forces_flags_rsrvd
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
530 proto_tree_add_item(forces_flags_tree
, hf_forces_flags_tp
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
533 while (tvb_reported_length_remaining(tvb
, offset
) >= TLV_TL_LENGTH
)
535 forces_tlv_tree
= proto_tree_add_subtree(forces_tree
, tvb
, offset
, TLV_TL_LENGTH
, ett_forces_tlv
, &ti
, "TLV");
537 tlv_type
= tvb_get_ntohs(tvb
, offset
);
538 tlv_item
= proto_tree_add_item(forces_tlv_tree
, hf_forces_tlv_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
539 length_count
= tvb_get_ntohs(tvb
, offset
+2) * 4;
540 proto_item_set_len(ti
, length_count
);
541 ti
= proto_tree_add_uint(forces_tlv_tree
, hf_forces_tlv_length
,
542 tvb
, offset
+2, 2, length_count
);
543 if (tvb_reported_length_remaining(tvb
, offset
) < length_count
)
544 expert_add_info_format(pinfo
, ti
, &ei_forces_tlv_length
, "Bogus: Main TLV length (%u bytes) is wrong", length_count
);
546 if (length_count
< TLV_TL_LENGTH
)
548 expert_add_info_format(pinfo
, ti
, &ei_forces_tlv_length
, "Bogus TLV length: %u", length_count
);
552 offset
+= TLV_TL_LENGTH
;
553 length_count
-= TLV_TL_LENGTH
;
558 tlv_tree
= proto_tree_add_subtree(forces_tlv_tree
, tvb
, offset
, length_count
,
559 ett_forces_lfbselect_tlv_type
, NULL
, "LFB select TLV");
560 dissect_lfbselecttlv(tvb
, pinfo
, tlv_tree
, offset
, length_count
);
564 tlv_tree
= proto_tree_add_subtree(forces_tlv_tree
, tvb
, offset
, length_count
,
565 ett_forces_redirect_tlv_type
, NULL
, "Redirect TLV");
566 dissect_redirecttlv(tvb
, pinfo
, tlv_tree
, offset
);
570 tlv_tree
= proto_tree_add_subtree(forces_tlv_tree
, tvb
, offset
, length_count
,
571 ett_forces_asresult_tlv
, NULL
, "ASResult TLV");
572 proto_tree_add_item(tlv_tree
, hf_forces_asresult_association_setup_result
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
576 tlv_tree
= proto_tree_add_subtree(forces_tlv_tree
, tvb
, offset
, length_count
,
577 ett_forces_astreason_tlv
, NULL
, "ASTreason TLV");
578 proto_tree_add_item(tlv_tree
, hf_forces_astreason_tlv_teardown_reason
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
582 expert_add_info(pinfo
, tlv_item
, &ei_forces_tlv_type
);
583 tlv_tree
= proto_tree_add_subtree(forces_tlv_tree
, tvb
, offset
, length_count
,
584 ett_forces_unknown_tlv
, NULL
, "Unknown TLV");
585 proto_tree_add_item(tlv_tree
, hf_forces_unknown_tlv
, tvb
, offset
, length_count
, ENC_NA
);
589 offset
+= length_count
;
593 /* Code to actually dissect the TCP packets */
595 dissect_forces_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
597 dissect_forces(tvb
, pinfo
, tree
, TCP_UDP_TML_FOCES_MESSAGE_OFFSET_TCP
);
598 return tvb_captured_length(tvb
);
601 /* Code to actually dissect the ForCES protocol layer packets,like UDP,SCTP and others */
603 dissect_forces_not_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
605 dissect_forces(tvb
, pinfo
, tree
, 0);
606 return tvb_captured_length(tvb
);
610 proto_register_forces(void)
612 module_t
*forces_module
;
613 expert_module_t
* expert_forces
;
615 /* Setup list of header fields See Section 1.6.1 for details*/
616 static hf_register_info hf
[] = {
617 { &hf_forces_version
,
618 { "Version", "forces.flags.version",
619 FT_UINT8
, BASE_DEC
, NULL
, 0xF0, NULL
, HFILL
}
622 { "Rsvd", "forces.flags.rsvd",
623 FT_UINT8
, BASE_DEC
, NULL
, 0x0F, NULL
, HFILL
}
625 { &hf_forces_messagetype
,
626 { "Message Type", "forces.messagetype",
627 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
630 { "Header Length", "forces.length",
631 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
634 { "Source ID", "forces.sid",
635 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
638 { "Destination ID", "forces.did",
639 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
641 { &hf_forces_correlator
,
642 { "Correlator", "forces.correlator",
643 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
645 { &hf_forces_tlv_type
,
646 { "Type", "forces.tlv.type",
647 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
649 { &hf_forces_tlv_length
,
650 { "Length", "forces.tlv.length",
651 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}
655 { "Flags", "forces.Flags",
656 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
658 { &hf_forces_flags_ack
,
659 { "ACK indicator", "forces.flags.ack",
660 FT_UINT32
, BASE_DEC
, VALS(main_header_flags_ack_vals
), 0xC0000000, NULL
, HFILL
}
662 { &hf_forces_flags_pri
,
663 { "Priority", "forces.flags.pri",
664 FT_UINT32
, BASE_DEC
, NULL
, 0x38000000, NULL
, HFILL
}
666 { &hf_forces_flags_rsrvd
,
667 { "Rsrvd", "forces.flags.rsrvd",
668 FT_UINT32
, BASE_DEC
,NULL
, 0x07000000, NULL
, HFILL
}
670 { &hf_forces_flags_em
,
671 { "Execution mode", "forces.flags.em",
672 FT_UINT32
, BASE_DEC
, VALS(main_header_flags_em_vals
), 0x00C00000, NULL
, HFILL
}
674 { &hf_forces_flags_at
,
675 { "Atomic Transaction", "forces.flags.at",
676 FT_UINT32
, BASE_DEC
, VALS(main_header_flags_at_vals
), 0x00200000, NULL
, HFILL
}
678 { &hf_forces_flags_tp
,
679 { "Transaction phase", "forces.flags.tp",
680 FT_UINT32
, BASE_DEC
, VALS(main_header_flags_tp_vals
), 0x00180000, NULL
, HFILL
}
682 { &hf_forces_flags_reserved
,
683 { "Reserved", "forces.flags.reserved",
684 FT_UINT32
, BASE_DEC
,NULL
, 0x0007ffff, NULL
, HFILL
}
687 { &hf_forces_lfbselect_tlv_type_lfb_classid
,
688 { "Class ID", "forces.lfbselect.tlv.type.lfb.classid",
689 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
691 { &hf_forces_lfbselect_tlv_type_lfb_instanceid
,
692 { "Instance ID", "forces.fbselect.tlv.type.lfb.instanceid",
693 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
696 { &hf_forces_lfbselect_tlv_type_operation_type
,
697 { "Type", "forces.lfbselect.tlv.type.operation.type",
698 FT_UINT16
, BASE_DEC
, VALS(operation_type_vals
), 0x0, NULL
, HFILL
}
700 { &hf_forces_lfbselect_tlv_type_operation_length
,
701 { "Length", "forces.lfbselect.tlv.type.operation.length",
702 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}
704 { &hf_forces_lfbselect_tlv_type_operation_path_type
,
705 { "Type", "forces.lfbselect.tlv.type.operation.path.type",
706 FT_UINT16
, BASE_DEC
, VALS(tlv_type_vals
), 0x0, NULL
, HFILL
}
708 { &hf_forces_lfbselect_tlv_type_operation_path_length
,
709 { "Length", "forces.lfbselect.tlv.type.operation.path.length",
710 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
712 { &hf_forces_lfbselect_tlv_type_operation_path_data
,
713 { "Data", "forces.lfbselect.tlv.type.operation.path.data",
714 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
716 { &hf_forces_lfbselect_tlv_type_operation_path_flags
,
717 {"Path Data Flags", "forces.lfbselect.tlv.type.operation.path.data.flags",
718 FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
720 { &hf_forces_lfbselect_tlv_type_operation_path_flags_selector
,
721 {"Selector", "forces.lfbselect.tlv.type.operation.path.data.flags.selector",
722 FT_UINT16
, BASE_HEX
, NULL
, 0x80, NULL
, HFILL
}
724 { &hf_forces_lfbselect_tlv_type_operation_path_flags_reserved
,
725 {"Reserved", "forces.lfbselect.tlv.type.operation.path.data.flags.reserved",
726 FT_UINT16
, BASE_HEX
, NULL
, 0x7F, NULL
, HFILL
}
728 { &hf_forces_lfbselect_tlv_type_operation_path_IDcount
,
729 { "Path Data IDcount", "forces.lfbselect.tlv.type.operation.path.data.IDcount",
730 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
732 { &hf_forces_lfbselect_tlv_type_operation_path_IDs
,
733 { "Path Data IDs", "forces.lfbselect.tlv.type.operation.path.data.IDs",
734 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
737 {&hf_forces_redirect_tlv_meta_data_tlv_type
,
738 { "Type", "forces.redirect.tlv.meta.data.tlv.type",
739 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
741 { &hf_forces_redirect_tlv_meta_data_tlv_length
,
742 { "Length", "forces.redirect.tlv.meta.data.tlv.length",
743 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}
745 { &hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv
,
746 { "Meta Data ILV", "forces.redirect.tlv.meta.data.tlv.meta.data.ilv",
747 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
749 { &hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_id
,
750 { "ID", "forces.redirect.tlv.meta.data.tlv.meta.data.ilv.id",
751 FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}
753 { &hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_length
,
754 { "Length", "forces.redirect.tlv.meta.data.tlv.meta.data.ilv.length",
755 FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}
757 { &hf_forces_redirect_tlv_redirect_data_tlv_type
,
758 { "Type", "forces.redirect.tlv.redirect.data.tlv.type",
759 FT_UINT16
, BASE_DEC
, VALS(tlv_type_vals
), 0x0, NULL
, HFILL
}
761 { &hf_forces_redirect_tlv_redirect_data_tlv_length
,
762 { "Length", "forces.redirect.tlv.redirect.data.tlv.length",
763 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}
765 { &hf_forces_asresult_association_setup_result
,
766 { "Association Setup Result", "forces.teardown.reason",
767 FT_UINT32
, BASE_DEC
, VALS(association_setup_result_at_vals
), 0x0, NULL
, HFILL
}
769 { &hf_forces_astreason_tlv_teardown_reason
,
770 { "AStreason TLV TearDown Reason", "forces.astreason.tlv.teardown.reason",
771 FT_UINT32
, BASE_DEC
, VALS(teardown_reason_at_vals
), 0x0, NULL
, HFILL
}
773 { &hf_forces_unknown_tlv
,
774 { "Data", "forces.unknown.tlv",
775 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
779 /* Setup protocol subtree array */
780 static int *ett
[] = {
782 &ett_forces_main_header
,
785 &ett_forces_lfbselect_tlv_type
,
786 &ett_forces_lfbselect_tlv_type_operation
,
787 &ett_forces_lfbselect_tlv_type_operation_path
,
788 &ett_forces_lfbselect_tlv_type_operation_path_data
,
789 &ett_forces_lfbselect_tlv_type_operation_path_data_path
,
790 &ett_forces_lfbselect_tlv_type_operation_path_selector
,
791 &ett_forces_path_data_tlv
,
792 &ett_forces_path_data_tlv_flags
,
793 &ett_forces_redirect_tlv_type
,
794 &ett_forces_redirect_tlv_meta_data_tlv
,
795 &ett_forces_redirect_tlv_redirect_data_tlv
,
796 &ett_forces_redirect_tlv_meta_data_tlv_meta_data_ilv
,
797 &ett_forces_asresult_tlv
,
798 &ett_forces_astreason_tlv
,
799 &ett_forces_unknown_tlv
802 static ei_register_info ei
[] = {
803 { &ei_forces_length
, { "forces.length.bad", PI_PROTOCOL
, PI_WARN
, "ForCES Header length is wrong", EXPFILL
}},
804 { &ei_forces_tlv_type
, { "forces.tlv.type.unknown", PI_PROTOCOL
, PI_WARN
, "Bogus: The Main_TLV type is unknown", EXPFILL
}},
805 { &ei_forces_tlv_length
, { "forces.tlv.length.bad", PI_PROTOCOL
, PI_WARN
, "Bogus TLV length", EXPFILL
}},
806 { &ei_forces_lfbselect_tlv_type_operation_path_length
, { "forces.lfbselect.tlv.type.operation.path.length.bad", PI_PROTOCOL
, PI_WARN
, "Bogus TLV length", EXPFILL
}},
807 { &ei_forces_lfbselect_tlv_type_operation_type
, { "forces.lfbselect.tlv.type.operation.type.unsupported", PI_PROTOCOL
, PI_WARN
, "ForCES Operation TLV is not supported", EXPFILL
}},
808 { &ei_forces_redirect_tlv_redirect_data_tlv_length
, { "forces.redirect.tlv.redirect.data.tlv.length.bad", PI_PROTOCOL
, PI_WARN
, "Redirect Data TLV length is wrong", EXPFILL
}},
811 /* Register the protocol name and description */
812 proto_forces
= proto_register_protocol("Forwarding and Control Element Separation Protocol", "ForCES", "forces");
814 /* Required function calls to register the header fields and subtrees used */
815 proto_register_field_array(proto_forces
, hf
, array_length(hf
));
816 proto_register_subtree_array(ett
, array_length(ett
));
817 expert_forces
= expert_register_protocol(proto_forces
);
818 expert_register_field_array(expert_forces
, ei
, array_length(ei
));
820 forces_handle_tcp
= register_dissector("forces.tcp", dissect_forces_tcp
, proto_forces
);
821 forces_handle
= register_dissector("forces", dissect_forces_not_tcp
, proto_forces
);
823 forces_module
= prefs_register_protocol(proto_forces
,proto_reg_handoff_forces
);
825 prefs_register_uint_preference(forces_module
, "sctp_high_prio_port",
826 "SCTP High Priority channel port",
827 "Decode packets on this sctp port as ForCES",
828 10, &forces_alternate_sctp_high_prio_channel_port
);
830 prefs_register_uint_preference(forces_module
, "sctp_med_prio_port",
831 "SCTP Medium Priority channel port",
832 "Decode packets on this sctp port as ForCES",
833 10, &forces_alternate_sctp_med_prio_channel_port
);
835 prefs_register_uint_preference(forces_module
, "sctp_low_prio_port",
836 "SCTP Low Priority channel port",
837 "Decode packets on this sctp port as ForCES",
838 10, &forces_alternate_sctp_low_prio_channel_port
);
842 proto_reg_handoff_forces(void)
844 static bool inited
= false;
846 static unsigned alternate_sctp_high_prio_channel_port
= 0; /* 6700 */
847 static unsigned alternate_sctp_med_prio_channel_port
= 0;
848 static unsigned alternate_sctp_low_prio_channel_port
= 0;
851 ip_handle
= find_dissector_add_dependency("ip", proto_forces
);
852 /* Register TCP port for dissection */
853 dissector_add_for_decode_as_with_preference("tcp.port", forces_handle_tcp
);
854 /* Register UDP port for dissection */
855 dissector_add_for_decode_as_with_preference("udp.port", forces_handle
);
860 /* Register SCTP port for high priority dissection */
861 if ((alternate_sctp_high_prio_channel_port
!= 0) &&
862 (alternate_sctp_high_prio_channel_port
!= forces_alternate_sctp_high_prio_channel_port
))
863 dissector_delete_uint("sctp.port", alternate_sctp_high_prio_channel_port
, forces_handle
);
864 if ((forces_alternate_sctp_high_prio_channel_port
!= 0) &&
865 (alternate_sctp_high_prio_channel_port
!= forces_alternate_sctp_high_prio_channel_port
))
866 dissector_add_uint("sctp.port", forces_alternate_sctp_high_prio_channel_port
, forces_handle
);
867 alternate_sctp_high_prio_channel_port
= forces_alternate_sctp_high_prio_channel_port
;
869 /* Register SCTP port for medium priority dissection */
870 if ((alternate_sctp_med_prio_channel_port
!= 0) &&
871 (alternate_sctp_med_prio_channel_port
!= forces_alternate_sctp_med_prio_channel_port
))
872 dissector_delete_uint("sctp.port", alternate_sctp_med_prio_channel_port
, forces_handle
);
873 if ((forces_alternate_sctp_med_prio_channel_port
!= 0) &&
874 (alternate_sctp_med_prio_channel_port
!= forces_alternate_sctp_med_prio_channel_port
))
875 dissector_add_uint("sctp.port", forces_alternate_sctp_med_prio_channel_port
, forces_handle
);
876 alternate_sctp_med_prio_channel_port
= forces_alternate_sctp_med_prio_channel_port
;
878 /* Register SCTP port for low priority dissection */
879 if ((alternate_sctp_low_prio_channel_port
!= 0) &&
880 (alternate_sctp_low_prio_channel_port
!= forces_alternate_sctp_low_prio_channel_port
))
881 dissector_delete_uint("sctp.port", alternate_sctp_low_prio_channel_port
, forces_handle
);
882 if ((forces_alternate_sctp_low_prio_channel_port
!= 0) &&
883 (alternate_sctp_low_prio_channel_port
!= forces_alternate_sctp_low_prio_channel_port
))
884 dissector_add_uint("sctp.port", forces_alternate_sctp_low_prio_channel_port
, forces_handle
);
885 alternate_sctp_low_prio_channel_port
= forces_alternate_sctp_low_prio_channel_port
;
889 * Editor modelines - https://www.wireshark.org/tools/modelines.html
894 * indent-tabs-mode: nil
897 * vi: set shiftwidth=4 tabstop=8 expandtab:
898 * :indentSize=4:tabSize=8:noTabs=true: