diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 2f4ae71bd3..1237a4f0de 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -586,6 +586,7 @@ CLEAN_DISSECTOR_SRC = \ packet-pana.c \ packet-p_mul.c \ packet-pagp.c \ + packet-pce.c \ packet-pcnfsd.c \ packet-per.c \ packet-pflog.c \ diff --git a/epan/dissectors/packet-pce.c b/epan/dissectors/packet-pce.c new file mode 100644 index 0000000000..7d98331644 --- /dev/null +++ b/epan/dissectors/packet-pce.c @@ -0,0 +1,2209 @@ +/* packet-pce.c + * Routines for PCE packet disassembly + * + * (c) Copyright 2007 Silvia Cristina Tejedor + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include "packet-frame.h" + +/*differents types of objects*/ +#define PCE_OPEN_OBJ 1 +#define PCE_RP_OBJ 2 +#define PCE_NO_PATH_OBJ 3 +#define PCE_END_POINT_OBJ 4 +#define PCE_BANDWIDTH_OBJ 5 +#define PCE_METRIC_OBJ 6 +#define PCE_EXPLICIT_ROUTE_OBJ 7 +#define PCE_RECORD_ROUTE_OBJ 8 +#define PCE_LSPA_OBJ 9 +#define PCE_IRO_OBJ 10 +#define PCE_SVEC_OBJ 11 +#define PCE_NOTIFICATION_OBJ 12 +#define PCE_PCEP_ERROR_OBJ 13 +#define PCE_LOAD_BALANCING_OBJ 14 +#define PCE_CLOSE_OBJ 15 +#define NO_DEFINED_OBJ 16 +#define PCE_XRO_OBJ 17 + +/*Subobjects of EXPLICIT ROUTE Object*/ +#define PCE_SUB_IPv4 1 +#define PCE_SUB_IPv6 2 +#define PCE_SUB_LABEL_CONTROL 3 +#define PCE_SUB_UNNUMB_INTERFACE_ID 4 +#define PCE_SUB_SRLG 5 +#define PCE_SUB_AUTONOMOUS_SYS_NUM 32 +#define PCE_SUB_EXRS 33 +#define PCE_SUB_AUTONOMOUS_SYS_NUM_XRO 4 +#define PCE_SUB_UNNUMB_INTERFACE_ID_XRO 3 + +/*Possible values of the NI in the NO-PATH object*/ +#define NO_SATISFYING 0 +#define CHAIN_BROKEN 1 + +/*Possible values of "Type (T)" in the METRIC object */ +#define NO_DEFINED 0 +#define IGP_METRIC 1 +#define TE_METRIC 2 +#define HOP_COUNTS 3 + +/*Possible values of L in the ERO and IRO objects */ +#define STRICT_HOP 0 +#define LOOSE_HOP 1 + +/*Possible values of U in the ERO and RRO objects */ +#define DOWNSTREAM_LABEL 0 +#define UPSTREAM_LABEL 1 + +/*Possible values of Notification Type */ +#define NOT_REQ_CANCEL 1 +#define PCE_CONGESTION 2 + +/*Possible values of Notification Value for NT=1*/ +#define NOTI_PCC_CANCEL_REQ 1 +#define NOTI_PCE_CANCEL_REQ 2 + +/*Possible values of Notification Value for NT=2*/ +#define NOTI_PCE_CONGEST 1 +#define NOTI_PCE_NO_CONGEST 2 + +/*Possible types of errors */ +#define ESTABLISH_FAILURE 1 +#define CAP_NOT_SUPPORTED 2 +#define UNKNOWN_OBJ 3 +#define NOT_SUPP_OBJ 4 +#define POLICY_VIOLATION 5 +#define MANDATORY_OBJ_MIS 6 +#define SYNCH_PCREQ_MIS 7 +#define UNKNOWN_REQ_REF 8 +#define ATTEMPT_2_SESSION 9 +#define UNRECO_IRO_SUBOBJ 11 +#define UNRECO_EXRS_SUBOBJ 12 + +/*Different values of errors type=1*/ +#define RX_MALFORM_PKT 1 +#define NO_OPEN_MSG 2 +#define UNACEP_NO_NEGO_SSESION 3 +#define UNACEP_NEG_SESSION 4 +#define TWO_OPEN_MSG_UNACEP 5 +#define RX_PCEERR_UNACEP_SESSION 6 +#define NO_KEEPALIVE_PCEERR 7 + +/*Different values of errors type=3*/ +#define UNRECON_OBJ_CLASS 1 +#define UNRECON_OBJ_TYPE 2 + +/*Different values of errors type=4*/ +#define NO_SUPP_OBJ 1 +#define NO_SUPP_TYPE 2 + +/*Different values of errors type=5*/ +#define C_METRIC_SET 1 +#define O_OBJ_SET 2 + +/*Different values of errors type=6*/ +#define RP_OBJ_MISS 1 +#define RRO_OBJ_MISS 2 +#define END_POINT_OBJ_MISS 3 + +/*Different values of Reason in the CLOSE object */ +#define NO_EXP_PROV 1 +#define DEADTIME_PROV 2 +#define RECEP_MALFORM_MSG 3 + +/*Different values of Atribute in the XRO object */ +#define INTERFACE 0 +#define NODE 1 +#define SRLG 2 + +/*Mask for the flags of HEADER of Messages*/ +#define PCE_HDR_MSG_RESERVED 0x1f + +/*Mask for the type of HEADER of Objects*/ +#define MASK_OBJ_TYPE 0xF0 + +/*Mask for the flags of HEADER of Objects*/ +#define PCE_HDR_OBJ_RESERVED 0x0C +#define PCE_HDR_OBJ_P 0x02 +#define PCE_HDR_OBJ_I 0x01 + +/*Mask for the flags of OPEN Object*/ +#define PCE_OPEN_RES 0x1F + +/*Mask for the flags of RP Object*/ +#define PCE_RP_PRI 0x000007 +#define PCE_RP_R 0x000008 +#define PCE_RP_B 0x000010 +#define PCE_RP_O 0x000020 +#define PCE_RP_RESERVED 0xFFFFC0 + +/*Mask for the flags of NO PATH Object*/ +#define PCE_NO_PATH_C 0x8000 + +/*Mask for the flags of METRIC Object*/ +#define PCE_METRIC_C 0x01 +#define PCE_METRIC_B 0x02 + +/*Mask for the flags of LSPA Object*/ +#define PCE_LSPA_L 0x01 + +/* Mask to differentiate the value of L and Type (Explicit Object)*/ +#define Mask_L 0x80 +#define Mask_Type 0x7f + +#define TCP_PORT_PPCE 1010 + +#define IPv4 1 +#define IPv6 2 + +/*Mask for the flags os SVEC Object*/ +#define PCE_SVEC_L 0x000001 +#define PCE_SVEC_N 0x000002 +#define PCE_SVEC_S 0x000004 + +/*Mask for the flags of XRO Object*/ +#define PCE_XRO_F 0x0001 + +/*Mask for the flags of IPv4, IPv6 and UNnumbered InterfaceID Subobjects of RRO Object*/ +#define PCE_SUB_LPA 0x01 +#define PCE_SUB_LPU 0x02 + +/*Mask for the flags of Label SubObject*/ +#define PCE_SUB_LABEL_GL 0x01 + + +static int proto_pce = -1; +static gint ett_pce = -1; +static gint ett_pce_hdr = -1; +static gint pce_hdr_msg_flags_reserved= -1; +static gint ett_pce_msg_open = -1; +static gint ett_pce_msg_keepalive = -1; +static gint ett_pce_msg_request = -1; +static gint ett_pce_msg_reply = -1; +static gint ett_pce_msg_notification = -1; +static gint ett_pce_msg_error = -1; +static gint ett_pce_msg_close = -1; +static gint ett_pce_obj_hdr = -1; +static gint pce_hdr_obj_flags_reserved= -1; +static gint pce_hdr_obj_flags_p= -1; +static gint pce_hdr_obj_flags_i= -1; +static gint ett_pce_obj_open = -1; +static gint pce_open_flags_res = -1; +static gint ett_pce_obj_request_parameters = -1; +static gint pce_rp_flags_pri = -1; +static gint pce_rp_flags_r = -1; +static gint pce_rp_flags_b = -1; +static gint pce_rp_flags_o = -1; +static gint pce_rp_flags_reserved = -1; +static gint ett_pce_obj_no_path = -1; +static gint pce_no_path_flags_c = -1; +static gint ett_pce_obj_end_point = -1; +static gint ett_pce_obj_bandwidth = -1; +static gint ett_pce_obj_metric = -1; +static gint pce_metric_flags_c = -1; +static gint pce_metric_flags_b = -1; +static gint ett_pce_obj_explicit_route = -1; +static gint ett_pce_obj_record_route = -1; +static gint ett_pce_obj_lspa = -1; +static gint pce_lspa_flags_l= -1; +static gint ett_pce_obj_iro = -1; +static gint ett_pce_obj_svec = -1; +static gint pce_svec_flags_l= -1; +static gint pce_svec_flags_n= -1; +static gint pce_svec_flags_s= -1; +static gint ett_pce_obj_notification = -1; +static gint ett_pce_obj_error = -1; +static gint ett_pce_obj_load_balancing = -1; +static gint ett_pce_obj_close = -1; +static gint ett_pce_obj_xro = -1; +static gint pce_xro_flags_f= -1; +static gint pce_subobj_flags_lpa= -1; +static gint pce_subobj_flags_lpu= -1; +static gint pce_subobj_label_flags_gl= -1; +static dissector_table_t pce_dissector_table; +static dissector_handle_t data_handle; + +/* PCE message types.*/ +typedef enum { + PCE_MSG_NO_VALID, + PCE_MSG_OPEN, + PCE_MSG_KEEPALIVE, + PCE_MSG_PATH_COMPUTATION_REQUEST, + PCE_MSG_PATH_COMPUTATION_REPLY, + PCE_MSG_NOTIFICATION, + PCE_MSG_ERROR, + PCE_MSG_CLOSE +} pce_message_types; + +static const value_string message_type_vals[] = { + {PCE_MSG_OPEN, "OPEN MESSAGE" }, + {PCE_MSG_KEEPALIVE, "KEEPALIVE MESSAGE" }, + {PCE_MSG_PATH_COMPUTATION_REQUEST, "PATH COMPUTATION REQUEST MESSAGE" }, + {PCE_MSG_PATH_COMPUTATION_REPLY, "PATH COMPUTATION REPLY MESSAGE" }, + {PCE_MSG_NOTIFICATION, "NOTIFICATION MESSAGE" }, + {PCE_MSG_ERROR, "ERROR MESSAGE" }, + {PCE_MSG_CLOSE, "CLOSE MESSAGE" }, + {0, NULL } +}; + +static const value_string pce_class_vals[] = { + {PCE_OPEN_OBJ, "OPEN OBJECT" }, + {PCE_RP_OBJ, "RP OBJECT" }, + {PCE_NO_PATH_OBJ, "NO-PATH OBJECT" }, + {PCE_END_POINT_OBJ, "END-POINT OBJECT" }, + {PCE_BANDWIDTH_OBJ, "BANDWIDTH OBJECT" }, + {PCE_METRIC_OBJ, "METRIC OBJECT" }, + {PCE_EXPLICIT_ROUTE_OBJ, "EXPLICIT ROUTE OBJECT (ERO)" }, + {PCE_RECORD_ROUTE_OBJ, "RECORD ROUTE OBJECT (RRO)" }, + {PCE_LSPA_OBJ, "LSPA OBJECT" }, + {PCE_IRO_OBJ, "IRO OBJECT" }, + {PCE_SVEC_OBJ, "SVEC OBJECT" }, + {PCE_NOTIFICATION_OBJ, "NOTIFICATION OBJECT" }, + {PCE_PCEP_ERROR_OBJ, "PCEP ERROR OBJECT" }, + {PCE_LOAD_BALANCING_OBJ, "LOAD BALANCING OBJECT" }, + {PCE_CLOSE_OBJ, "CLOSE OBJECT" }, + {NO_DEFINED_OBJ, "Non Defined OBJECT" }, + {PCE_XRO_OBJ, "EXCLUDE ROUTE OBJECT (XRO)" }, + {0, NULL } +}; + +static const value_string pce_subobj_vals[] = { + {PCE_SUB_IPv4, "SUBOBJECT IPv4" }, + {PCE_SUB_IPv6, "SUBOBJECT IPv6" }, + {PCE_SUB_LABEL_CONTROL, "SUBOBJECT LABEL" }, + {PCE_SUB_UNNUMB_INTERFACE_ID, "SUBOBJECT UNNUMBERED INTERFACE-ID" }, + {PCE_SUB_SRLG, "SUBOBJECT SRLG" }, + {PCE_SUB_AUTONOMOUS_SYS_NUM, "SUBOBJECT AUTONOMOUS SYSTEM NUMBER" }, + {0, NULL } +}; + + +static const value_string pce_subobj_xro_vals[] = { + {PCE_SUB_IPv4, "SUBOBJECT IPv4" }, + {PCE_SUB_IPv6, "SUBOBJECT IPv6" }, + {PCE_SUB_UNNUMB_INTERFACE_ID_XRO,"SUBOBJECT UNNUMBERED INTERFACE-ID" }, + {PCE_SUB_AUTONOMOUS_SYS_NUM_XRO,"SUBOBJECT AUTONOMOUS SYSTEM NUMBER" }, + {PCE_SUB_SRLG, "SUBOBJECT SRLG" }, + {0, NULL } +}; + +/*In the NO-PATH Object the two different possibilities that NI can have*/ +static const value_string pce_no_path_obj_vals[] = { + {NO_SATISFYING, "Nature of Issue: No path satisfying the set of constraints could be found (0x0)" }, + {CHAIN_BROKEN, "Nature of Issue: PCE Chain Broken (0x1)" }, + {0, NULL } +}; + +/*Different values of "Type (T)" in the METRIC Obj */ +static const value_string pce_metric_obj_vals[] = { + {NO_DEFINED, "Type not defined" }, + {IGP_METRIC, "Type: IGP Metric (T=1)" }, + {TE_METRIC, "Type: TE Metric (T=2)" }, + {HOP_COUNTS, "Type: Hop Counts (T=3)" }, + {0, NULL } +}; + +/*Different values for (L) in the ERO and IRO Objs */ +static const value_string pce_route_l_obj_vals[] = { + {STRICT_HOP, "L=0 Strict Hop in the Explicit Route" }, + {LOOSE_HOP, "L=1 Loose Hop in the Explicit Route" }, + {0, NULL } +}; + +/*Different values of the direction of the label (U) in the ERO and RRO Objs */ +static const value_string pce_route_u_obj_vals[] = { + {DOWNSTREAM_LABEL, "U=0 S Downstream Label" }, + {UPSTREAM_LABEL, "U=1 Upstream Label" }, + {0, NULL } +}; + +/*Values of Notification type*/ +static const value_string pce_notification_types_vals[] = { + {NOT_REQ_CANCEL, "Pending Request Cancelled" }, + {PCE_CONGESTION, "PCE Congestion" }, + {0, NULL } +}; + +/*Values of Notification value for Notification Type=1*/ +static const value_string pce_notification_values1_vals[] = { + {NOTI_PCC_CANCEL_REQ, "PCC Cancels a set of Pending Request (s)" }, + {NOTI_PCE_CANCEL_REQ, "PCE Cancels a set of Pending Request (s)" }, + {0, NULL } +}; + +/*Values of Notification value for Notification Type=2*/ +static const value_string pce_notification_values2_vals[] = { + {NOTI_PCE_CONGEST, "PCE in Congested State " }, + {NOTI_PCE_NO_CONGEST, "PCE no Longer in Congested state" }, + {0, NULL } +}; + + +/*Values of different types of errors*/ +static const value_string pce_error_types_obj_vals[] = { + {ESTABLISH_FAILURE, "1 PCEP Session Establishment Failure" }, + {CAP_NOT_SUPPORTED, "2 Capability non supported" }, + {UNKNOWN_OBJ, "3 Unknown Object" }, + {NOT_SUPP_OBJ, "4 Not Supported Object" }, + {POLICY_VIOLATION, "5 Policy Violation" }, + {MANDATORY_OBJ_MIS, "6 Mandatory Object Missing" }, + {SYNCH_PCREQ_MIS, "7 Synchronized Path Computation Request Missing" }, + {UNKNOWN_REQ_REF, "8 Unknown Request Reference" }, + {ATTEMPT_2_SESSION, "9 Attempt to Establish a Second PCEP Session" }, + {UNRECO_IRO_SUBOBJ, "11 Unrecognized IRO Subobject" }, + {UNRECO_EXRS_SUBOBJ, "12 Unrecognized EXRS Subobject" }, + {0, NULL } +}; + +static const value_string pce_close_reason_obj_vals[] = { + {NO_DEFINED, "Reason = 0 no defined" }, + {NO_EXP_PROV, "Reason = 1 No Explanation Provided " }, + {DEADTIME_PROV, "Reason = 2 Deadtime Expired" }, + {RECEP_MALFORM_MSG, "Reason = 3 Reception of a Malformed PCEP Message" }, + {0, NULL } +}; + +static const value_string pce_xro_atribute_obj_vals[] = { + {INTERFACE, "Atribute = 0 Interface" }, + {NODE, "Atribute = 1 Node " }, + {SRLG, "Atribute = 2 SRLG" }, + {0, NULL } +}; + +/* The PCE filtering keys */ +enum pce_filter_keys{ + + PCEF_MSG, + + PCEF_OPEN, + PCEF_KEEPALIVE, + PCEF_PATH_COMPUTATION_REQUEST, + PCEF_PATH_COMPUTATION_REPLY, + PCEF_NOTIFICATION, + PCEF_ERROR, + PCEF_CLOSE, + + PCEF_OBJ_HEADER, + PCEF_OBJECT, + PCEF_OBJ_OPEN, + PCEF_OBJ_RP, + PCEF_OBJ_NO_PATH, + PCEF_OBJ_END_POINT, + PCEF_OBJ_BANDWIDTH, + PCEF_OBJ_METRIC, + PCEF_OBJ_EXPLICIT_ROUTE, + PCEF_OBJ_RECORD_ROUTE, + PCEF_OBJ_LSPA, + PCEF_OBJ_IRO, + PCEF_OBJ_SVEC, + PCEF_OBJ_NOTIFICATION, + PCEF_NOTI_TYPE, + PCEF_NOTI_VAL1, + PCEF_NOTI_VAL2, + PCEF_OBJ_PCEP_ERROR, + PCEF_ERROR_TYPE, + PCEF_OBJ_LOAD_BALANCING, + PCEF_OBJ_CLOSE, + PCEF_OBJ_NO_DEF, + PCEF_OBJ_XRO, + PCEF_SUBOBJ, + PCEF_SUBOBJ_IPv4, + PCEF_SUBOBJ_IPv6, + PCEF_SUBOBJ_LABEL_CONTROL, + PCEF_SUBOBJ_UNNUM_INTERFACEID, + PCEF_SUBOBJ_AUTONOMOUS_SYS_NUM, + PCEF_SUBOBJ_SRLG, + PCEF_SUBOBJ_EXRS, + PCEF_SUBOBJ_XRO, + PCEF_SUB_XRO_ATRIB, + + PCEF_MAX + +}; + + +/*Registering data structures*/ + +static gint *ett[] = { + &ett_pce, + &ett_pce_hdr, + &ett_pce_msg_open, + &ett_pce_msg_keepalive, + &ett_pce_msg_request, + &ett_pce_msg_reply, + &ett_pce_msg_notification, + &ett_pce_msg_error, + &ett_pce_msg_close, + &ett_pce_obj_hdr, + &ett_pce_obj_open, + &ett_pce_obj_request_parameters, + &ett_pce_obj_no_path, + &ett_pce_obj_end_point, + &ett_pce_obj_bandwidth, + &ett_pce_obj_metric, + &ett_pce_obj_explicit_route, + &ett_pce_obj_record_route, + &ett_pce_obj_lspa, + &ett_pce_obj_iro, + &ett_pce_obj_svec, + &ett_pce_obj_notification, + &ett_pce_obj_error, + &ett_pce_obj_load_balancing, + &ett_pce_obj_close, + &ett_pce_obj_xro +}; + +/*Registering data structures*/ + +static int pce_filter[PCEF_MAX]; + +static hf_register_info pcef_info[] = { + + /* Message type number */ + {&pce_filter[PCEF_MSG], + { "Message Type", "pce.msg", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x0, + "", HFILL }}, + { &pce_hdr_msg_flags_reserved, + { "Reserved Flags", "pce.hdr.msg.flags.reserved", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_HDR_MSG_RESERVED, + "", HFILL }}, + {&pce_filter[PCEF_OPEN], + { "Open Message", "pce.msg.open", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_KEEPALIVE], + { "Keepalive Message", "pce.msg.keepalive", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_PATH_COMPUTATION_REQUEST], + { "Path Computation Request Message", "pce.msg.path.computation.request", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_PATH_COMPUTATION_REPLY], + { "Path Computation Reply Mesagge", "pce.msg.path.computation.reply", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_NOTIFICATION], + { "Notification Message", "pce.msg.notification", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_ERROR], + { "Error Message", "pce.msg.error", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_CLOSE], + { "Close Message", "pce.msg.close", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "", HFILL }}, + + /*Object header*/ + { &pce_hdr_obj_flags_reserved, + { "Reserved Flags", "pce.hdr.obj.flags.reserved", FT_BOOLEAN, 4, TFS(&tfs_set_notset), PCE_HDR_OBJ_RESERVED, + "", HFILL }}, + { &pce_hdr_obj_flags_p, + { "Processing-Rule (P)", "pce.hdr.obj.flags.p", FT_BOOLEAN, 4, TFS(&tfs_set_notset), PCE_HDR_OBJ_P, + "", HFILL }}, + { &pce_hdr_obj_flags_i, + { "Ignore (I)", "pce.hdr.obj.flags.i", FT_BOOLEAN, 4, TFS(&tfs_set_notset), PCE_HDR_OBJ_I, + "", HFILL }}, + /* Object class */ + {&pce_filter[PCEF_OBJECT], + { "Object Class", "pce.object", FT_UINT32, BASE_DEC, VALS(pce_class_vals), 0x0, + "", HFILL }}, + + /* Object types */ + {&pce_filter[PCEF_OBJ_OPEN], + { "PCE OPEN OBJECT Body", "pce.obj.open", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + { &pce_open_flags_res, + { "Reserved Flags", "pce.open.flags.res", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_OPEN_RES, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_RP], + { "PCE RP OBJECT Body", "pce.obj.rp", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + { &pce_rp_flags_reserved, + { "Reserved Flags", "pce.rp.flags.reserved", FT_BOOLEAN, 24, TFS(&tfs_set_notset), PCE_RP_RESERVED, + "", HFILL }}, + { &pce_rp_flags_pri, + { "Priority (PRI)", "pce.rp.flags.pri", FT_BOOLEAN, 24, TFS(&tfs_on_off), PCE_RP_PRI, + "", HFILL }}, + { &pce_rp_flags_r, + { "Reoptimization (R)", "pce.rp.flags.r", FT_BOOLEAN, 24, TFS(&tfs_set_notset), PCE_RP_R, + "", HFILL }}, + { &pce_rp_flags_b, + { "Bi-directional (L)", "pce.rp.flags.b", FT_BOOLEAN, 24, TFS(&tfs_set_notset), PCE_RP_B, + "", HFILL }}, + { &pce_rp_flags_o, + { "Strict/Loose (L)", "pce.rp.flags.o", FT_BOOLEAN, 24, TFS(&tfs_set_notset), PCE_RP_O, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_NO_PATH], + { "PCE NO PATH OBJECT Body", "pce.obj.nopath", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + { &pce_no_path_flags_c, + { "C", "pce.no.path.flags.c", FT_BOOLEAN, 16, TFS(&tfs_set_notset), PCE_NO_PATH_C, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_END_POINT], + { "PCE END POINT OBJECT Body", "pce.obj.endpoint", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_BANDWIDTH], + { "PCE BANDWIDTH OBJECT Body", "pce.obj.bandwidth", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_METRIC], + { "PCE METRIC OBJECT Body", "pce.obj.metric", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + { &pce_metric_flags_c, + { "Cost (C)", "pce.metric.flags.c", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_METRIC_C, + "", HFILL }}, + { &pce_metric_flags_b, + { "Bound (B)", "pce.metric.flags.b", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_METRIC_B, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_EXPLICIT_ROUTE], + { "PCE EXPLICIT ROUTE OBJECT (ERO) Body", "pce.obj.ero", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_RECORD_ROUTE], + { "PCE RECORD ROUTE OBJECT (RRO) Body", "pce.obj.rro", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_LSPA], + { "PCE LSPA OBJECT Body", "pce.obj.lspa", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + { &pce_lspa_flags_l, + { "Local Protection Desired (L)", "pce.lspa.flags.l", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_LSPA_L, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_IRO], + { "PCE IRO OBJECT Body", "pce.obj.iro", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_SVEC], + { "PCE SVEC OBJECT Body", "pce.obj.svec", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + + { &pce_svec_flags_l, + { "Link diverse (L)", "pce.svec.flags.l", FT_BOOLEAN, 24, TFS(&tfs_set_notset), PCE_SVEC_L, + "", HFILL }}, + + { &pce_svec_flags_n, + { "Node diverse (N)", "pce.svec.flags.n", FT_BOOLEAN, 24, TFS(&tfs_set_notset), PCE_SVEC_N, + "", HFILL }}, + + { &pce_svec_flags_s, + { "SRLG diverse (S)", "pce.svec.flags.s", FT_BOOLEAN, 24, TFS(&tfs_set_notset), PCE_SVEC_S, + "", HFILL }}, + + {&pce_filter[PCEF_OBJ_NOTIFICATION], + { "PCE NOTIFICATION OBJECT Body", "pce.obj.notification", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + + {&pce_filter[PCEF_NOTI_TYPE], + { "Notification Value", "pce.notification.value1", FT_UINT32, BASE_DEC, VALS(pce_notification_types_vals), 0x0, + "", HFILL }}, + {&pce_filter[PCEF_NOTI_VAL1], + { "Notification Type", "pce.notification.type2", FT_UINT32, BASE_DEC, VALS(pce_notification_values1_vals), 0x0, + "", HFILL }}, + {&pce_filter[PCEF_NOTI_VAL2], + { "Notification Type", "pce.notification.type", FT_UINT32, BASE_DEC, VALS(pce_notification_values2_vals), 0x0, + "", HFILL }}, + + {&pce_filter[PCEF_OBJ_PCEP_ERROR], + { "PCE ERROR OBJECT Body", "pce.obj.error", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_ERROR_TYPE], + { "Error-Type", "pce.error.type", FT_UINT8, BASE_DEC, VALS(pce_error_types_obj_vals), 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_LOAD_BALANCING], + { "PCE LOAD BALANCING OBJECT Body", "pce.obj.load.balancing", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_CLOSE], + { "PCE CLOSE OBJECT Body", "pce.obj.close", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_NO_DEF], + { "NO DEFINED OBJECT", "pce.obj.no.defined", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_OBJ_XRO], + { "PCE EXCLUDE ROUTE OBJECT (XRO) Body", "pce.obj.xro", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + + /*SUbobjects*/ + {&pce_filter[PCEF_SUBOBJ], + { "Type", "pce.subobj", FT_UINT8, BASE_DEC, VALS(pce_subobj_vals), 0x0, + "", HFILL }}, + + {&pce_filter[PCEF_SUBOBJ_IPv4], + { "SUBOBJECT: IPv4 Prefix", "pce.subobj.ipv4", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_SUBOBJ_IPv6], + { "SUBOBJECT: IPv6 Prefix", "pce.subobj.ipv6", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_SUBOBJ_LABEL_CONTROL], + { "SUBOBJECT: Label Control", "pce.subobj.label.control", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_SUBOBJ_UNNUM_INTERFACEID], + { "SUBOBJECT: Unnumbered Interface ID", "pce.subobj.unnum.interfaceid", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_SUBOBJ_AUTONOMOUS_SYS_NUM], + { "SUBOBJECT: Autonomous System Number", "pce.subobj.auntonomus.sys.num", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_SUBOBJ_SRLG], + { "SUBOBJECT: SRLG", "pce.subobj.srlg", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_SUBOBJ_EXRS], + { "SUBOBJECT: EXRS", "pce.subobj.exrs", FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL }}, + {&pce_filter[PCEF_SUBOBJ_XRO], + + { "Type", "pce.subobj.label", FT_UINT32, BASE_DEC, VALS(pce_subobj_xro_vals), 0x0, + "", HFILL }}, + { &pce_xro_flags_f, + { "Fail (F)", "pce.xro.flags.f", FT_BOOLEAN, 16, TFS(&tfs_set_notset), PCE_XRO_F, + "", HFILL }}, + {&pce_filter[PCEF_SUB_XRO_ATRIB], + { "Attribute", "pce.xro.sub.atribute", FT_UINT32, BASE_DEC, VALS(pce_xro_atribute_obj_vals), 0x0, + "", HFILL }}, + + { &pce_subobj_flags_lpa, + { "Local Protection Available", "pce.subobj.flags.lpa", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_SUB_LPA, + "", HFILL }}, + { &pce_subobj_flags_lpu, + { "Local protection in Use", "pce.subobj.flags.lpu", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_SUB_LPU, + "", HFILL }}, + { &pce_subobj_label_flags_gl, + { "Global Label", "pce.subobj.label.flags.gl", FT_BOOLEAN, 8, TFS(&tfs_set_notset), PCE_SUB_LABEL_GL, + "", HFILL }}, + +}; + + +static void +dissect_pce_tlv(proto_item *ti, proto_tree *pce_obj, tvbuff_t *tvb, int *offset2, gint hdr_obj, gint body_obj_obl, gint obj_length, gint ett_pce_obj, gint *len){ + + proto_tree *tlv; + guint16 tlv_length = 0; + guint16 tlv_type; + int j = 0; + int m = 0; + int padding = 0; + if (obj_length>(hdr_obj+body_obj_obl)){ + + for(j=0; j<(obj_length - (hdr_obj+body_obj_obl)); ){ + m=m+1; + + tlv_type = tvb_get_ntohs(tvb, *offset2+j); + tlv_length = tvb_get_ntohs(tvb, *offset2 + j + 2); + ti = proto_tree_add_text(pce_obj, tvb, *offset2 + j, tlv_length+4, "TLV %u", m); + tlv = proto_item_add_subtree(ti, ett_pce_obj); + proto_tree_add_text(tlv, tvb, *offset2 + j, 2, "Type: %u", tlv_type); + proto_tree_add_text(tlv, tvb, *offset2 + 2 + j, 2, "Length: %u", tlv_length); + proto_tree_add_text(tlv, tvb, *offset2+4+j, tlv_length, "Data: %s", + bytestring_to_str(tvb_get_ptr(tvb, (*offset2) + 4 + j, tlv_length), tlv_length, ' ')); + padding = (4 - (tlv_length % 4)) % 4; + if (padding != 0){ + proto_tree_add_text(tlv, tvb, *offset2+4+j+tlv_length, padding, "Padding: %s", + bytestring_to_str(tvb_get_ptr(tvb, (*offset2) + 4 + j + tlv_length, padding), padding, ' ')); + + } + j=(j + tlv_length + 4 + padding); + } + + *offset2 = (*offset2) + obj_length - (hdr_obj+body_obj_obl); + *len = *len + obj_length - hdr_obj; + + } + else + *len = (*len) + body_obj_obl; + +}; + +/*------------------------------------------------------------------------------ + *SUBOBJECTS + *------------------------------------------------------------------------------*/ +static void +dissect_subobj_ipv4(proto_item *ti, proto_tree *pce_subobj_tree, tvbuff_t *tvb, int *offset2, int *len, int obj_class, gint ett_pce_obj, guint l_and_or_type, guint length){ + + proto_tree *pce_subobj_ipv4; + proto_tree *pce_subobj_ipv4_flags; + guint8 prefix_length; + guint8 resvd; + guint l; + prefix_length = tvb_get_guint8(tvb, *offset2+6); + resvd = tvb_get_guint8(tvb, *offset2+7); + + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_IPv4], tvb, *offset2, length, FALSE); + pce_subobj_ipv4 = proto_item_add_subtree(ti, ett_pce_obj); + + switch(obj_class){ + + case PCE_EXPLICIT_ROUTE_OBJ: + l = (l_and_or_type& Mask_L)>>7; + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2, 1, val_to_str(l, pce_route_l_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_uint(pce_subobj_ipv4, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+2, 4, "IPv4 Address: (%s)", ip_to_str(tvb_get_ptr(tvb, *offset2+2, 4))); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+6, 1, "Prefix Length: %u", prefix_length); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+7, 1, "Padding: 0x%02x", resvd); + break; + + case PCE_RECORD_ROUTE_OBJ: + proto_tree_add_uint(pce_subobj_ipv4, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, l_and_or_type); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+2, 4, "IPv4 Address: (%s)", ip_to_str(tvb_get_ptr(tvb, *offset2+2, 4))); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+6, 1, "Prefix Length: %u", prefix_length); + ti = proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+7, 1, "Flags: 0x%02x ", resvd); + pce_subobj_ipv4_flags = proto_item_add_subtree(ti, ett_pce_obj); + proto_tree_add_boolean(pce_subobj_ipv4_flags, pce_subobj_flags_lpa, tvb, *offset2+7, 1, resvd); + proto_tree_add_boolean(pce_subobj_ipv4_flags, pce_subobj_flags_lpu, tvb, *offset2+7, 1, resvd); + break; + + case PCE_IRO_OBJ: + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2, 1, "l: %x", (l_and_or_type & 0x80)>>7); + proto_tree_add_uint(pce_subobj_ipv4, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+2, 4, "IPv4 Address: (%s)", ip_to_str(tvb_get_ptr(tvb, *offset2+2, 4))); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+6, 1, "Prefix Length: %u", prefix_length); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+7, 1, "Padding: 0x%02x", resvd); + break; + + case PCE_XRO_OBJ: + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2, 1, "X: %x", (l_and_or_type & 0x01)>>7); + proto_tree_add_uint(pce_subobj_ipv4, pce_filter[PCEF_SUBOBJ_XRO], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2, 1, "Type: %u", (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+2, 4, "IPv4 Address: (%s)", ip_to_str(tvb_get_ptr(tvb, *offset2+2, 4))); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+6, 1, "Prefix Length: %u", prefix_length); + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2+7, 1, val_to_str(resvd, pce_xro_atribute_obj_vals, "Unknown Atribute (%u). ")); + break; + + default: + proto_tree_add_text(pce_subobj_ipv4, tvb, *offset2, 8, "Non defined subobject for this object"); + break; + } + + *len = *len + 8; + *offset2 = *offset2 + 8; +} + +static void +dissect_subobj_ipv6(proto_item *ti, proto_tree *pce_subobj_tree, tvbuff_t *tvb, int *offset2, int *len, int obj_class, gint ett_pce_obj, guint l_and_or_type, guint length){ + + proto_tree *pce_subobj_ipv6; + proto_tree *pce_subobj_ipv6_flags; + guint8 prefix_length; + guint8 resv; + int l; + + prefix_length = tvb_get_guint8(tvb, *offset2+18); + resv = tvb_get_guint8(tvb, *offset2+19); + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_IPv6], tvb, *offset2, length, FALSE); + pce_subobj_ipv6 = proto_item_add_subtree(ti, ett_pce_obj); + + switch(obj_class){ + case PCE_EXPLICIT_ROUTE_OBJ: + l = (l_and_or_type& Mask_L)>>7; + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2, 1, val_to_str(l, pce_route_l_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_uint(pce_subobj_ipv6, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+2, 16, "IPv6 Address: %s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, *offset2+2, 16))); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+18, 1, "Prefix Length: %u", prefix_length); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+19, 1, "Padding: 0x%02x", resv); + break; + + case PCE_RECORD_ROUTE_OBJ: + proto_tree_add_uint(pce_subobj_ipv6, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, l_and_or_type); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+2, 16, "IPv6 Address: %s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, *offset2+2, 16))); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+18, 1, "Prefix Length: %u", prefix_length); + ti = proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+19, 1, "Flags: 0x%02x ", resv); + pce_subobj_ipv6_flags = proto_item_add_subtree(ti, ett_pce_obj); + proto_tree_add_boolean(pce_subobj_ipv6_flags, pce_subobj_flags_lpa, tvb, *offset2+19, 1, resv); + proto_tree_add_boolean(pce_subobj_ipv6_flags, pce_subobj_flags_lpu, tvb, *offset2+19, 1, resv); + break; + + case PCE_IRO_OBJ: + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2, 1, "l: %x", (l_and_or_type & 0x80)>>7); + proto_tree_add_uint(pce_subobj_ipv6, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+2, 16, "IPv6 Address: %s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, *offset2+2, 16))); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+18, 1, "Prefix Length: %u", prefix_length); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+19, 1, "Padding: 0x%02x", resv); + break; + + case PCE_XRO_OBJ: + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2, 1, "X: %x", (l_and_or_type & 0x01)>>7); + proto_tree_add_uint(pce_subobj_ipv6, pce_filter[PCEF_SUBOBJ_XRO], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+2, 16, "IPv6 Address: %s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, *offset2+2, 16))); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+18, 1, "Prefix Length: %u", prefix_length); + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2+19, 1, val_to_str(resv, pce_xro_atribute_obj_vals, "Unknown Atribute (%u). ")); + break; + + default: + proto_tree_add_text(pce_subobj_ipv6, tvb, *offset2, 20, "Non defined subobject for this object"); + break; + } + + *len = *len + 20; + *offset2 = *offset2 + 20; + +} + + +static void +dissect_subobj_label_control(proto_item *ti, proto_tree *pce_subobj_tree, tvbuff_t *tvb, int *offset2, int *len, int obj_class, gint ett_pce_obj, guint l_and_or_type, guint length){ + + proto_tree *pce_subobj_label_control; + proto_tree *pce_subobj_label_flags; + guint8 u_reserved; + guint8 c_type; + int l; + int u; + + u_reserved = tvb_get_guint8(tvb, *offset2+2); + c_type = tvb_get_guint8(tvb, *offset2+3); + + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_LABEL_CONTROL], tvb, *offset2, length, FALSE); + pce_subobj_label_control = proto_item_add_subtree(ti, ett_pce_obj); + + switch(obj_class){ + + case PCE_EXPLICIT_ROUTE_OBJ: + l = (l_and_or_type& Mask_L)>>7; + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2, 1, val_to_str(l, pce_route_l_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_uint(pce_subobj_label_control, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+1, 1, "Length: %u", length); + u = (u_reserved & 0x80)>>7; + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+2, 1, val_to_str(u, pce_route_u_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+2, 1, "Reserved: %u", (u_reserved & 0x7f)); + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+3, 1, "C-Type: %u", c_type); + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+4, length-4, "Label: %s", + bytestring_to_str(tvb_get_ptr(tvb, *offset2+4, length-4), length-4, ' ')); + break; + + case PCE_RECORD_ROUTE_OBJ: + proto_tree_add_uint(pce_subobj_label_control, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, l_and_or_type); + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+1, 1, "Length: %u", length); + u = (u_reserved & 0x80)>>7; + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+2, 1, val_to_str(u, pce_route_u_obj_vals, "Unknown Object (%u). ")); + + ti = proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+2, 1, "Flags: 0x%02x ", (u_reserved & 0x7f)); + pce_subobj_label_flags = proto_item_add_subtree(ti, ett_pce_obj); + proto_tree_add_boolean(pce_subobj_label_flags, pce_subobj_label_flags_gl, tvb, *offset2+2, 1, (u_reserved & 0x7f)); + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+3, 1, "C-Type: %u", c_type); + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2+4, length-4, "Label: %s", + bytestring_to_str(tvb_get_ptr(tvb, *offset2+4, length-4), length-4, ' ')); + break; + + default: + proto_tree_add_text(pce_subobj_label_control, tvb, *offset2, length, "Non defined subobject for this object"); + break; + } + + *len = *len + 8; + *offset2 = *offset2 + 8; +} + +static void +dissect_subobj_unnumb_interfaceID(proto_item *ti, proto_tree *pce_subobj_tree, tvbuff_t *tvb, int *offset2, int *len, int obj_class, gint ett_pce_obj, guint l_and_or_type, guint length){ + + proto_tree *pce_subobj_unnumb_interfaceID; + proto_tree *pce_subobj_unnumb_interfaceID_flags; + guint32 router_ID; + guint32 interface_ID; + guint16 reserved_flags; + int l; + + reserved_flags = tvb_get_ntohs(tvb, *offset2+2); + router_ID = tvb_get_ntohl(tvb, *offset2+4); + interface_ID = tvb_get_ntohl(tvb, *offset2+8); + + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_UNNUM_INTERFACEID], tvb, *offset2, length, FALSE); + pce_subobj_unnumb_interfaceID = proto_item_add_subtree(ti, ett_pce_obj); + + switch(obj_class){ + + case PCE_EXPLICIT_ROUTE_OBJ: + l = (l_and_or_type& Mask_L)>>7; + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2, 1, val_to_str(l, pce_route_l_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_uint(pce_subobj_unnumb_interfaceID, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+2, 2, "Reserved: 0x%04x", reserved_flags); + break; + + case PCE_RECORD_ROUTE_OBJ: + proto_tree_add_uint(pce_subobj_unnumb_interfaceID, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, l_and_or_type); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+1, 1, "Length: %u", length); + + ti = proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+2, 2, "Flags: 0x%02x ", (reserved_flags & 0xff00)>>8); + pce_subobj_unnumb_interfaceID_flags = proto_item_add_subtree(ti, ett_pce_obj); + proto_tree_add_boolean(pce_subobj_unnumb_interfaceID_flags, pce_subobj_flags_lpa, tvb, *offset2+2, 1, (reserved_flags & 0xff00)>>8); + proto_tree_add_boolean(pce_subobj_unnumb_interfaceID_flags, pce_subobj_flags_lpu, tvb, *offset2+2, 1, (reserved_flags & 0xff00)>>8); + + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+3, 1, "Reserved: 0x%02x", (reserved_flags & 0x00ff)); + break; + + case PCE_IRO_OBJ: + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2, 1, "l: %x", (l_and_or_type & 0x80)>>7); + proto_tree_add_uint(pce_subobj_unnumb_interfaceID, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+2, 2, "Reserved: 0x%04x", reserved_flags); + break; + + case PCE_XRO_OBJ: + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2, 1, "X: %x", (l_and_or_type & 0x01)>>7); + proto_tree_add_uint(pce_subobj_unnumb_interfaceID, pce_filter[PCEF_SUBOBJ_XRO], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+2, 1, "Reserved: 0x%02x", (reserved_flags & 0xff00)>>4); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+3, 1, val_to_str((reserved_flags & 0x00ff), pce_xro_atribute_obj_vals, "Unknown Atribute (%u). ")); + break; + + default: + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2, 12, "Non defined subobject for this object"); + break; + } + + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+4, 4, "Router ID: 0x%08x", router_ID); + proto_tree_add_text(pce_subobj_unnumb_interfaceID, tvb, *offset2+8, 4, "Interface ID: 0x%08x", interface_ID); + + *offset2 = *offset2 + 12; + *len = *len + 12; + +} + +static void +dissect_subobj_autonomous_sys_num(proto_item *ti, proto_tree *pce_subobj_tree, tvbuff_t *tvb, int *offset2, int *len, int obj_class, guint ett_pce_obj, guint l_and_or_type, guint length){ + + proto_tree *pce_subobj_autonomous_sys_num; + guint16 AS_number; + guint8 reserved; + guint8 attribute; + guint16 op_AS_nu_high_oct; + int l; + l = (l_and_or_type& Mask_L)>>7; + + if(obj_class == PCE_XRO_OBJ){ + reserved = tvb_get_guint8(tvb, *offset2+2); + attribute = tvb_get_guint8(tvb, *offset2+3); + op_AS_nu_high_oct = tvb_get_ntohs(tvb, *offset2+4); + AS_number = tvb_get_ntohs(tvb, *offset2+6); + + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_AUTONOMOUS_SYS_NUM], tvb, *offset2, length, FALSE); + pce_subobj_autonomous_sys_num = proto_item_add_subtree(ti, ett_pce_obj); + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2, 1, "X: %x", (l_and_or_type & 0x01)>>7); + proto_tree_add_uint(pce_subobj_autonomous_sys_num, pce_filter[PCEF_SUBOBJ_XRO], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2+1, 1, "Length: %u", length); + + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2+2, 1, "Reserved: 0x%02x", reserved); + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2+3, 1, val_to_str(attribute, pce_xro_atribute_obj_vals, "Unknown Object (%u).")); + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2+4, 2, "Optional AS Number High Octets: 0x%04x", AS_number); + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2+6, 2, "AS Number: 0x%04x", AS_number); + + *offset2 = *offset2 + 8; + *len = *len + 8; + } + + else{ AS_number = tvb_get_ntohs(tvb, *offset2+2); + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_AUTONOMOUS_SYS_NUM], tvb, *offset2, length, FALSE); + pce_subobj_autonomous_sys_num = proto_item_add_subtree(ti, ett_pce_obj); + + if(obj_class == PCE_IRO_OBJ) + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2, 1, "l: %x", (l_and_or_type & 0x80)>>7); + else + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2, 1, val_to_str(l, pce_route_l_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_uint(pce_subobj_autonomous_sys_num, pce_filter[PCEF_SUBOBJ], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2+1, 1, "Length: %u", length); + proto_tree_add_text(pce_subobj_autonomous_sys_num, tvb, *offset2+2, 2, "AS Number: 0x%04x", AS_number); + + *offset2 = *offset2 + 4; + *len = *len + 4; + } +} + +static void +dissect_subobj_srlg(proto_item *ti, proto_tree *pce_subobj_tree, tvbuff_t *tvb, int *offset2, int *len, guint ett_pce_obj, guint l_and_or_type, guint length){ + + proto_tree *pce_subobj_srlg; + guint32 srlg_id; + guint8 reserved; + guint8 attribute; + + srlg_id = tvb_get_ntohl(tvb, *offset2+2); + reserved = tvb_get_guint8(tvb, *offset2+6); + attribute = tvb_get_guint8(tvb, *offset2+7); + + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_SRLG], tvb, *offset2, length, FALSE); + pce_subobj_srlg = proto_item_add_subtree(ti, ett_pce_obj); + + proto_tree_add_text(pce_subobj_srlg, tvb, *offset2, 1, "X: %x", (l_and_or_type & 0x01)>>7); + proto_tree_add_uint(pce_subobj_srlg, pce_filter[PCEF_SUBOBJ_XRO], tvb, *offset2, 1, (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_srlg, tvb, *offset2+1, 1, "Length: %u", length); + + proto_tree_add_text(pce_subobj_srlg, tvb, *offset2+2, 4, "SRLG ID: 0x%08x", srlg_id); + proto_tree_add_text(pce_subobj_srlg, tvb, *offset2+6, 1, "Reserved: 0x%02x", reserved); + proto_tree_add_text(pce_subobj_srlg, tvb, *offset2+7, 1, val_to_str(attribute, pce_xro_atribute_obj_vals, "Unknown Object (%u).")); + + *offset2 = *offset2 + 8; + *len = *len + 8; + +} + +static void +dissect_subobj_exrs(proto_item *ti, proto_tree *pce_subobj_tree, tvbuff_t *tvb, int *offset2, int *len, int obj_class, guint ett_pce_obj, guint type_iro, guint l_and_or_type, guint length){ + + proto_tree *pce_subobj_exrs; + guint16 reserved; + guint8 l_type; + guint8 length2; + guint type_exrs; + guint offset_exrs = 0; + guint l; + + ti = proto_tree_add_item(pce_subobj_tree, pce_filter[PCEF_SUBOBJ_EXRS], tvb, *offset2, length, FALSE); + pce_subobj_exrs = proto_item_add_subtree(ti, ett_pce_obj); + + l = (l_and_or_type& Mask_L)>>7; + proto_tree_add_text(pce_subobj_exrs, tvb, *offset2, 1, val_to_str(l, pce_route_l_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_text(pce_subobj_exrs, tvb, *offset2, 1, "Type: %u", (l_and_or_type & 0x7f)); + proto_tree_add_text(pce_subobj_exrs, tvb, *offset2+1, 1, "Length: %u", length); + + reserved = tvb_get_ntohs(tvb, *offset2+2); + proto_tree_add_text(pce_subobj_exrs, tvb, *offset2+2, 2, "Reserved: 0x%04x", reserved); + + *len = *len + 4; + *offset2 = *offset2 + 4; + + while(offset_exrs>5); + + ti = proto_tree_add_text(pce_open_obj, tvb, *offset2, 1, "Flags: "); + pce_open_obj_flags = proto_item_add_subtree(ti, ett_pce_obj_open); + + proto_tree_add_boolean(pce_open_obj_flags, pce_open_flags_res, tvb, *offset2, 1, version_flags & 0x1f); + proto_tree_add_text(pce_open_obj, tvb, *offset2+1, 1, "Keepalive: %u", keepalive); + proto_tree_add_text(pce_open_obj, tvb, *offset2+2, 1, "Deadtime: %u", deadtimer); + proto_tree_add_text(pce_open_obj, tvb, *offset2+3, 1, "SID: %u", SID); + + *offset2 = (*offset2) + body_obj_obl; + + dissect_pce_tlv(ti, pce_open_obj, tvb, offset2, hdr_obj, body_obj_obl, obj_length, ett_pce_obj_open, len); + +} + +/*------------------------------------------------------------------------------ + * RP OBJECT + *------------------------------------------------------------------------------*/ +static void +dissect_pce_rp_obj(proto_item *ti, proto_tree *pce_tree, + tvbuff_t *tvb, int *offset2, int obj_length, int *len) +{ + + proto_tree *pce_rp_obj; + proto_tree *pce_rp_obj_flags; + guint8 reserved; + guint32 flags; + guint32 requested_id_number; + guint hdr_obj=4; + guint body_obj_obl=8; + + reserved = tvb_get_guint8(tvb, *offset2); + flags = tvb_get_ntoh24(tvb, *offset2+1); + requested_id_number = tvb_get_ntohl(tvb, *offset2+4); + + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_RP], tvb, *offset2, obj_length-4, FALSE); + pce_rp_obj = proto_item_add_subtree(ti, ett_pce_obj_request_parameters); + + proto_tree_add_text(pce_rp_obj, tvb, *offset2, 1, "Reserved: 0x%02x", reserved); + + ti = proto_tree_add_text(pce_rp_obj, tvb, *offset2+1, 3, "Flags: 0x%06x ", flags); + pce_rp_obj_flags = proto_item_add_subtree(ti, ett_pce_obj_request_parameters); + + proto_tree_add_boolean(pce_rp_obj_flags, pce_rp_flags_reserved, tvb, *offset2+1, 3, flags); + proto_tree_add_boolean(pce_rp_obj_flags, pce_rp_flags_o, tvb, *offset2+1, 3, flags); + proto_tree_add_boolean(pce_rp_obj_flags, pce_rp_flags_b, tvb, *offset2+1, 3, flags); + proto_tree_add_boolean(pce_rp_obj_flags, pce_rp_flags_r, tvb, *offset2+1, 3, flags); + proto_tree_add_boolean(pce_rp_obj_flags, pce_rp_flags_pri, tvb, *offset2+1, 3, flags); + + proto_tree_add_text(pce_rp_obj, tvb, *offset2+4, 4, "Requested ID Number: 0x%08x", requested_id_number); + *offset2 = (*offset2) + body_obj_obl; + + dissect_pce_tlv(ti, pce_rp_obj, tvb, offset2, hdr_obj, body_obj_obl, obj_length, ett_pce_obj_request_parameters, len); + +} + +/*------------------------------------------------------------------------------ + * NO PATH OBJECT + *------------------------------------------------------------------------------*/ +static void +dissect_pce_no_path_obj(proto_item *ti, proto_tree *pce_tree, + tvbuff_t *tvb, int *offset2, int obj_length, int *len) +{ + + proto_tree *pce_no_path_obj; + proto_tree *pce_no_path_obj_flags; + guint8 ni; + guint16 flags; + guint8 reserved; + guint hdr_obj=4; + guint body_obj_obl=4; + + ni = tvb_get_guint8(tvb, *offset2); + flags = tvb_get_ntohs(tvb, *offset2+1); + reserved = tvb_get_guint8(tvb, *offset2+3); + + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_NO_PATH], tvb, *offset2, obj_length-4, FALSE); + pce_no_path_obj = proto_item_add_subtree(ti, ett_pce_obj_no_path); + + proto_tree_add_text(pce_no_path_obj, tvb, *offset2, 1, val_to_str(ni, pce_no_path_obj_vals, "Unknown Object (%u). ")); + + ti = proto_tree_add_text(pce_no_path_obj, tvb, *offset2+1, 2, "Flags: 0x%04x", flags); + pce_no_path_obj_flags = proto_item_add_subtree(ti, ett_pce_obj_no_path); + + proto_tree_add_boolean(pce_no_path_obj_flags, pce_no_path_flags_c, tvb, *offset2+1, 2, flags); + proto_tree_add_text(pce_no_path_obj, tvb, *offset2+3, 1, "Reserved: 0x%02x", reserved); + + *offset2 = (*offset2) + body_obj_obl; + dissect_pce_tlv(ti, pce_no_path_obj, tvb, offset2, hdr_obj, body_obj_obl, obj_length, ett_pce_obj_no_path, len); + +} + +/*------------------------------------------------------------------------------ + * END POINT OBJECT + *------------------------------------------------------------------------------*/ +static void +dissect_pce_end_point_obj(proto_item *ti, proto_tree *pce_tree, + tvbuff_t *tvb, int *offset2, int obj_length, int *len, int type) +{ + proto_tree *pce_end_point_obj; + + switch(type) + { + case IPv4:{ + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_END_POINT], tvb, *offset2, obj_length-4, FALSE); + pce_end_point_obj = proto_item_add_subtree(ti, ett_pce_obj_end_point); + + proto_tree_add_text(pce_end_point_obj, tvb, *offset2, 4, "Source IPv4 Address: (%s)", ip_to_str(tvb_get_ptr(tvb, *offset2, 4))); + proto_tree_add_text(pce_end_point_obj, tvb, *offset2+4, 4, "Destination IPv4 Address: (%s)", ip_to_str(tvb_get_ptr(tvb, *offset2+4, 4))); + + *len = *len + 8; + + break; + + } + case IPv6:{ + + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_END_POINT], tvb, *offset2, obj_length-4, FALSE); + pce_end_point_obj = proto_item_add_subtree(ti, ett_pce_obj_end_point); + + proto_tree_add_text(pce_end_point_obj, tvb, *offset2, 16, "Source IPv6 Address: %s", + ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, *offset2, 16))); + proto_tree_add_text(pce_end_point_obj, tvb, *offset2+16, 16, "Destination IPv6 Address: %s", + ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, *offset2+16, 16))); + + *len = *len + 32; + + break; + + } + default: + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_END_POINT], tvb, *offset2, obj_length-4, FALSE); + pce_end_point_obj = proto_item_add_subtree(ti, ett_pce_obj_end_point); + proto_tree_add_text(pce_end_point_obj, tvb, *offset2, 1, "UNKNOWN Type Object (%u)", type); + break; + + } + +} + + + +/*------------------------------------------------------------------------------ + * BANDWIDTH OBJECT + *------------------------------------------------------------------------------*/ +static void +dissect_pce_bandwidth_obj(proto_item *ti, proto_tree *pce_tree, tvbuff_t *tvb, int *offset2, int obj_length, int *len) + { + proto_tree *pce_bandwidth_obj; + guint32 bandwidth; + + bandwidth = tvb_get_ntohl(tvb, *offset2); + + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_BANDWIDTH], tvb, *offset2, obj_length-4, FALSE); + pce_bandwidth_obj = proto_item_add_subtree(ti, ett_pce_obj_bandwidth); + proto_tree_add_text(pce_bandwidth_obj, tvb, *offset2, 4, "Bandwidth: 0x%x", bandwidth); + + *len = *len + 8; + +} + +/*------------------------------------------------------------------------------ + * METRIC OBJECT + *------------------------------------------------------------------------------*/ +static void +dissect_pce_metric_obj(proto_item *ti, proto_tree *pce_tree, + tvbuff_t *tvb, int *offset2, int obj_length, int *len) + { + + proto_tree *pce_metric_obj; + proto_tree *pce_metric_obj_flags; + guint16 reserved; + guint8 flags; + guint8 metric_type; + guint32 metric_value; + + reserved = tvb_get_ntohs(tvb, *offset2); + flags = tvb_get_guint8(tvb, *offset2+2); + metric_type = tvb_get_guint8(tvb, *offset2+3); + metric_value = tvb_get_ntohl(tvb, *offset2+4); + + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_METRIC], tvb, *offset2, obj_length-4, FALSE); + pce_metric_obj = proto_item_add_subtree(ti, ett_pce_obj_metric); + + proto_tree_add_text(pce_metric_obj, tvb, *offset2, 2, "Reserved: %u", reserved); + + ti = proto_tree_add_text(pce_metric_obj, tvb, *offset2+2, 1, "Flags: 0x%02x", flags); + pce_metric_obj_flags = proto_item_add_subtree(ti, ett_pce_obj_metric); + + proto_tree_add_boolean(pce_metric_obj_flags, pce_metric_flags_c, tvb, *offset2+2, 1, flags); + proto_tree_add_boolean(pce_metric_obj_flags, pce_metric_flags_b, tvb, *offset2+2, 1, flags); + proto_tree_add_text(pce_metric_obj, tvb, *offset2+3, 1, val_to_str(metric_type, pce_metric_obj_vals, "Unknown Object (%u). ")); + proto_tree_add_text(pce_metric_obj, tvb, *offset2+4, 4, "Metric Value: 0x%x", metric_value); + + *len = *len + 8; +} + +/*------------------------------------------------------------------------------ + * EXPLICIT ROUTE OBJECT (ERO) + *------------------------------------------------------------------------------*/ +static void +dissect_pce_explicit_route_obj(proto_item *ti, proto_tree *pce_tree, + tvbuff_t *tvb, int *offset2, int obj_length, int obj_class, int *len, int *msg_length) +{ + proto_tree *pce_explicit_route_obj; + guint8 l_type; + guint8 length; + guint type_exp_route; + guint body_obj_len; + body_obj_len = obj_length - 4; + + ti = proto_tree_add_item(pce_tree, pce_filter[PCEF_OBJ_EXPLICIT_ROUTE], tvb, *offset2, obj_length-4, FALSE); + pce_explicit_route_obj = proto_item_add_subtree(ti, ett_pce_obj_explicit_route); + + while(body_obj_len){ + + l_type = tvb_get_guint8(tvb, *offset2); + length = tvb_get_guint8(tvb, *offset2+1); + type_exp_route = (l_type & Mask_Type); + if (body_obj_len >4; + + ti = proto_tree_add_text(pce_tree, tvb, offset, 4, "PCE %s Header", val_to_str(obj_class, pce_class_vals, "Unknown Message (%u). ")); + pce_object_tree = proto_item_add_subtree(ti, ett_pce_obj_hdr); + + proto_tree_add_text(pce_object_tree, tvb, offset+1, 1, "Object Type: %u", type); + + ti = proto_tree_add_text(pce_object_tree, tvb, offset+1, 1, "Flags"); + pce_header_obj_flags = proto_item_add_subtree(ti, ett_pce_hdr); + proto_tree_add_boolean(pce_header_obj_flags, pce_hdr_obj_flags_reserved, tvb, offset+1, 1, ot_res_p_i); + proto_tree_add_boolean(pce_header_obj_flags, pce_hdr_obj_flags_p, tvb, offset+1, 1, ot_res_p_i); + proto_tree_add_boolean(pce_header_obj_flags, pce_hdr_obj_flags_i, tvb, offset+1, 1, ot_res_p_i); + + if (obj_length < 4) { + proto_tree_add_text(pce_object_tree, tvb, offset+2, 2, "Length: %u (bogus, must be >= 4)", obj_length); + break; + } + + proto_tree_add_text(pce_object_tree, tvb, offset+2, 2, "Object Length: %u", obj_length); + proto_tree_add_uint(pce_object_tree, pce_filter[PCEF_OBJECT], tvb, offset, 1, obj_class); + + offset2 = offset+4; + len = len + 4; + + switch(obj_class) { + + case PCE_OPEN_OBJ: + dissect_pce_open_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_RP_OBJ: + dissect_pce_rp_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_NO_PATH_OBJ: + dissect_pce_no_path_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_END_POINT_OBJ: + dissect_pce_end_point_obj(ti, pce_tree, tvb, &offset2, obj_length, &len, type); + break; + + case PCE_BANDWIDTH_OBJ: + dissect_pce_bandwidth_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_METRIC_OBJ: + dissect_pce_metric_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_EXPLICIT_ROUTE_OBJ: + dissect_pce_explicit_route_obj(ti, pce_tree, tvb, &offset2, obj_length, obj_class, &len, &msg_length); + break; + + case PCE_RECORD_ROUTE_OBJ: + dissect_pce_record_route_obj(ti, pce_tree, tvb, &offset2, obj_length, obj_class, &len, &msg_length); + break; + + case PCE_LSPA_OBJ: + dissect_pce_lspa_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_IRO_OBJ: + dissect_pce_iro_obj(ti, pce_tree, tvb, &offset2, obj_length, obj_class, &len, &msg_length); + break; + + case PCE_SVEC_OBJ: + dissect_pce_svec_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_NOTIFICATION_OBJ: + dissect_pce_notification_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_PCEP_ERROR_OBJ: + dissect_pce_error_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_LOAD_BALANCING_OBJ: + dissect_pce_balancing_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_CLOSE_OBJ: + dissect_pce_close_obj(ti, pce_tree, tvb, &offset2, obj_length, &len); + break; + + case PCE_XRO_OBJ: + dissect_pce_xro_obj(ti, pce_tree, tvb, &offset2, obj_length, obj_class, &len, &msg_length); + break; + + default: + ti = proto_tree_add_text(pce_tree, tvb, offset2, obj_length-4, "PCE Object BODY non defined (%u)", type); + break; + + } + + offset += obj_length; + } +} + + +/*------------------------------------------------------------------------------ + * Dissect a single PCE message in a tree + *------------------------------------------------------------------------------*/ +static void +dissect_pce_msg_tree(tvbuff_t *tvb, proto_tree *tree, guint tree_mode, packet_info *pinfo) +{ + proto_tree *pce_tree = NULL; + proto_tree *pce_header_tree; + proto_tree *ti; + proto_tree *pce_header_msg_flags; + + int offset = 0; + int len=0; + guint8 ver_flags; + guint8 message_type; + guint16 msg_length; + + ver_flags = tvb_get_guint8(tvb, 0); + message_type = tvb_get_guint8(tvb, 1); + msg_length = tvb_get_ntohs(tvb, 2); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(message_type, message_type_vals, "Unknown Message (%u). ")); + } + + ti = proto_tree_add_item(tree, proto_pce, tvb, offset, msg_length, FALSE); + pce_tree = proto_item_add_subtree(ti, tree_mode); + + proto_item_append_text(pce_tree, ": "); + proto_item_append_text(pce_tree, "Path Computation Element communication protocol"); + + ti = proto_tree_add_text(pce_tree, tvb, offset, 4, "PCE %s Header", val_to_str(message_type, message_type_vals, "Unknown Message (%u). ")); + + pce_header_tree = proto_item_add_subtree(ti, ett_pce_hdr); + + proto_tree_add_text(pce_header_tree, tvb, offset, 1, "PCE Version: %x", (ver_flags & 0x20)>>5); + + ti = proto_tree_add_text(pce_header_tree, tvb, offset, 1, "Flags: "); + pce_header_msg_flags = proto_item_add_subtree(ti, ett_pce_hdr); + proto_tree_add_boolean(pce_header_msg_flags, pce_hdr_msg_flags_reserved, tvb, offset, 1, (ver_flags & 0x1f)); + proto_tree_add_uint(pce_header_tree, pce_filter[PCEF_MSG], tvb, offset+1, 1, message_type); + proto_tree_add_text(pce_header_tree, tvb, offset+2, 2, "Message length: %u", msg_length); + + switch (PCEF_MSG + message_type) { + + case PCEF_OPEN: + case PCEF_KEEPALIVE: + case PCEF_PATH_COMPUTATION_REQUEST: + case PCEF_PATH_COMPUTATION_REPLY: + case PCEF_NOTIFICATION: + case PCEF_ERROR: + case PCEF_CLOSE: + + proto_tree_add_boolean_hidden(pce_header_tree, pce_filter[PCEF_MSG + message_type], tvb, offset+1, 1, 1); + break; + + default: + proto_tree_add_protocol_format(pce_header_tree, proto_malformed, tvb, offset+1, 1, "Invalid message type: %u", message_type); + return; + } + + offset = 4; + len = 4; + + dissect_pce_obj_tree(ti, tvb, pce_tree, len, offset, msg_length); +} + + +static guint +get_pce_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) +{ + guint16 plen; + + /* Get the length of the PCE packet.*/ + plen = tvb_get_ntohs(tvb, offset+2); + + return plen; +} + +static void +dissect_pce_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + +/* Set up structures needed to add the protocol subtree and manage it */ + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PCE"); + + /* Clear out stuff in the info column */ + if(check_col(pinfo->cinfo,COL_INFO)) + col_clear(pinfo->cinfo,COL_INFO); + + if (tree) { + dissect_pce_msg_tree(tvb, tree, ett_pce, pinfo); + } + +}; + + +static void +dissect_pce(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4, get_pce_message_len, + dissect_pce_pdu); +} + +/*Register le protocol with wireshark*/ +void +proto_register_pce(void){ + +/*Register the protocol name and description*/ + proto_pce = proto_register_protocol ( + "PCE Protocol", /* name*/ + "PCE", /* short name */ + "pce" /* abbrev*/); + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_pce, pcef_info, array_length(pcef_info)); + proto_register_subtree_array(ett, array_length(ett)); + pce_dissector_table = register_dissector_table("pce.proto", "PCE Protocol", FT_UINT8, BASE_DEC); + +} + +/*Dissector Handoff*/ +void +proto_reg_handoff_pce(void) +{ + + dissector_handle_t pce_handle; + pce_handle = create_dissector_handle(dissect_pce, proto_pce); + dissector_add("tcp.port", TCP_PORT_PPCE, pce_handle); + data_handle = find_dissector("data"); + +} + + + + + + + + + + + + + + + +