MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-forces.c
blob7c1d447bd74c428ca82e83488b72f817822a07ba
1 /* packet-forces.c
2 * RFC 5810
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 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <glib.h>
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
33 #include <epan/expert.h>
35 static dissector_handle_t ip_handle;
37 /* Initialize the ForCES protocol and registered fields */
38 static int proto_forces = -1;
40 /*Main header*/
41 static int hf_forces_version = -1;
42 static int hf_forces_rsvd = -1;
43 static int hf_forces_messagetype = -1;
44 static int hf_forces_sid = -1;
45 static int hf_forces_did = -1;
46 static int hf_forces_correlator = -1;
47 static int hf_forces_length = -1;
48 /*Flags*/
49 static int hf_forces_flags= -1;
50 static int hf_forces_flags_ack= -1;
51 static int hf_forces_flags_pri= -1;
52 static int hf_forces_flags_rsrvd= -1;
53 static int hf_forces_flags_em= -1;
54 static int hf_forces_flags_at= -1;
55 static int hf_forces_flags_tp= -1;
56 static int hf_forces_flags_reserved = -1;
58 static int hf_forces_tlv_type = -1;
59 static int hf_forces_tlv_length = -1;
61 /*Initiation of LFBSelect TLV*/
62 static int hf_forces_lfbselect_tlv_type_lfb_classid = -1;
63 static int hf_forces_lfbselect_tlv_type_lfb_instanceid = -1;
65 /*Initiation of Operation TLV*/
66 static int hf_forces_lfbselect_tlv_type_operation_type = -1;
67 static int hf_forces_lfbselect_tlv_type_operation_length = -1;
68 static int hf_forces_lfbselect_tlv_type_operation_path_type = -1;
69 static int hf_forces_lfbselect_tlv_type_operation_path_length = -1;
70 static int hf_forces_lfbselect_tlv_type_operation_path_flags = -1;
71 static int hf_forces_lfbselect_tlv_type_operation_path_flags_selector = -1;
72 static int hf_forces_lfbselect_tlv_type_operation_path_flags_reserved = -1;
73 static int hf_forces_lfbselect_tlv_type_operation_path_IDcount = -1;
74 static int hf_forces_lfbselect_tlv_type_operation_path_IDs = -1;
75 static int hf_forces_lfbselect_tlv_type_operation_path_data = -1;
77 /*Initiation of Redirect TLV*/
78 static int hf_forces_redirect_tlv_meta_data_tlv_type = -1;
79 static int hf_forces_redirect_tlv_meta_data_tlv_length = -1;
80 static int hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv = -1;
81 static int hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_id = -1;
82 static int hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_length = -1;
83 static int hf_forces_redirect_tlv_redirect_data_tlv_type = -1;
84 static int hf_forces_redirect_tlv_redirect_data_tlv_length = -1;
86 /*Initiation of ASResult TLV*/
87 static int hf_forces_asresult_association_setup_result = -1;
89 /*Initiation of ASTreason TLV*/
90 static int hf_forces_astreason_tlv_teardown_reason = -1;
92 /*Main TLV may be unknown*/
93 static int hf_forces_unknown_tlv = -1;
95 /*Message Types */
96 #define AssociationSetup 0x01
97 #define AssociationTeardown 0x02
98 #define Config 0x03
99 #define Query 0x04
100 #define EventNotification 0x05
101 #define PacketRedirect 0x06
102 #define Heartbeat 0x0F
103 #define AssociationSetupRepsonse 0x11
104 #define ConfigResponse 0x13
105 #define QueryResponse 0x14
107 /*TLV Types*/
108 #define Reserved 0x0000
109 #define REDIRECT_TLV 0x0001
110 #define ASResult_TLV 0x0010
111 #define ASTreason_TLV 0x0011
112 #define LFBselect_TLV 0x1000
113 #define PATH_DATA_TLV 0x0110
114 #define KEYINFO_TLV 0x0111
115 #define FULLDATA_TLV 0x0112
116 #define SPARSEDATA_TLV 0x0113
117 #define RESULT_TLV 0x0114
118 #define METADATA_TLV 0x0115
119 #define REDIRECTDATA_TLV 0x0116
121 /*Operation Type*/
122 #define Reserved 0x0000
123 #define SET 0x0001
124 #define SET_PROP 0x0002
125 #define SET_RESPONSE 0x0003
126 #define SET_PROP_RESPONSE 0x0004
127 #define DEL 0x0005
128 #define DEL_RESPONSE 0x0006
129 #define GET 0x0007
130 #define GET_PROP 0x0008
131 #define GET_RESPONSE 0x0009
132 #define GET_PROP_RESPONSE 0x000A
133 #define REPORT 0x000B
134 #define COMMIT 0x000C
135 #define COMMIT_RESPONSE 0x000D
136 #define TRCOMP 0x000E
138 #define FLAG_SELECTOR 0x8000
140 #define ForCES_HEADER_LENGTH 24
141 #define TLV_TL_LENGTH 4 /*Type+length*/
142 #define MIN_IP_HEADER_LENGTH 20
144 /*For TCP+UDP TML. There are two bytes added to the ForCES PL message, not strictly combine to the ForCES protocol.
145 For other type TMLs,no need to add these 2 bytes.*/
146 #define TCP_UDP_TML_FOCES_MESSAGE_OFFSET_TCP 2
148 /*TCP+UDP TML*/
149 static guint forces_alternate_tcp_port = 0;
150 static guint forces_alternate_udp_port = 0;
151 /*SCTP TML*/
152 static guint forces_alternate_sctp_high_prio_channel_port = 0;
153 static guint forces_alternate_sctp_med_prio_channel_port = 0;
154 static guint forces_alternate_sctp_low_prio_channel_port = 0;
156 /*Initialize the subtree pointers*/
157 static gint ett_forces = -1;
158 static gint ett_forces_main_header = -1;
159 static gint ett_forces_flags = -1;
160 static gint ett_forces_tlv = -1;
161 static gint ett_forces_lfbselect_tlv_type = -1;
163 /*Operation TLV subtree*/
164 static gint ett_forces_lfbselect_tlv_type_operation = -1;
165 static gint ett_forces_lfbselect_tlv_type_operation_path = -1;
166 static gint ett_forces_lfbselect_tlv_type_operation_path_data = -1;
167 static gint ett_forces_lfbselect_tlv_type_operation_path_data_path = -1;
168 static gint ett_forces_path_data_tlv = -1;
169 static gint ett_forces_path_data_tlv_flags = -1;
171 /*Selector subtree*/
172 static gint ett_forces_lfbselect_tlv_type_operation_path_selector = -1;
174 /*Redirect TLV subtree*/
175 static gint ett_forces_redirect_tlv_type = -1;
176 static gint ett_forces_redirect_tlv_meta_data_tlv = -1;
177 static gint ett_forces_redirect_tlv_meta_data_tlv_meta_data_ilv = -1;
178 static gint ett_forces_redirect_tlv_redirect_data_tlv = -1;
180 /*ASResult TLV subtree*/
181 static gint ett_forces_asresult_tlv = -1;
183 /*ASReason subtree*/
184 static gint ett_forces_astreason_tlv = -1;
186 /*Main_TLV unknown subtree*/
187 static gint ett_forces_unknown_tlv = -1;
190 static expert_field ei_forces_length = EI_INIT;
191 static expert_field ei_forces_tlv_type = EI_INIT;
192 static expert_field ei_forces_tlv_length = EI_INIT;
193 static expert_field ei_forces_lfbselect_tlv_type_operation_path_length = EI_INIT;
194 static expert_field ei_forces_lfbselect_tlv_type_operation_type = EI_INIT;
195 static expert_field ei_forces_redirect_tlv_redirect_data_tlv_length = EI_INIT;
197 /*ACK values and the strings to be displayed*/
198 static const value_string main_header_flags_ack_vals[] = {
199 { 0x0, "NoACK" },
200 { 0x1, "SuccessACK" },
201 { 0x2, "FailureACK" },
202 { 0x3, "AlwaysACK" },
203 { 0, NULL}
206 /*Execution mode(EM) values and the strings to be displayed*/
207 static const value_string main_header_flags_em_vals[] = {
208 { 0x0, "Reserved" },
209 { 0x1, "Execute-all-or-none" },
210 { 0x2, "Execute-until-failure" },
211 { 0x3, "Continue-execute-on-failure" },
212 { 0, NULL}
215 /*Transaction Phase values and the strings to be displayed*/
216 static const value_string main_header_flags_tp_vals[] = {
217 { 0x0, "SOT (Start of Transaction)" },
218 { 0x1, "MOT (Middle of Transaction)" },
219 { 0x2, "EOT (End of Transaction)" },
220 { 0x3, "ABT (Abort)" },
221 { 0, NULL}
224 /*Atomic Transaction(AT) values and the strings to be displayed*/
225 static const value_string main_header_flags_at_vals[] = {
226 { 0x0, "Stand-alone Message"},
227 { 0x1, "2PC Transaction Message"},
228 { 0, NULL}
231 /*Association Setup Result*/
232 static const value_string association_setup_result_at_vals[] = {
233 { 0x0, "success"},
234 { 0x1, "FE ID invalid"},
235 { 0x2, "permission denied"},
236 { 0, NULL},
239 /*Teardown Reason*/
240 static const value_string teardown_reason_at_vals[] = {
241 { 0x0, "normal-teardown by administrator"},
242 { 0x1, "error - loss of heartbeats"},
243 { 0x2, "error - out of bandwidth"},
244 { 0x3, "error - out of memory"},
245 { 0x4, "error - application crash"},
246 { 0x255, "error - other or unspecified"},
247 { 0, NULL},
250 static const value_string message_type_vals[] = {
251 { AssociationSetup, "AssociationSetup" },
252 { AssociationTeardown, "AssociationTeardown" },
253 { Config, "Config" },
254 { Query, "Query" },
255 { EventNotification, "EventNotification" },
256 { PacketRedirect, "PacketRedirect" },
257 { Heartbeat, "Heartbeat" },
258 { AssociationSetupRepsonse, "AssociationSetupRepsonse" },
259 { ConfigResponse, "ConfigResponse" },
260 { QueryResponse, "QueryResponse" },
261 { 0, NULL},
264 static const value_string tlv_type_vals[] = {
265 { REDIRECT_TLV, "REDIRECT-TLV" },
266 { ASResult_TLV, "ASResult-TLV" },
267 { ASTreason_TLV, "ASTreason-TLV" },
268 { LFBselect_TLV, "LFBselect-TLV" },
269 { PATH_DATA_TLV, "PATH DATA-TLV" },
270 { KEYINFO_TLV, "KEYINFO-TLV" },
271 { FULLDATA_TLV, "FULLDATA-TLV" },
272 { SPARSEDATA_TLV, "SPARSEDATA-TLV" },
273 { RESULT_TLV, "RESULT-TLV" },
274 { METADATA_TLV, "METADATA-TLV" },
275 { REDIRECTDATA_TLV, "REDIRECTDATA-TLV" },
276 { 0, NULL},
279 static const value_string operation_type_vals[] = {
280 { Reserved, "Reserved" },
281 { SET, "SET" },
282 { SET_PROP, "SET-PROP" },
283 { SET_RESPONSE, "SET-RESPONSE" },
284 { SET_PROP_RESPONSE, "SET-PROP-RESPONSE" },
285 { DEL, "DEL" },
286 { DEL_RESPONSE, "DEL-RESPONSE" },
287 { GET, "GET" },
288 { GET_PROP, "GET-PROP" },
289 { GET_RESPONSE, "GET-RESPONSE" },
290 { GET_PROP_RESPONSE, "GET-PROP-RESPONSE" },
291 { REPORT, "REPORT" },
292 { COMMIT, "COMMIT" },
293 { COMMIT_RESPONSE, "COMMIT-RESPONSE" },
294 { TRCOMP, "TRCOMP" },
295 { 0, NULL},
298 static void
299 dissect_path_data_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
301 proto_item *ti, *flag_item;
302 guint length_TLV, IDcount, i;
303 guint16 type, flag;
304 proto_tree *tlv_tree, *path_data_tree, *flag_tree;
306 while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH)
308 ti = proto_tree_add_text(tree, tvb, offset, TLV_TL_LENGTH, "TLV");
309 tlv_tree = proto_item_add_subtree(ti, ett_forces_path_data_tlv);
311 type = tvb_get_ntohs(tvb, offset);
312 proto_tree_add_item(tlv_tree, hf_forces_lfbselect_tlv_type_operation_path_type,
313 tvb, offset, 2, ENC_BIG_ENDIAN);
314 length_TLV = tvb_get_ntohs(tvb, offset+2);
315 proto_tree_add_item(tlv_tree, hf_forces_lfbselect_tlv_type_operation_path_length,
316 tvb, offset+2, 2, ENC_BIG_ENDIAN);
317 if (length_TLV < TLV_TL_LENGTH)
319 expert_add_info_format(pinfo, ti, &ei_forces_lfbselect_tlv_type_operation_path_length, "Bogus TLV length: %u", length_TLV);
320 break;
322 proto_item_set_len(ti, length_TLV);
324 if (type == PATH_DATA_TLV)
326 ti = proto_tree_add_text(tree, tvb, offset+TLV_TL_LENGTH, length_TLV-TLV_TL_LENGTH, "Path Data TLV");
327 path_data_tree = proto_item_add_subtree(ti, ett_forces_path_data_tlv);
329 flag = tvb_get_ntohs(tvb, offset+TLV_TL_LENGTH);
330 flag_item = proto_tree_add_item(path_data_tree, hf_forces_lfbselect_tlv_type_operation_path_flags,
331 tvb, offset+TLV_TL_LENGTH, 2, ENC_BIG_ENDIAN);
332 flag_tree = proto_item_add_subtree(flag_item, ett_forces_path_data_tlv_flags);
333 proto_tree_add_item(flag_tree, hf_forces_lfbselect_tlv_type_operation_path_flags_selector,
334 tvb, offset+TLV_TL_LENGTH, 2, ENC_BIG_ENDIAN);
335 proto_tree_add_item(flag_tree, hf_forces_lfbselect_tlv_type_operation_path_flags_reserved,
336 tvb, offset+TLV_TL_LENGTH, 2, ENC_BIG_ENDIAN);
338 IDcount = tvb_get_ntohs(tvb, offset + TLV_TL_LENGTH + 2);
339 proto_tree_add_item(path_data_tree, hf_forces_lfbselect_tlv_type_operation_path_IDcount,
340 tvb, offset+TLV_TL_LENGTH+2, 2, ENC_BIG_ENDIAN);
342 for (i = 0; i < IDcount; i++)
343 proto_tree_add_item(path_data_tree, hf_forces_lfbselect_tlv_type_operation_path_IDs,
344 tvb, offset+TLV_TL_LENGTH+2+(i*4), 4, ENC_BIG_ENDIAN);
346 else
348 flag = 0;
349 proto_tree_add_item(tree, hf_forces_lfbselect_tlv_type_operation_path_data,
350 tvb, offset+TLV_TL_LENGTH, length_TLV-TLV_TL_LENGTH, ENC_NA);
353 if ((flag & FLAG_SELECTOR) == 0)
354 break;
356 offset += length_TLV;
360 static void
361 dissect_operation_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint length_count)
363 proto_item *ti;
364 proto_tree *oper_tree;
365 guint type, length;
367 while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH)
369 ti = proto_tree_add_text(tree, tvb, offset, length_count, "Operation TLV");
370 oper_tree = proto_item_add_subtree(ti, ett_forces_lfbselect_tlv_type_operation);
372 type = tvb_get_ntohs(tvb,offset);
373 ti = proto_tree_add_item(oper_tree, hf_forces_lfbselect_tlv_type_operation_type,
374 tvb, offset, 2, ENC_BIG_ENDIAN);
375 if (try_val_to_str(type, operation_type_vals) == NULL)
376 expert_add_info_format(pinfo, ti, &ei_forces_lfbselect_tlv_type_operation_type,
377 "Bogus: ForCES Operation TLV (Type:0x%04x) is not supported", type);
379 length = tvb_get_ntohs(tvb, offset+2);
380 proto_tree_add_uint_format_value(oper_tree, hf_forces_lfbselect_tlv_type_operation_length,
381 tvb, offset+2, 2, length, "%u Bytes", length);
383 dissect_path_data_tlv(tvb, pinfo, oper_tree, offset+TLV_TL_LENGTH);
384 if (length == 0)
385 break;
386 offset += length;
390 static void
391 dissect_lfbselecttlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint length_count)
393 guint tlv_length;
395 proto_tree_add_item(tree, hf_forces_lfbselect_tlv_type_lfb_classid, tvb, offset, 4, ENC_BIG_ENDIAN);
396 proto_tree_add_item(tree, hf_forces_lfbselect_tlv_type_lfb_instanceid, tvb, offset+4, 4, ENC_BIG_ENDIAN);
398 offset += 8;
399 while ((tvb_reported_length_remaining(tvb, offset) > TLV_TL_LENGTH) && (length_count > 12))
401 tlv_length = tvb_get_ntohs(tvb, offset+2);
402 dissect_operation_tlv(tvb, pinfo, tree, offset, tlv_length);
403 if (tlv_length == 0)
404 break;
405 offset += tlv_length;
409 static void
410 dissect_redirecttlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
412 proto_tree *meta_data_tree, *meta_data_ilv_tree, *redirect_data_tree;
413 gint start_offset;
414 gint length_meta, length_ilv, length_redirect;
415 proto_item *ti;
416 address src_addr = pinfo->src,
417 src_net_addr = pinfo->net_src,
418 dst_addr = pinfo->dst,
419 dst_net_addr = pinfo->net_dst;
421 ti = proto_tree_add_text(tree, tvb, offset, TLV_TL_LENGTH, "Meta Data TLV");
422 meta_data_tree = proto_item_add_subtree(ti, ett_forces_redirect_tlv_meta_data_tlv);
423 proto_tree_add_item(meta_data_tree, hf_forces_redirect_tlv_meta_data_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN);
425 length_meta = tvb_get_ntohs(tvb, offset+2);
426 proto_tree_add_uint_format_value(meta_data_tree, hf_forces_redirect_tlv_meta_data_tlv_length, tvb, offset+2, 2,
427 length_meta, "%u Bytes", length_meta);
428 proto_item_set_len(ti, length_meta);
430 start_offset = offset;
431 while ((tvb_reported_length_remaining(tvb, offset) >= 8) && (start_offset+length_meta > offset))
433 ti = proto_tree_add_text(tree, tvb, offset, TLV_TL_LENGTH, "Meta Data ILV");
434 meta_data_ilv_tree = proto_item_add_subtree(ti, ett_forces_redirect_tlv_meta_data_tlv_meta_data_ilv);
436 proto_tree_add_item(meta_data_ilv_tree, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_id,
437 tvb, offset+8, 4, ENC_BIG_ENDIAN);
438 length_ilv = tvb_get_ntohl(tvb, offset+12);
439 proto_tree_add_uint_format_value(meta_data_ilv_tree, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_length,
440 tvb, offset+12, 4, length_ilv, "%u Bytes", length_ilv);
441 if (length_ilv > 0)
442 proto_tree_add_item(meta_data_ilv_tree, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv,
443 tvb, offset+8, length_ilv, ENC_NA);
445 proto_item_set_len(ti, length_ilv + 8);
446 offset += length_ilv + 8;
449 if (tvb_reported_length_remaining(tvb, offset) > 0)
451 ti = proto_tree_add_text(tree, tvb, offset, TLV_TL_LENGTH, "Redirect Data TLV");
452 redirect_data_tree = proto_item_add_subtree(ti, ett_forces_redirect_tlv_redirect_data_tlv);
454 proto_tree_add_item(redirect_data_tree, hf_forces_redirect_tlv_redirect_data_tlv_type,
455 tvb, offset, 2, ENC_BIG_ENDIAN);
456 length_redirect = tvb_get_ntohs(tvb, offset+2);
457 proto_tree_add_uint_format_value(redirect_data_tree, hf_forces_redirect_tlv_redirect_data_tlv_length,
458 tvb, offset+2, 2, length_redirect, "%u Bytes", length_redirect);
460 if (tvb_reported_length_remaining(tvb, offset) < length_redirect)
462 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);
464 else if (length_redirect < TLV_TL_LENGTH + MIN_IP_HEADER_LENGTH)
466 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);
468 else
470 tvbuff_t *next_tvb;
472 next_tvb = tvb_new_subset(tvb, offset+4, length_redirect-TLV_TL_LENGTH, length_redirect-TLV_TL_LENGTH);
473 call_dissector(ip_handle, next_tvb, pinfo, redirect_data_tree);
475 /* Restore IP info */
476 memcpy(&(pinfo->src), &src_addr, sizeof(address));
477 memcpy(&(pinfo->net_src), &src_net_addr, sizeof(address));
478 memcpy(&(pinfo->dst), &dst_addr, sizeof(address));
479 memcpy(&(pinfo->net_dst), &dst_net_addr, sizeof(address));
484 static void
485 dissect_forces(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
487 /* Set up structures needed to add the protocol subtree and manage it */
488 proto_item *ti, *tlv_item;
489 proto_tree *forces_tree, *forces_flags_tree;
490 proto_tree *forces_main_header_tree, *forces_tlv_tree, *tlv_tree;
491 gint length_count;
493 guint8 message_type;
494 guint16 tlv_type;
496 /* Make entries in Protocol column and Info column on summary display */
497 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ForCES");
498 col_clear(pinfo->cinfo, COL_INFO);
500 ti = proto_tree_add_item(tree, proto_forces, tvb, 0, -1, ENC_NA);
501 forces_tree = proto_item_add_subtree(ti, ett_forces);
503 ti = proto_tree_add_text(forces_tree, tvb, 0, ForCES_HEADER_LENGTH, "Common Header");
504 forces_main_header_tree = proto_item_add_subtree(ti, ett_forces_main_header);
506 proto_tree_add_item(forces_main_header_tree, hf_forces_version, tvb, 0, 1, ENC_BIG_ENDIAN);
507 proto_tree_add_item(forces_main_header_tree, hf_forces_rsvd, tvb, 0, 1, ENC_BIG_ENDIAN);
509 message_type = tvb_get_guint8(tvb, offset+1);
510 proto_tree_add_item( forces_main_header_tree, hf_forces_messagetype, tvb, offset+1, 1, ENC_BIG_ENDIAN);
512 length_count = tvb_get_ntohs(tvb, offset+2) * 4; /*multiply 4 DWORD*/
513 ti = proto_tree_add_uint_format( forces_main_header_tree, hf_forces_length,
514 tvb, offset+2, 2, length_count, "Length: %u Bytes", length_count);
515 if (length_count != tvb_reported_length_remaining(tvb, offset))
516 expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is wrong),should be (%u bytes)",
517 length_count, tvb_reported_length_remaining(tvb, offset));
518 if (length_count < 24)
519 expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is less than 24bytes)", length_count);
521 col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type: %s, Total Length: %u Bytes",
522 val_to_str(message_type, message_type_vals, "Unknown messagetype 0x%x"), length_count);
524 proto_tree_add_item( forces_main_header_tree, hf_forces_sid, tvb, offset+4, 4, ENC_BIG_ENDIAN);
525 proto_tree_add_item( forces_main_header_tree, hf_forces_did, tvb, offset+8, 4, ENC_BIG_ENDIAN);
526 proto_tree_add_item( forces_main_header_tree, hf_forces_correlator, tvb, offset+12, 8, ENC_BIG_ENDIAN);
528 /*Add flags tree*/
529 ti = proto_tree_add_item(forces_main_header_tree, hf_forces_flags, tvb, offset+20, 4, ENC_BIG_ENDIAN);
530 forces_flags_tree = proto_item_add_subtree(ti, ett_forces_flags);
532 proto_tree_add_item(forces_flags_tree, hf_forces_flags_ack, tvb, offset+20, 4, ENC_BIG_ENDIAN);
533 proto_tree_add_item(forces_flags_tree, hf_forces_flags_at, tvb, offset+20, 4, ENC_BIG_ENDIAN);
534 proto_tree_add_item(forces_flags_tree, hf_forces_flags_em, tvb, offset+20, 4, ENC_BIG_ENDIAN);
535 proto_tree_add_item(forces_flags_tree, hf_forces_flags_pri, tvb, offset+20, 4, ENC_BIG_ENDIAN);
536 proto_tree_add_item(forces_flags_tree, hf_forces_flags_reserved, tvb, offset+20, 4, ENC_BIG_ENDIAN);
537 proto_tree_add_item(forces_flags_tree, hf_forces_flags_rsrvd, tvb, offset+20, 4, ENC_BIG_ENDIAN);
538 proto_tree_add_item(forces_flags_tree, hf_forces_flags_tp, tvb, offset+20, 4, ENC_BIG_ENDIAN);
540 offset += 24;
541 while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH)
543 ti = proto_tree_add_text(forces_tree, tvb, offset, TLV_TL_LENGTH, "TLV");
544 forces_tlv_tree = proto_item_add_subtree(ti, ett_forces_tlv);
546 tlv_type = tvb_get_ntohs(tvb, offset);
547 tlv_item = proto_tree_add_item(forces_tlv_tree, hf_forces_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN);
548 length_count = tvb_get_ntohs(tvb, offset+2) * 4;
549 proto_item_set_len(ti, length_count);
550 ti = proto_tree_add_uint_format_value(forces_tlv_tree, hf_forces_tlv_length,
551 tvb, offset+2, 2, length_count, "%u Bytes", length_count);
552 if (tvb_reported_length_remaining(tvb, offset) < length_count)
553 expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus: Main TLV length (%u bytes) is wrong", length_count);
555 if (length_count < TLV_TL_LENGTH)
557 expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus TLV length: %u", length_count);
558 break;
561 offset += TLV_TL_LENGTH;
562 length_count -= TLV_TL_LENGTH;
564 switch(tlv_type)
566 case LFBselect_TLV:
567 ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "LFB select TLV");
568 tlv_tree = proto_item_add_subtree(ti, ett_forces_lfbselect_tlv_type);
569 dissect_lfbselecttlv(tvb, pinfo, tlv_tree, offset, length_count);
570 break;
572 case REDIRECT_TLV:
573 ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Redirect TLV");
574 tlv_tree = proto_item_add_subtree(ti, ett_forces_redirect_tlv_type);
575 dissect_redirecttlv(tvb, pinfo, tlv_tree, offset);
576 break;
578 case ASResult_TLV:
579 ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASResult TLV");
580 tlv_tree = proto_item_add_subtree(ti, ett_forces_asresult_tlv);
581 proto_tree_add_item(tlv_tree, hf_forces_asresult_association_setup_result, tvb, offset, 4, ENC_BIG_ENDIAN);
582 break;
584 case ASTreason_TLV:
585 ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASTreason TLV");
586 tlv_tree = proto_item_add_subtree(ti, ett_forces_astreason_tlv);
587 proto_tree_add_item(tlv_tree, hf_forces_astreason_tlv_teardown_reason, tvb, offset, 4, ENC_BIG_ENDIAN);
588 break;
590 default:
591 expert_add_info(pinfo, tlv_item, &ei_forces_tlv_type);
592 ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Unknown TLV");
593 tlv_tree = proto_item_add_subtree(ti, ett_forces_unknown_tlv);
594 proto_tree_add_item(tlv_tree, hf_forces_unknown_tlv, tvb, offset, length_count, ENC_NA);
595 break;
598 offset += length_count;
602 /* Code to actually dissect the TCP packets */
603 static void
604 dissect_forces_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
606 dissect_forces(tvb, pinfo, tree, TCP_UDP_TML_FOCES_MESSAGE_OFFSET_TCP);
609 /* Code to actually dissect the ForCES protocol layer packets,like UDP,SCTP and others */
610 static void
611 dissect_forces_not_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
613 dissect_forces(tvb, pinfo, tree, 0);
616 void proto_reg_handoff_forces(void);
618 void
619 proto_register_forces(void)
621 module_t *forces_module;
622 expert_module_t* expert_forces;
624 /* Setup list of header fields See Section 1.6.1 for details*/
625 static hf_register_info hf[] = {
626 { &hf_forces_version,
627 { "Version", "forces.flags.version",
628 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
630 { &hf_forces_rsvd,
631 { "Rsvd", "forces.flags.rsvd",
632 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
634 { &hf_forces_messagetype,
635 { "Message Type", "forces.messagetype",
636 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
638 { &hf_forces_length,
639 { "Header Length", "forces.length",
640 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
642 { &hf_forces_sid,
643 { "Source ID", "forces.sid",
644 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
646 { &hf_forces_did,
647 { "Destination ID", "forces.did",
648 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
650 { &hf_forces_correlator,
651 { "Correlator", "forces.correlator",
652 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
654 { &hf_forces_tlv_type,
655 { "Type", "forces.tlv.type",
656 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
658 { &hf_forces_tlv_length,
659 { "Length", "forces.tlv.length",
660 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
662 /*flags*/
663 { &hf_forces_flags,
664 { "Flags", "forces.Flags",
665 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
667 { &hf_forces_flags_ack,
668 { "ACK indicator", "forces.flags.ack",
669 FT_UINT32, BASE_DEC, VALS(main_header_flags_ack_vals), 0xC0000000, NULL, HFILL }
671 { &hf_forces_flags_pri,
672 { "Priority", "forces.flags.pri",
673 FT_UINT32, BASE_DEC, NULL, 0x38000000, NULL, HFILL }
675 { &hf_forces_flags_rsrvd,
676 { "Rsrvd", "forces.Flags",
677 FT_UINT32, BASE_DEC,NULL, 0x07000000, NULL, HFILL }
679 { &hf_forces_flags_em,
680 { "Execution mode", "forces.flags.em",
681 FT_UINT32, BASE_DEC, VALS(main_header_flags_em_vals), 0x00C00000, NULL, HFILL }
683 { &hf_forces_flags_at,
684 { "Atomic Transaction", "forces.flags.at",
685 FT_UINT32, BASE_DEC, VALS(main_header_flags_at_vals), 0x00200000, NULL, HFILL }
687 { &hf_forces_flags_tp,
688 { "Transaction phase", "forces.flags.tp",
689 FT_UINT32, BASE_DEC, VALS(main_header_flags_tp_vals), 0x00180000, NULL, HFILL }
691 { &hf_forces_flags_reserved,
692 { "Reserved", "forces.flags.reserved",
693 FT_UINT32, BASE_DEC,NULL, 0x0007ffff, NULL, HFILL }
695 /*LFBSelectTLV*/
696 { &hf_forces_lfbselect_tlv_type_lfb_classid,
697 { "Class ID", "forces.lfbselect.tlv.type.lfb.classid",
698 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
700 { &hf_forces_lfbselect_tlv_type_lfb_instanceid,
701 { "Instance ID", "forces.fbselect.tlv.type.lfb.instanceid",
702 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
704 /*Operation TLV*/
705 { &hf_forces_lfbselect_tlv_type_operation_type,
706 { "Type", "forces.lfbselect.tlv.type.operation.type",
707 FT_UINT16, BASE_DEC, VALS(operation_type_vals), 0x0, NULL, HFILL }
709 { &hf_forces_lfbselect_tlv_type_operation_length,
710 { "Length", "forces.lfbselect.tlv.type.operation.length",
711 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
713 { &hf_forces_lfbselect_tlv_type_operation_path_type,
714 { "Type", "forces.lfbselect.tlv.type.operation.path.type",
715 FT_UINT16, BASE_DEC, VALS(tlv_type_vals), 0x0, NULL, HFILL }
717 { &hf_forces_lfbselect_tlv_type_operation_path_length,
718 { "Length", "forces.lfbselect.tlv.type.operation.path.length",
719 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
721 { &hf_forces_lfbselect_tlv_type_operation_path_data,
722 { "Data", "forces.lfbselect.tlv.type.operation.path.data",
723 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
725 { &hf_forces_lfbselect_tlv_type_operation_path_flags,
726 {"Path Data Flags", "forces.lfbselect.tlv.type.operation.path.data.flags",
727 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
729 { &hf_forces_lfbselect_tlv_type_operation_path_flags_selector,
730 {"Selector", "forces.lfbselect.tlv.type.operation.path.data.flags.selector",
731 FT_UINT16, BASE_HEX, NULL, 0x80, NULL, HFILL }
733 { &hf_forces_lfbselect_tlv_type_operation_path_flags_reserved,
734 {"Reserved", "forces.lfbselect.tlv.type.operation.path.data.flags.reserved",
735 FT_UINT16, BASE_HEX, NULL, 0x7F, NULL, HFILL }
737 { &hf_forces_lfbselect_tlv_type_operation_path_IDcount,
738 { "Path Data IDcount", "forces.lfbselect.tlv.type.operation.path.data.IDcount",
739 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
741 { &hf_forces_lfbselect_tlv_type_operation_path_IDs,
742 { "Path Data IDs", "forces.lfbselect.tlv.type.operation.path.data.IDs",
743 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
745 /*Meta data TLV*/
746 {&hf_forces_redirect_tlv_meta_data_tlv_type,
747 { "Type", "forces.redirect.tlv.meta.data.tlv.type",
748 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
750 { &hf_forces_redirect_tlv_meta_data_tlv_length,
751 { "Length", "forces.redirect.tlv.meta.data.tlv.length",
752 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
754 { &hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv,
755 { "Meta Data ILV", "forces.redirect.tlv.meta.data.tlv.meta.data.ilv",
756 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
758 { &hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_id,
759 { "ID", "forces.redirect.tlv.meta.data.tlv.meta.data.ilv.id",
760 FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }
762 { &hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_length,
763 { "Length", "forces.redirect.tlv.meta.data.tlv.meta.data.ilv.length",
764 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
766 { &hf_forces_redirect_tlv_redirect_data_tlv_type,
767 { "Type", "forces.redirect.tlv.redirect.data.tlv.type",
768 FT_UINT16, BASE_DEC, VALS(tlv_type_vals), 0x0, NULL, HFILL }
770 { &hf_forces_redirect_tlv_redirect_data_tlv_length,
771 { "Length", "forces.redirect.tlv.redirect.data.tlv.length",
772 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
774 { &hf_forces_asresult_association_setup_result,
775 { "Association Setup Result", "forces.teardown.reason",
776 FT_UINT32, BASE_DEC, VALS(association_setup_result_at_vals), 0x0, NULL, HFILL }
778 { &hf_forces_astreason_tlv_teardown_reason,
779 { "AStreason TLV TearDonw Reason", "forces.astreason.tlv.teardonw.reason",
780 FT_UINT32, BASE_DEC, VALS(teardown_reason_at_vals), 0x0, NULL, HFILL }
782 { &hf_forces_unknown_tlv,
783 { "Data", "forces.unknown.tlv",
784 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
788 /* Setup protocol subtree array */
789 static gint *ett[] = {
790 &ett_forces,
791 &ett_forces_main_header,
792 &ett_forces_flags,
793 &ett_forces_tlv,
794 &ett_forces_lfbselect_tlv_type,
795 &ett_forces_lfbselect_tlv_type_operation,
796 &ett_forces_lfbselect_tlv_type_operation_path,
797 &ett_forces_lfbselect_tlv_type_operation_path_data,
798 &ett_forces_lfbselect_tlv_type_operation_path_data_path,
799 &ett_forces_lfbselect_tlv_type_operation_path_selector,
800 &ett_forces_path_data_tlv,
801 &ett_forces_path_data_tlv_flags,
802 &ett_forces_redirect_tlv_type,
803 &ett_forces_redirect_tlv_meta_data_tlv,
804 &ett_forces_redirect_tlv_redirect_data_tlv,
805 &ett_forces_redirect_tlv_meta_data_tlv_meta_data_ilv,
806 &ett_forces_asresult_tlv,
807 &ett_forces_astreason_tlv,
808 &ett_forces_unknown_tlv
811 static ei_register_info ei[] = {
812 { &ei_forces_length, { "forces.length.bad", PI_PROTOCOL, PI_WARN, "ForCES Header length is wrong", EXPFILL }},
813 { &ei_forces_tlv_type, { "forces.tlv.type.unknown", PI_PROTOCOL, PI_WARN, "Bogus: The Main_TLV type is unknown", EXPFILL }},
814 { &ei_forces_tlv_length, { "forces.tlv.length.bad", PI_PROTOCOL, PI_WARN, "Bogus TLV length", EXPFILL }},
815 { &ei_forces_lfbselect_tlv_type_operation_path_length, { "forces.lfbselect.tlv.type.operation.path.length.bad", PI_PROTOCOL, PI_WARN, "Bogus TLV length", EXPFILL }},
816 { &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 }},
817 { &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 }},
820 /* Register the protocol name and description */
821 proto_forces = proto_register_protocol("Forwarding and Control Element Separation Protocol", "ForCES", "forces");
823 /* Required function calls to register the header fields and subtrees used */
824 proto_register_field_array(proto_forces, hf, array_length(hf));
825 proto_register_subtree_array(ett, array_length(ett));
826 expert_forces = expert_register_protocol(proto_forces);
827 expert_register_field_array(expert_forces, ei, array_length(ei));
829 forces_module = prefs_register_protocol(proto_forces,proto_reg_handoff_forces);
831 prefs_register_uint_preference(forces_module, "tcp_alternate_port",
832 "TCP port",
833 "Decode packets on this TCP port as ForCES",
834 10, &forces_alternate_tcp_port);
836 prefs_register_uint_preference(forces_module, "udp_alternate_port",
837 "UDP port",
838 "Decode packets on this UDP port as ForCES",
839 10, &forces_alternate_udp_port);
841 prefs_register_uint_preference(forces_module, "sctp_high_prio_port",
842 "SCTP High Priority channel port",
843 "Decode packets on this sctp port as ForCES",
844 10, &forces_alternate_sctp_high_prio_channel_port);
846 prefs_register_uint_preference(forces_module, "sctp_med_prio_port",
847 "SCTP Meidium Priority channel port",
848 "Decode packets on this sctp port as ForCES",
849 10, &forces_alternate_sctp_med_prio_channel_port);
851 prefs_register_uint_preference(forces_module, "sctp_low_prio_port",
852 "SCTP Low Priority channel port",
853 "Decode packets on this sctp port as ForCES",
854 10, &forces_alternate_sctp_low_prio_channel_port);
857 void
858 proto_reg_handoff_forces(void)
860 static gboolean inited = FALSE;
862 static guint alternate_tcp_port = 0; /* 3000 */
863 static guint alternate_udp_port = 0;
864 static guint alternate_sctp_high_prio_channel_port = 0; /* 6700 */
865 static guint alternate_sctp_med_prio_channel_port = 0;
866 static guint alternate_sctp_low_prio_channel_port = 0;
868 static dissector_handle_t forces_handle_tcp, forces_handle;
870 if (!inited) {
871 forces_handle_tcp = create_dissector_handle(dissect_forces_tcp, proto_forces);
872 forces_handle = create_dissector_handle(dissect_forces_not_tcp, proto_forces);
873 ip_handle = find_dissector("ip");
874 inited = TRUE;
877 /* Register TCP port for dissection */
878 if ((alternate_tcp_port != 0) && (alternate_tcp_port != forces_alternate_tcp_port))
879 dissector_delete_uint("tcp.port", alternate_tcp_port, forces_handle_tcp);
880 if ((forces_alternate_tcp_port != 0) && (alternate_tcp_port != forces_alternate_tcp_port))
881 dissector_add_uint("tcp.port", forces_alternate_tcp_port, forces_handle_tcp);
882 alternate_tcp_port = forces_alternate_tcp_port;
884 /* Register UDP port for dissection */
885 if ((alternate_udp_port != 0) && (alternate_udp_port != forces_alternate_udp_port))
886 dissector_delete_uint("udp.port", alternate_udp_port, forces_handle);
887 if ((forces_alternate_udp_port != 0) && (alternate_udp_port != forces_alternate_udp_port))
888 dissector_add_uint("udp.port", forces_alternate_udp_port, forces_handle);
889 alternate_udp_port = forces_alternate_udp_port;
891 /* Register SCTP port for high priority dissection */
892 if ((alternate_sctp_high_prio_channel_port != 0) &&
893 (alternate_sctp_high_prio_channel_port != forces_alternate_sctp_high_prio_channel_port))
894 dissector_delete_uint("sctp.port", alternate_sctp_high_prio_channel_port, forces_handle);
895 if ((forces_alternate_sctp_high_prio_channel_port != 0) &&
896 (alternate_sctp_high_prio_channel_port != forces_alternate_sctp_high_prio_channel_port))
897 dissector_add_uint("sctp.port", forces_alternate_sctp_high_prio_channel_port, forces_handle);
898 alternate_sctp_high_prio_channel_port = forces_alternate_sctp_high_prio_channel_port;
900 /* Register SCTP port for medium priority dissection */
901 if ((alternate_sctp_med_prio_channel_port != 0) &&
902 (alternate_sctp_med_prio_channel_port != forces_alternate_sctp_med_prio_channel_port))
903 dissector_delete_uint("udp.port", alternate_sctp_med_prio_channel_port, forces_handle);
904 if ((forces_alternate_sctp_med_prio_channel_port != 0) &&
905 (alternate_sctp_med_prio_channel_port != forces_alternate_sctp_med_prio_channel_port))
906 dissector_add_uint("udp.port", forces_alternate_sctp_med_prio_channel_port, forces_handle);
907 alternate_sctp_med_prio_channel_port = forces_alternate_sctp_med_prio_channel_port;
909 /* Register SCTP port for low priority dissection */
910 if ((alternate_sctp_low_prio_channel_port != 0) &&
911 (alternate_sctp_low_prio_channel_port != forces_alternate_sctp_low_prio_channel_port))
912 dissector_delete_uint("udp.port", alternate_sctp_low_prio_channel_port, forces_handle);
913 if ((forces_alternate_sctp_low_prio_channel_port != 0) &&
914 (alternate_sctp_low_prio_channel_port != forces_alternate_sctp_low_prio_channel_port))
915 dissector_add_uint("udp.port", forces_alternate_sctp_low_prio_channel_port, forces_handle);
916 alternate_sctp_low_prio_channel_port = forces_alternate_sctp_low_prio_channel_port;
920 * Editor modelines - http://www.wireshark.org/tools/modelines.html
922 * Local variables:
923 * c-basic-offset: 4
924 * tab-width: 8
925 * indent-tabs-mode: nil
926 * End:
928 * vi: set shiftwidth=4 tabstop=8 expandtab:
929 * :indentSize=4:tabSize=8:noTabs=true: